signal-1.4.6/0000755000000000000000000000000014673270174007740 5ustar00signal-1.4.6/COPYING0000644000000000000000000010451514673270174011001 0ustar00 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 . signal-1.4.6/DESCRIPTION0000644000000000000000000000055214673270174011450 0ustar00Name: signal Version: 1.4.6 Date: 2024-09-20 Author: various authors Maintainer: Mike Miller Title: Signal Processing Description: Signal processing tools, including filtering, windowing and display functions. Depends: octave (>= 3.8), control (>= 2.4) Autoload: no License: GPLv3+, public domain Url: https://octave.sourceforge.io/signal/ signal-1.4.6/INDEX0000644000000000000000000000403514673270174010534 0ustar00signal >> Signal processing Signals buffer chirp cmorwavf diric gauspuls gmonopuls mexihat meyeraux morlet pulstran rectpuls sawtooth shanwavf shiftdata sigmoid_train specgram square tripuls udecode uencode unshiftdata vco Signal Measurement findpeaks peak2peak peak2rms rms rssq Correlation and Convolution cconv convmtx wconv xcorr xcorr2 xcov Filtering filtfilt filtic medfilt1 movingrms sgolayfilt sosfilt Filter Analysis filternorm filtord freqs freqs_plot fwhm grpdelay impz isallpass ismaxphase isminphase isstable phasez zplane Filter Conversion polystab residued residuez sos2ss sos2tf sos2zp ss2tf ss2zp tf2sos tf2ss tf2zp zp2sos zp2ss zp2tf IIR Filter Design besselap besself bilinear buttap butter buttord cheb cheb1ap cheb1ord cheb2ap cheb2ord cheby1 cheby2 ellip ellipap ellipord iirlp2mb impinvar invimpinvar firpm firpmord ncauer pei_tseng_notch sftrans FIR Filter Design cl2bp fir1 fir2 firls kaiserord qp_kaiser remez sgolay Transforms bitrevorder cceps cplxreal czt dct dct2 dctmtx dftmtx digitrevorder dst dwt fht fwht hilbert idct idct2 idst ifht ifwht rceps Power Spectrum Analysis ar_psd cohere cpsd csd db2pow mscohere pburg pow2db pwelch pyulear tfe tfestimate __power Window Functions barthannwin blackmanharris blackmannuttall bohmanwin boxcar chebwin expwin flattopwin gaussian gausswin hann kaiser nuttallwin parzenwin poisswin rectwin taylorwin triang tukeywin ultrwin welchwin window System Identification arburg aryule invfreq invfreqs invfreqz levinson lpc Sample Rate Change data2fun decimate downsample interp resample upfirdn upsample Pulse Metrics statelevels Utility buffer clustersegment fracshift marcumq primitive sampled2continuous schtrig upsamplefill wkeep wrev zerocrossing signal-1.4.6/NEWS0000644000000000000000000002334614673270174010447 0ustar00Summary of important user-visible changes for signal 1.4.6: ---------------------------------------------------------- ** Minor bug fixes and documentation improvements have been made to the following functions: cheb1ap cl2bp decimate firpm pwelch residuez ** The following new functions have been added to the signal package: poisswin taylorwin Summary of important user-visible changes for signal 1.4.5: ---------------------------------------------------------- ** Added qt documentation ** Minor bug fixes and documentation improvements have been made to the following functions: db2pow findpeaks filtfilt firmpm sos2zp vco ** The following new functions have been added to the signal package: filtord filternorm isallpass ismaxphase isminphase phasez statelevels Summary of important user-visible changes for signal 1.4.4: ---------------------------------------------------------- ** Minor bug fixes and documentation improvements have been made to the following functions: sos2tf xcorr xcov zp2sos ** The following new functions have been added to the signal package: firpm firpmord istable lpc vco Summary of important user-visible changes for signal 1.4.3: ---------------------------------------------------------- ** Minor bug fixes and documentation improvements have been made to the following functions: fir2 remez residuez sos2tf sos2zp xcorr zp2sos Summary of important user-visible changes for signal 1.4.2: ---------------------------------------------------------- ** The compiled functions have been made compatible with recent changes in the development version of Octave. ** Minor bug fixes and documentation improvements have been made to the following functions: cplxreal cheb2ap buffer data2fun ss2zp clustersegmen ncauer cohere csd pburg pwelch pyulear tfe invfreq invfreqs invfreqz upfirdn ** The following new functions have been added to the signal package: sos2ss Summary of important user-visible changes for signal 1.4.1: ---------------------------------------------------------- ** Build failures introduced in the previous release on BSD and Windows systems have been fixed. ** The compiled functions have been made compatible with recent changes in the development version of Octave. ** Minor bug fixes and documentation improvements have been made to the following functions: butter rceps zplane filtfilt sos2tf filtic tukeywin Summary of important user-visible changes for signal 1.4.0: ---------------------------------------------------------- ** The buttord, cheb1ord, cheb2ord, and ellipord functions now support analog filter design with the "s" option. ** The cheb1ord and cheb2ord functions will now compute the filter order for band-stop or notch filters. ** The medfilt1 function has been completely rewritten to support additional arguments and options and to improve Matlab compatibility. ** The following new functions have been added to the signal package: cconv pow2db udecode db2pow rms uencode peak2peak rssq unshiftdata peak2rms shiftdata ** Other functions that have been changed for smaller bugfixes, increased Matlab compatibility, or performance: bitrevorder ellip primitive buffer findpeaks rectpuls butter fracshift schtrig cheby1 gauspuls sigmoid_train cheby2 gausswin specgram chirp impz square cplxreal invfreqs tripuls data2fun invfreqz digitrevorder marcumq Summary of important user-visible changes for signal 1.3.2: ---------------------------------------------------------- ** The package is no longer dependent on the general package. Summary of important user-visible changes for signal 1.3.1: ---------------------------------------------------------- ** The following window functions now accept a Matlab compatible option to select the periodic variant, useful for FFT applications: blackmanharris hann blackmannuttall nuttallwin ** The following filter design functions have improved and more consistent input parameter validation: buttord cheb2ord cheb1ord ellipord =============================================================================== signal-1.3.0 Release Date: 2014-01-26 Release Manager: Mike Miller =============================================================================== ** The following functions are new: digitrevorder upsamplefill primitive wconv ultrwin ** Several bugs have been fixed in the following functions: ellipord ifwht findpeaks remez fir1 resample fwht schtrig grpdelay zp2sos ** Replaced line continuation marker "\" by "..." to avoid deprecated syntax warning in Octave 3.8. ** The signal package now depends on Octave 3.8 or newer. The `ellipke' function is required, which used to be provided by the specfun package. Consequently, the signal package no longer depends on specfun. =============================================================================== signal-1.2.2 Release Date: 2013-03-25 Release Manager: Mike Miller =============================================================================== ** No change release to correct bad file permissions on previous release. =============================================================================== signal-1.2.1 Release Date: 2013-03-17 Release Manager: Mike Miller =============================================================================== ** The following functions are new: buttap cheb1ap cheb2ap ellipap findpeaks fwht ifwht ** Improved Matlab compatibility for the following window functions: barthannwin blackmanharris blackmannuttall chebwin flattopwin nuttallwin The changes include always returning a column vector, returning a valid window for a length argument of 1, and making all arguments after the length optional. ** Minor updates to documentation for the following functions: cpsd mscohere sos2tf sos2zp tfestimate zp2sos ** signal is no longer dependent on the optim package. =============================================================================== signal-1.2.0 Release Date: 2012-09-21 Release Manager: Carnë Draug =============================================================================== ** Improved Matlab compability for the function `fir2'. This changes include always returning vaues in a row (even when the smoothing window is a single column), the default values for grid_n and ramp_n, and returning an error when invalid values are used (instead of silently adjusting them). ** Fixed failing tests for the following functions: fir1 pei_tseng_notch residued ** The function `rceps' was fixed to work correctly with odd-length inputs. ** Bugfix in `xcorr2' introduced in 1.1.2 that would not accept "none" as scale option. ** `xcorr2' scaling option "coeff" was changed to return the normalized cross-correlation. ** The following functions are new: movingrms schtrig clustersegment ** signal is no longer dependent on the image package. ** signal is now dependent on the general package. =============================================================================== signal-1.1.3 Release Date: 2012-05-12 Release Manager: Carnë Draug =============================================================================== ** signal is no longer dependent on the audio package. ** signal is now dependent on the image package. ** The function `marcumq' was imported from the communications package and has been completely rewritten to improve performance and fix computational errors. ** Package is no longer automatically loaded. ** The functions `__ellip_ws' and `__ellip_ws_min' have been removed (they are now subfunctions of `ncauer'. ** The function `blackmanharris' was fixed to have even symmetry. =============================================================================== signal-1.1.2 Release Date: 2012-01-06 Release Manager: Lukas Reichlin =============================================================================== * Added the following filter conversion functions: ss2tf ss2zp tf2ss tf2zp zp2ss zp2tf =============================================================================== signal-1.1.1 Release Date: 2011-11-06 Release Manager: Juan Pablo Carbajal =============================================================================== * Following function now show help text correctly instead of copyright notice: downsample dst flattopwin fwhm idst square upsample * Apply pathc by Paul Dreik to cl2bp_lib.h. =============================================================================== signal-1.1.0 Release Date: 2011-11-04 Release Manager: Juan Pablo Carbajal =============================================================================== * Minor bug fixes in: blackmannuttall.m xcorr.m filtfilt.m invfreq.m invfreqs.m resample.m * New functions added: data2fun.m impinvar.m invimpinvar.m sigmoid_train.m pei_tseng_notch.m iirlp2mb.m * Not implemented functions removed from the documentation. * All demos are now working! signal-1.4.6/doc/0000755000000000000000000000000014673270174010505 5ustar00signal-1.4.6/doc/functions.texi0000644000000000000000000064320414673270174013421 0ustar00@c --------------------------------------------------- @node Signals @section Signals @cindex Signals @c Signals buffer @c ----------------------------------------- @subsection buffer @cindex buffer @deftypefn {Function File} {@var{y} =} buffer (@var{x}, @var{n}, @var{p}, @var{opt}) @deftypefnx {Function File} {[@var{y}, @var{z}, @var{opt}] =} buffer (@dots{}) Buffer a signal into a data frame. The arguments to @code{buffer} are @table @asis @item @var{x} The data to be buffered. @item @var{n} The number of rows in the produced data buffer. This is an positive integer value and must be supplied. @item @var{p} An integer less than @var{n} that specifies the under- or overlap between column in the data frame. The default value of @var{p} is 0. @item @var{opt} In the case of an overlap, @var{opt} can be either a vector of length @var{p} or the string 'nodelay'. If @var{opt} is a vector, then the first @var{p} entries in @var{y} will be filled with these values. If @var{opt} is the string 'nodelay', then the first value of @var{y} corresponds to the first value of @var{x}. In the can of an underlap, @var{opt} must be an integer between 0 and @code{-@var{p}}. The represents the initial underlap of the first column of @var{y}. The default value for @var{opt} the vector @code{zeros (1, @var{p})} in the case of an overlap, or 0 otherwise. @end table In the case of a single output argument, @var{y} will be padded with zeros to fill the missing values in the data frame. With two output arguments @var{z} is the remaining data that has not been used in the current data frame. Likewise, the output @var{opt} is the overlap, or underlap that might be used for a future call to @code{code} to allow continuous buffering. @end deftypefn @c Signals chirp @c ----------------------------------------- @subsection chirp @cindex chirp @deftypefn {Function File} {} chirp (@var{t}) @deftypefnx {Function File} {} chirp (@var{t}, @var{f0}) @deftypefnx {Function File} {} chirp (@var{t}, @var{f0}, @var{t1}) @deftypefnx {Function File} {} chirp (@var{t}, @var{f0}, @var{t1}, @var{f1}) @deftypefnx {Function File} {} chirp (@var{t}, @var{f0}, @var{t1}, @var{f1}, @var{shape}) @deftypefnx {Function File} {} chirp (@var{t}, @var{f0}, @var{t1}, @var{f1}, @var{shape}, @var{phase}) Evaluate a chirp signal at time @var{t}. A chirp signal is a frequency swept cosine wave. @table @var @item t vector of times to evaluate the chirp signal @item f0 frequency at time t=0 [ 0 Hz ] @item t1 time t1 [ 1 sec ] @item f1 frequency at time t=t1 [ 100 Hz ] @item shape shape of frequency sweep 'linear' f(t) = (f1-f0)*(t/t1) + f0 'quadratic' f(t) = (f1-f0)*(t/t1)^2 + f0 'logarithmic' f(t) = (f1/f0)^(t/t1) * f0 @item phase phase shift at t=0 @end table For example: @example @group @c doctest: +SKIP specgram (chirp ([0:0.001:5])); # default linear chirp of 0-100Hz in 1 sec specgram (chirp ([-2:0.001:15], 400, 10, 100, "quadratic")); soundsc (chirp ([0:1/8000:5], 200, 2, 500, "logarithmic"), 8000); @end group @end example If you want a different sweep shape f(t), use the following: @verbatim y = cos (2 * pi * integral (f(t)) + phase); @end verbatim @end deftypefn @c Signals cmorwavf @c ----------------------------------------- @subsection cmorwavf @cindex cmorwavf @deftypefn {Function File} {[@var{psi}, @var{x}] =} cmorwavf (@var{lb}, @var{ub}, @var{n}, @var{fb}, @var{fc}) Compute the Complex Morlet wavelet. @end deftypefn @c Signals diric @c ----------------------------------------- @subsection diric @cindex diric @deftypefn {Function File} {@var{y} =} diric (@var{x},@var{n}) Compute the dirichlet function. @xseealso{sinc, gauspuls, sawtooth} @end deftypefn @c Signals gauspuls @c ----------------------------------------- @subsection gauspuls @cindex gauspuls @deftypefn {Function File} {@var{y} =} gauspuls (@var{t}) @deftypefnx {Function File} {@var{y} =} gauspuls (@var{t}, @var{fc}) @deftypefnx {Function File} {@var{y} =} gauspuls (@var{t}, @var{fc}, @var{bw}) Generate a Gaussian modulated sinusoidal pulse sampled at times @var{t}. @xseealso{pulstran, rectpuls, tripuls} @end deftypefn @c Signals gmonopuls @c ----------------------------------------- @subsection gmonopuls @cindex gmonopuls @deftypefn {Function File} {@var{y} =} gmonopuls (@var{t},@var{fc}) Return the gaussian monopulse. @end deftypefn @c Signals mexihat @c ----------------------------------------- @subsection mexihat @cindex mexihat @deftypefn {Function File} {[@var{psi}, @var{x}] =} mexihat (@var{lb}, @var{ub}, @var{n}) Compute the Mexican hat wavelet. @end deftypefn @c Signals meyeraux @c ----------------------------------------- @subsection meyeraux @cindex meyeraux @deftypefn {Function File} {@var{y} =} meyeraux (@var{x}) Compute the Meyer wavelet auxiliary function. @end deftypefn @c Signals morlet @c ----------------------------------------- @subsection morlet @cindex morlet @deftypefn {Function File} {[@var{psi}, @var{x}] =} morlet (@var{lb}, @var{ub}, @var{n}) Compute the Morlet wavelet. @end deftypefn @c Signals pulstran @c ----------------------------------------- @subsection pulstran @cindex pulstran @deftypefn {Function File} {@var{y} =} pulstran (@var{t}, @var{d}, @var{func}, @dots{}) @deftypefnx {Function File} {@var{y} =} pulstran (@var{t}, @var{d}, @var{p}) @deftypefnx {Function File} {@var{y} =} pulstran (@var{t}, @var{d}, @var{p}, @var{Fs}) @deftypefnx {Function File} {@var{y} =} pulstran (@var{t}, @var{d}, @var{p}, @var{Fs}, @var{method}) Generate the signal y=sum(func(t+d,...)) for each d. If d is a matrix of two columns, the first column is the delay d and the second column is the amplitude a, and y=sum(a*func(t+d)) for each d,a. Clearly, func must be a function which accepts a vector of times. Any extra arguments needed for the function must be tagged on the end. Example: @example fs = 11025; # arbitrary sample rate f0 = 100; # pulse train sample rate w = 0.001; # pulse width of 1 millisecond auplot (pulstran (0:1/fs:0.1, 0:1/f0:0.1, "rectpuls", w), fs); @end example If instead of a function name you supply a pulse shape sampled at frequency Fs (default 1 Hz), an interpolated version of the pulse is added at each delay d. The interpolation stays within the the time range of the delayed pulse. The interpolation method defaults to linear, but it can be any interpolation method accepted by the function interp1. Example: @example fs = 11025; # arbitrary sample rate f0 = 100; # pulse train sample rate w = boxcar(10); # pulse width of 1 millisecond at 10 kHz auplot (pulstran (0:1/fs:0.1, 0:1/f0:0.1, w, 10000), fs); @end example @end deftypefn @c Signals rectpuls @c ----------------------------------------- @subsection rectpuls @cindex rectpuls @deftypefn {Function File} {@var{y} =} rectpuls (@var{t}) @deftypefnx {Function File} {@var{y} =} rectpuls (@var{t}, @var{w}) Generate a rectangular pulse over the interval [-@var{w}/2,@var{w}/2), sampled at times @var{t}. This is useful with the function @code{pulstran} for generating a series of pulses. Example: @example @group fs = 11025; # arbitrary sample rate f0 = 100; # pulse train sample rate w = 0.3/f0; # pulse width 3/10th the distance between pulses plot (pulstran (0:1/fs:4/f0, 0:1/f0:4/f0, "rectpuls", w)); @end group @end example @xseealso{gauspuls, pulstran, tripuls} @end deftypefn @c Signals sawtooth @c ----------------------------------------- @subsection sawtooth @cindex sawtooth @deftypefn {Function File} {@var{y} =} sawtooth (@var{t}) @deftypefnx {Function File} {@var{y} =} sawtooth (@var{t}, @var{width}) Generates a sawtooth wave of period @code{2 * pi} with limits @code{+1/-1} for the elements of @var{t}. @var{width} is a real number between @code{0} and @code{1} which specifies the point between @code{0} and @code{2 * pi} where the maximum is. The function increases linearly from @code{-1} to @code{1} in @code{[0, 2 * pi * @var{width}]} interval, and decreases linearly from @code{1} to @code{-1} in the interval @code{[2 * pi * @var{width}, 2 * pi]}. If @var{width} is 0.5, the function generates a standard triangular wave. If @var{width} is not specified, it takes a value of 1, which is a standard sawtooth function. @end deftypefn @c Signals shanwavf @c ----------------------------------------- @subsection shanwavf @cindex shanwavf @deftypefn {Function File} {[@var{psi}, @var{x}] =} shanwavf (@var{lb}, @var{ub}, @var{n}, @var{fb}, @var{fc}) Compute the Complex Shannon wavelet. @end deftypefn @c Signals shiftdata @c ----------------------------------------- @subsection shiftdata @cindex shiftdata @deftypefn {Function File} {[@var{out perm shifts}] =} shiftdata (@var{in}) @deftypefnx {Function File} {[@var{out perm shifts}] =} shiftdata (@var{in}, @var{dim}) Shift data @var{in} to permute the dimension @var{dim} to the first column. @xseealso{unshiftdata} @end deftypefn @c Signals sigmoid_train @c ----------------------------------------- @subsection sigmoid_train @cindex sigmoid_train @deftypefn {Function File} {[@var{y} @var{s}] =} sigmoid_train (@var{t}, @var{ranges}, @var{rc}) Evaluate a train of sigmoid functions at @var{t}. The number and duration of each sigmoid is determined from @var{ranges}. Each row of @var{ranges} represents a real interval, e.g. if sigmoid @code{i} starts at @code{t=0.1} and ends at @code{t=0.5}, then @code{@var{ranges}(i,:) = [0.1 0.5]}. The input @var{rc} is an array that defines the rising and falling time constants of each sigmoid. Its size must equal the size of @var{ranges}. The individual sigmoids are returned in @var{s}. The combined sigmoid train is returned in the vector @var{y} of length equal to @var{t}, and such that @code{Y = max (S)}. Run @code{demo sigmoid_train} to some examples of the use of this function. @end deftypefn @c Signals specgram @c ----------------------------------------- @subsection specgram @cindex specgram @deftypefn {Function File} {} specgram (@var{x}) @deftypefnx {Function File} {} specgram (@var{x}, @var{n}) @deftypefnx {Function File} {} specgram (@var{x}, @var{n}, @var{Fs}) @deftypefnx {Function File} {} specgram (@var{x}, @var{n}, @var{Fs}, @var{window}) @deftypefnx {Function File} {} specgram (@var{x}, @var{n}, @var{Fs}, @var{window}, @var{overlap}) @deftypefnx {Function File} {[@var{S}, @var{f}, @var{t}] =} specgram (@dots{}) Generate a spectrogram for the signal @var{x}. The signal is chopped into overlapping segments of length @var{n}, and each segment is windowed and transformed into the frequency domain using the FFT. The default segment size is 256. If @var{fs} is given, it specifies the sampling rate of the input signal. The argument @var{window} specifies an alternate window to apply rather than the default of @code{hanning (@var{n})}. The argument @var{overlap} specifies the number of samples overlap between successive segments of the input signal. The default overlap is @code{length (@var{window})/2}. If no output arguments are given, the spectrogram is displayed. Otherwise, @var{S} is the complex output of the FFT, one row per slice, @var{f} is the frequency indices corresponding to the rows of @var{S}, and @var{t} is the time indices corresponding to the columns of @var{S}. Example: @example @group x = chirp([0:0.001:2],0,2,500); # freq. sweep from 0-500 over 2 sec. Fs=1000; # sampled every 0.001 sec so rate is 1 kHz step=ceil(20*Fs/1000); # one spectral slice every 20 ms window=ceil(100*Fs/1000); # 100 ms data window specgram(x, 2^nextpow2(window), Fs, window, window-step); ## Speech spectrogram [x, Fs] = auload(file_in_loadpath("sample.wav")); # audio file step = fix(5*Fs/1000); # one spectral slice every 5 ms window = fix(40*Fs/1000); # 40 ms data window fftn = 2^nextpow2(window); # next highest power of 2 [S, f, t] = specgram(x, fftn, Fs, window, window-step); S = abs(S(2:fftn*4000/Fs,:)); # magnitude in range 0= minF & f <= maxF); Then there is the choice of colormap. A brightness varying colormap such as copper or bone gives good shape to the ridges and valleys. A hue varying colormap such as jet or hsv gives an indication of the steepness of the slopes. The final spectrogram is displayed in log energy scale and by convention has low frequencies on the bottom of the image: imagesc(t, f, flipud(log(S(idx,:)))); @end deftypefn @c Signals square @c ----------------------------------------- @subsection square @cindex square @deftypefn {Function File} {@var{s} =} square (@var{t}, @var{duty}) @deftypefnx {Function File} {@var{s} =} square (@var{t}) Generate a square wave of period 2 pi with limits +1/-1. If @var{duty} is specified, it is the percentage of time the square wave is "on". The square wave is +1 for that portion of the time. @verbatim on time * 100 duty cycle = ------------------ on time + off time @end verbatim @xseealso{cos, sawtooth, sin, tripuls} @end deftypefn @c Signals tripuls @c ----------------------------------------- @subsection tripuls @cindex tripuls @deftypefn {Function File} {@var{y} =} tripuls (@var{t}) @deftypefnx {Function File} {@var{y} =} tripuls (@var{t}, @var{w}) @deftypefnx {Function File} {@var{y} =} tripuls (@var{t}, @var{w}, @var{skew}) Generate a triangular pulse over the interval [-@var{w}/2,@var{w}/2), sampled at times @var{t}. This is useful with the function @code{pulstran} for generating a series of pulses. @var{skew} is a value between -1 and 1, indicating the relative placement of the peak within the width. -1 indicates that the peak should be at -@var{w}/2, and 1 indicates that the peak should be at @var{w}/2. The default value is 0. Example: @example @group fs = 11025; # arbitrary sample rate f0 = 100; # pulse train sample rate w = 0.3/f0; # pulse width 3/10th the distance between pulses plot (pulstran (0:1/fs:4/f0, 0:1/f0:4/f0, "tripuls", w)); @end group @end example @xseealso{gauspuls, pulstran, rectpuls} @end deftypefn @c Signals udecode @c ----------------------------------------- @subsection udecode @cindex udecode @deftypefn {Function File} {@var{out} =} udecode (@var{in}, @var{n}) @deftypefnx {Function File} {@var{out} =} udecode (@var{in}, @var{n}, @var{v}) @deftypefnx {Function File} {@var{out} =} udecode (@var{in}, @var{n}, @var{v}, @var{overflows}) Invert the operation of uencode. @xseealso{uencode} @end deftypefn @c Signals uencode @c ----------------------------------------- @subsection uencode @cindex uencode @deftypefn {Function File} {@var{out} =} uencode (@var{in}, @var{n}) @deftypefnx {Function File} {@var{out} =} uencode (@var{in}, @var{n}, @var{v}) @deftypefnx {Function File} {@var{out} =} uencode (@var{in}, @var{n}, @var{v}, @var{signed}) Quantize the entries of the array @var{in} using 2^@var{n} quantization levels. @xseealso{udecode} @end deftypefn @c Signals unshiftdata @c ----------------------------------------- @subsection unshiftdata @cindex unshiftdata @deftypefn {Function File} {[@var{out}] =} unshiftdata (@var{in}, @var{perm}, @var{shifts}) Reverse what is done by shiftdata. @xseealso{shiftdata} @end deftypefn @c Signals vco @c ----------------------------------------- @subsection vco @cindex vco @deftypefn {} {y =} vco (@var{x}, @var{fc}, @var{fs}) @deftypefnx {} {y =} vco (@var{x}, [@var{fmin}, @var{fmax}], @var{fs}) Creates a signal that oscillates at a frequency determined by input @var{x} with a sampling frequency @var{fs}. Inputs: @itemize @item @var{x} - input data with a range of -1 to 1. A value of -1 means no output, 0 cuoreesponds to @var{fc}, and 1 corresponds to 2*@var{fc}. @item @var{fc} - Carrier frequency @item @var{fs} - Sampling rate @item @var{fmin}, @var{fmax} - Frequency modulation range limits. @end itemize Outputs: @itemize @item @var{y} - output signal @end itemize @end deftypefn @c --------------------------------------------------- @node Signal Measurement @section Signal Measurement @cindex Signal Measurement @c Signal Measurement findpeaks @c ----------------------------------------- @subsection findpeaks @cindex findpeaks @deftypefn {Function File} {[@var{pks}, @var{loc}, @var{extra}] =} findpeaks (@var{data}) @deftypefnx {Function File} {@dots{} =} findpeaks (@dots{}, @var{property}, @var{value}) @deftypefnx {Function File} {@dots{} =} findpeaks (@dots{}, @asis{"DoubleSided"}) Finds peaks on @var{data}. Peaks of a positive array of data are defined as local maxima. For double-sided data, they are maxima of the positive part and minima of the negative part. @var{data} is expected to be a single column vector. The function returns the value of @var{data} at the peaks in @var{pks}. The index indicating their position is returned in @var{loc}. The third output argument is a structure with additional information: @table @asis @item "parabol" A structure containing the parabola fitted to each returned peak. The structure has two fields, @asis{"x"} and @asis{"pp"}. The field @asis{"pp"} contains the coefficients of the 2nd degree polynomial and @asis{"x"} the extrema of the interval where it was fitted. @item "height" The estimated height of the returned peaks (in units of @var{data}). @item "baseline" The height at which the roots of the returned peaks were calculated (in units of @var{data}). @item "roots" The abscissa values (in index units) at which the parabola fitted to each of the returned peaks realizes its width as defined below. @end table This function accepts property-value pair given in the list below: @table @asis @item "MinPeakHeight" Minimum peak height (non-negative scalar). Only peaks that exceed this value will be returned. For data taking positive and negative values use the option "DoubleSided". Default value @code{eps}. @item "MinPeakDistance" Minimum separation between (positive integer). Peaks separated by less than this distance are considered a single peak. This distance is also used to fit a second order polynomial to the peaks to estimate their width, therefore it acts as a smoothing parameter. The neighborhood size is equal to the value of @asis{"MinPeakDistance"}. Default value 1. @item "MinPeakWidth" Minimum width of peaks (positive integer). The width of the peaks is estimated using a parabola fitted to the neighborhood of each peak. The width is caulculated with the formula @verbatim a * (width - x0)^2 = 1 @end verbatim where a is the the concavity of the parabola and x0 its vertex. Default value 1. @item "MaxPeakWidth" Maximum width of peaks (positive integer). Default value @code{Inf}. @item "DoubleSided" Tells the function that data takes positive and negative values. The base-line for the peaks is taken as the mean value of the function. This is equivalent as passing the absolute value of the data after removing the mean. @end table Run @command{demo findpeaks} to see some examples. @end deftypefn @c Signal Measurement peak2peak @c ----------------------------------------- @subsection peak2peak @cindex peak2peak @deftypefn {Function File} {@var{y} =} peak2peak (@var{x}) @deftypefnx {Function File} {@var{y} =} peak2peak (@var{x}, @var{dim}) Compute the difference between the maximum and minimum values in the vector @var{x}. If @var{x} is a matrix, compute the difference for each column and return them in a row vector. If the optional argument @var{dim} is given, operate along this dimension. @xseealso{max, min, peak2rms, rms, rssq} @end deftypefn @c Signal Measurement peak2rms @c ----------------------------------------- @subsection peak2rms @cindex peak2rms @deftypefn {Function File} {@var{y} =} peak2rms (@var{x}) @deftypefnx {Function File} {@var{y} =} peak2rms (@var{x}, @var{dim}) Compute the ratio of the largest absolute value to the root-mean-square (RMS) value of the vector @var{x}. If @var{x} is a matrix, compute the peak-magnitude-to-RMS ratio for each column and return them in a row vector. If the optional argument @var{dim} is given, operate along this dimension. @xseealso{max, min, peak2peak, rms, rssq} @end deftypefn @c Signal Measurement rms @c ----------------------------------------- @subsection rms @cindex rms @deftypefn {Function File} {@var{y} =} rms (@var{x}) @deftypefnx {Function File} {@var{y} =} rms (@var{x}, @var{dim}) Compute the root-mean-square (RMS) of the vector @var{x}. The root-mean-square is defined as @tex $$ {\rm rms}(x) = {\sqrt{\sum_{i=1}^N {x_i}^2 \over N}} $$ @end tex @ifnottex @example rms (@var{x}) = SQRT (1/N SUM_i @var{x}(i)^2) @end example @end ifnottex If @var{x} is a matrix, compute the root-mean-square for each column and return them in a row vector. If the optional argument @var{dim} is given, operate along this dimension. @xseealso{mean, meansq, peak2rms, rssq, sumsq} @end deftypefn @c Signal Measurement rssq @c ----------------------------------------- @subsection rssq @cindex rssq @deftypefn {Function File} {@var{y} =} rssq (@var{x}) @deftypefnx {Function File} {@var{y} =} rssq (@var{x}, @var{dim}) Compute the root-sum-of-squares (RSS) of the vector @var{x}. The root-sum-of-squares is defined as @tex $$ {\rm rssq}(x) = {\sqrt{\sum_{i=1}^N {x_i}^2}} $$ @end tex @ifnottex @example rssq (@var{x}) = SQRT (SUM_i @var{x}(i)^2) @end example @end ifnottex If @var{x} is a matrix, compute the root-sum-of-squares for each column and return them in a row vector. If the optional argument @var{dim} is given, operate along this dimension. @xseealso{mean, meansq, sumsq, rms} @end deftypefn @c --------------------------------------------------- @node Correlation and Convolution @section Correlation and Convolution @cindex Correlation and Convolution @c Correlation and Convolution cconv @c ----------------------------------------- @subsection cconv @cindex cconv @deftypefn {Function File} {@var{c} =} cconv (@var{a}, @var{b}, @var{n}) @deftypefnx {Function File} {@var{c} =} cconv (@var{a}, @var{b}) Compute the modulo-N circular convolution. @var{a} and @var{b} are input vectors and @var{c} is the modolo-@var{n} convolution of @var{a} and @var{b}. If @var{n} is not provided, its assumed default value is @code{length(@var{a}) + length(@var{b}) - 1}, which provides the same result as a linear convolution. Examples: @example @group cconv (1:2, 1:4) @result{} 1 4 7 10 8 @end group @end example @example @group cconv (1:2, 1:4, 2) @result{} 16 14 @end group @end example @example @group cconv (1:2, 1:4, 4) @result{} 9 4 7 10 @end group @end example @xseealso{conv, circshift} @end deftypefn @c Correlation and Convolution convmtx @c ----------------------------------------- @subsection convmtx @cindex convmtx @deftypefn {Function File} {} convmtx (@var{a}, @var{n}) If @var{a} is a column vector and @var{x} is a column vector of length @var{n}, then @code{convmtx(@var{a}, @var{n}) * @var{x}} gives the convolution of of @var{a} and @var{x} and is the same as @code{conv(@var{a}, @var{x})}. The difference is if many vectors are to be convolved with the same vector, then this technique is possibly faster. Similarly, if @var{a} is a row vector and @var{x} is a row vector of length @var{n}, then @code{@var{x} * convmtx(@var{a}, @var{n})} is the same as @code{conv(@var{x}, @var{a})}. @end deftypefn @xseealso{conv} @c Correlation and Convolution wconv @c ----------------------------------------- @subsection wconv @cindex wconv @deftypefn {Function File} {@var{y} =} wconv (@var{type}, @var{x}, @var{f}) @deftypefnx {Function File} {@var{y} =} wconv (@var{type}, @var{x}, @var{f}, @var{shape}) 1-D or 2-D convolution. @strong{Inputs} @table @var @item type Type of convolution. @item x Signal vector or matrix. @item f Coefficients of @acronym{FIR} filter. @item shape Shape. @end table @strong{Outputs} @table @var @item y Convoluted signal. @end table @end deftypefn @c Correlation and Convolution xcorr @c ----------------------------------------- @subsection xcorr @cindex xcorr @deftypefn {Function File} {[@var{R}, @var{lag}] =} xcorr ( @var{X} ) @deftypefnx {Function File} {@dots{} =} xcorr ( @var{X}, @var{Y} ) @deftypefnx {Function File} {@dots{} =} xcorr ( @dots{}, @var{maxlag}) @deftypefnx {Function File} {@dots{} =} xcorr ( @dots{}, @var{scale}) Estimates the cross-correlation. Estimate the cross correlation R_xy(k) of vector arguments @var{X} and @var{Y} or, if @var{Y} is omitted, estimate autocorrelation R_xx(k) of vector @var{X}, for a range of lags k specified by argument "maxlag". If @var{X} is a matrix, each column of @var{X} is correlated with itself and every other column. The cross-correlation estimate between vectors "x" and "y" (of length N) for lag "k" is given by @tex $$ R_{xy}(k) = \sum_{i=1}^{N} x_{i+k} \overline{y_i}, $$ @end tex @ifnottex @example @group N R_xy(k) = sum x_@{i+k@} conj(y_i), i=1 @end group @end example @end ifnottex where data not provided (for example x(-1), y(N+1)) is zero. Note the definition of cross-correlation given above. To compute a cross-correlation consistent with the field of statistics, see @command{xcov}. @strong{ARGUMENTS} @table @var @item X [non-empty; real or complex; vector or matrix] data @item Y [real or complex vector] data If @var{X} is a matrix (not a vector), @var{Y} must be omitted. @var{Y} may be omitted if @var{X} is a vector; in this case xcorr estimates the autocorrelation of @var{X}. @item maxlag [integer scalar] maximum correlation lag If omitted, the default value is N-1, where N is the greater of the lengths of @var{X} and @var{Y} or, if @var{X} is a matrix, the number of rows in @var{X}. @item scale [character string] specifies the type of scaling applied to the correlation vector (or matrix). is one of: @table @samp @item none return the unscaled correlation, R, @item biased return the biased average, R/N, @item unbiased return the unbiased average, R(k)/(N-|k|), @item coeff or normalized return the correlation coefficient, R/(rms(x).rms(y)), where "k" is the lag, and "N" is the length of @var{X}. If omitted, the default value is "none". If @var{Y} is supplied but does not have the same length as @var{X}, scale must be "none". @end table @end table @strong{RETURNED VARIABLES} @table @var @item R array of correlation estimates @item lag row vector of correlation lags [-maxlag:maxlag] @end table The array of correlation estimates has one of the following forms: (1) Cross-correlation estimate if @var{X} and @var{Y} are vectors. (2) Autocorrelation estimate if is a vector and @var{Y} is omitted. (3) If @var{X} is a matrix, R is an matrix containing the cross-correlation estimate of each column with every other column. Lag varies with the first index so that R has 2*maxlag+1 rows and P^2 columns where P is the number of columns in @var{X}. If Rij(k) is the correlation between columns i and j of @var{X} @code{R(k+maxlag+1,P*(i-1)+j) == Rij(k)} for lag k in [-maxlag:maxlag], or @code{R(:,P*(i-1)+j) == xcorr(X(:,i),X(:,j))}. @code{reshape(R(k,:),P,P)} is the cross-correlation matrix for @code{X(k,:)}. @xseealso{xcov} @end deftypefn @c Correlation and Convolution xcorr2 @c ----------------------------------------- @subsection xcorr2 @cindex xcorr2 @deftypefn {Function File} {} xcorr2 (@var{a}) @deftypefnx {Function File} {} xcorr2 (@var{a}, @var{b}) @deftypefnx {Function File} {} xcorr2 (@dots{}, @var{scale}) Compute the 2D cross-correlation of matrices @var{a} and @var{b}. If @var{b} is not specified, computes autocorrelation of @var{a}, i.e., same as @code{xcorr (@var{a}, @var{a})}. The optional argument @var{scale}, defines the type of scaling applied to the cross-correlation matrix. Possible values are: @table @asis @item "none" (default) No scaling. @item "biased" Scales the raw cross-correlation by the maximum number of elements of @var{a} and @var{b} involved in the generation of any element of @var{c}. @item "unbiased" Scales the raw correlation by dividing each element in the cross-correlation matrix by the number of products @var{a} and @var{b} used to generate that element. @item "coeff" Scales the normalized cross-correlation on the range of [0 1] so that a value of 1 corresponds to a correlation coefficient of 1. @end table @xseealso{conv2, corr2, xcorr} @end deftypefn @c Correlation and Convolution xcov @c ----------------------------------------- @subsection xcov @cindex xcov @deftypefn {Function File} {[@var{R}, @var{lag}] =} xcov ( @var{X} ) @deftypefnx {Function File} {@dots{} =} xcov ( @var{X}, @var{Y} ) @deftypefnx {Function File} {@dots{} =} xcov ( @dots{}, @var{maxlag}) @deftypefnx {Function File} {@dots{} =} xcov ( @dots{}, @var{scale}) Compute covariance at various lags [=correlation(x-mean(x),y-mean(y))]. @table @var @item X input vector @item Y if specified, compute cross-covariance between X and Y, otherwise compute autocovariance of X. @item maxlag is specified, use lag range [-maxlag:maxlag], otherwise use range [-n+1:n-1]. @item scale: @table @samp @item biased for covariance=raw/N, @item unbiased for covariance=raw/(N-|lag|), @item coeff for covariance=raw/(covariance at lag 0), @item none for covariance=raw @item none is the default. @end table @end table Returns the covariance for each lag in the range, plus an optional vector of lags. @xseealso{xcorr} @end deftypefn @c --------------------------------------------------- @node Filtering @section Filtering @cindex Filtering @c Filtering filtfilt @c ----------------------------------------- @subsection filtfilt @cindex filtfilt @deftypefn {Function File} {@var{y} =} filtfilt (@var{b}, @var{a}, @var{x}) Forward and reverse filter the signal. This corrects for phase distortion introduced by a one-pass filter, though it does square the magnitude response in the process. That's the theory at least. In practice the phase correction is not perfect, and magnitude response is distorted, particularly in the stop band. Example @example @group [b, a]=butter(3, 0.1); # 5 Hz low-pass filter t = 0:0.01:1.0; # 1 second sample x=sin(2*pi*t*2.3)+0.25*randn(size(t)); # 2.3 Hz sinusoid+noise y = filtfilt(b,a,x); z = filter(b,a,x); # apply filter plot(t,x,';data;',t,y,';filtfilt;',t,z,';filter;') @end group @end example @end deftypefn @c Filtering filtic @c ----------------------------------------- @subsection filtic @cindex filtic @deftypefn {Function File} {@var{zf} =} filtic (@var{b}, @var{a}, @var{y}) @deftypefnx {Function File} {@var{zf} =} filtic (@var{b}, @var{a}, @var{y}, @var{x}) Set initial condition vector for filter function The vector zf has the same values that would be obtained from function filter given past inputs x and outputs y The vectors x and y contain the most recent inputs and outputs respectively, with the newest values first: x = [x(-1) x(-2) ... x(-nb)], nb = length(b)-1 y = [y(-1) y(-2) ... y(-na)], na = length(a)-a If length(x) p. By default, p=3 and n=p+2 or n=p+3 if p is even. If @var{f} is given as a matrix, it is expected to be a filter as computed by @code{sgolay}. These filters are particularly good at preserving lineshape while removing high frequency squiggles. Particularly, compare a 5 sample averager, an order 5 butterworth lowpass filter (cutoff 1/3) and sgolayfilt(x, 3, 5), the best cubic estimated from 5 points: @example @group [b, a] = butter (5, 1/3); x = [zeros(1,15), 10*ones(1,10), zeros(1,15)]; plot (sgolayfilt (x), "r;sgolayfilt;", ... filtfilt (ones (1,5)/5, 1, x), "g;5 sample average;", ... filtfilt (b, a, x), "c;order 5 butterworth;", ... x, "+b;original data;"); @end group @end example @xseealso{sgolay} @end deftypefn @c Filtering sosfilt @c ----------------------------------------- @subsection sosfilt @cindex sosfilt @deftypefn {Loadable Function} {@var{y} =} sosfilt (@var{sos}, @var{x}) Second order section IIR filtering of @var{x}. The second order section filter is described by the matrix @var{sos} with: @multitable {col 1} {this is column two} @item @tab [ @var{B1} @var{A1} ]@* @item @var{sos} = @tab [ @dots{} ],@* @item @tab [ @var{BN} @var{AN} ]@* @end multitable where @code{@var{B1} = [b0 b1 b2]} and @code{@var{A1} = [1 a1 a2]} for section 1, etc. The b0 entry must be nonzero for each section. @end deftypefn @c --------------------------------------------------- @node Filter Analysis @section Filter Analysis @cindex Filter Analysis @c Filter Analysis filternorm @c ----------------------------------------- @subsection filternorm @cindex filternorm @deftypefn {Function File} {@var{L} = } filternorm (@var{b}, @var{a}) @deftypefnx {Function File} {@var{L} = } filternorm (@var{b}, @var{a}, @var{pnorm}) @deftypefnx {Function File} {@var{L} = } filternorm (@var{b}, @var{a}, 2, @var{tol}) Compute the 2-norm of a digital filter defined by the numerator coefficients, @var{b}, and the denominator coefficients, @var{a}. It is also possible to compute the infinity-norm by passing inf in the @var{pnorm} parameter. @var{pnorm} only accepts 2 or inf. Example: @example [b, a] = butter (8, 0.5); filternorm (b, a) @end example @end deftypefn @c Filter Analysis filtord @c ----------------------------------------- @subsection filtord @cindex filtord @deftypefn {Function File} {@var{n} = } filtord (@var{b}, @var{a}) @deftypefnx {Function File} {@var{n} = } filtord (@var{sos}) Returns the filter order @var{n} for a filter defined by the numerator coefficients, @var{b}, and the denominator coefficients, @var{a}. It also accepts a filter defined by a matrix of second-order sections, @var{sos}. Example: @example [b, a] = butter (8, 0.5); filtord (b, a) @end example @end deftypefn @c Filter Analysis freqs @c ----------------------------------------- @subsection freqs @cindex freqs @deftypefn {Function File} {@var{h} =} freqs (@var{b}, @var{a}, @var{w}) @deftypefnx {Function File} {} freqs (@var{b}, @var{a}, @var{w}) Compute the s-plane frequency response of the IIR filter B(s)/A(s) as H = polyval(B,j*W)./polyval(A,j*W). If called with no output argument, a plot of magnitude and phase are displayed. Example: @example b = [1 2]; a = [1 1]; w = linspace (0, 4, 128); freqs (b, a, w); @end example @end deftypefn @c Filter Analysis freqs_plot @c ----------------------------------------- @subsection freqs_plot @cindex freqs_plot @deftypefn {Function File} {} freqs_plot (@var{w}, @var{h}) Plot the amplitude and phase of the vector @var{h}. @end deftypefn @c Filter Analysis fwhm @c ----------------------------------------- @subsection fwhm @cindex fwhm @deftypefn {Function File} {@var{f} =} fwhm (@var{y}) @deftypefnx {Function File} {@var{f} =} fwhm (@var{x}, @var{y}) @deftypefnx {Function File} {@var{f} =} fwhm (@dots{}, "zero") @deftypefnx {Function File} {@var{f} =} fwhm (@dots{}, "min") @deftypefnx {Function File} {@var{f} =} fwhm (@dots{}, "alevel", @var{level}) @deftypefnx {Function File} {@var{f} =} fwhm (@dots{}, "rlevel", @var{level}) Compute peak full-width at half maximum (FWHM) or at another level of peak maximum for vector or matrix data @var{y}, optionally sampled as @math{y(x)}. If @var{y} is a matrix, return FWHM for each column as a row vector. The default option "zero" computes fwhm at half maximum, i.e. @math{0.5*max(y)}. The option "min" computes fwhm at the middle curve, i.e. @math{0.5*(min(y)+max(y))}. The option "rlevel" computes full-width at the given relative level of peak profile, i.e. at @math{rlevel*max(y)} or @math{rlevel*(min(y)+max(y))}, respectively. For example, @code{fwhm (@dots{}, "rlevel", 0.1)} computes full width at 10 % of peak maximum with respect to zero or minimum; FWHM is equivalent to @code{fwhm(@dots{}, "rlevel", 0.5)}. The option "alevel" computes full-width at the given absolute level of @var{y}. Return 0 if FWHM does not exist (e.g. monotonous function or the function does not cut horizontal line at @math{rlevel*max(y)} or @math{rlevel*(max(y)+min(y))} or alevel, respectively). @end deftypefn @c Filter Analysis grpdelay @c ----------------------------------------- @subsection grpdelay @cindex grpdelay @deftypefn {Function File} {[@var{g}, @var{w}] =} grpdelay (@var{b}) @deftypefnx {Function File} {[@var{g}, @var{w}] =} grpdelay (@var{b}, @var{a}) @deftypefnx {Function File} {[@var{g}, @var{w}] =} grpdelay (@dots{}, @var{n}) @deftypefnx {Function File} {[@var{g}, @var{w}] =} grpdelay (@dots{}, @var{n}, "whole") @deftypefnx {Function File} {[@var{g}, @var{f}] =} grpdelay (@dots{}, @var{n}, @var{Fs}) @deftypefnx {Function File} {[@var{g}, @var{f}] =} grpdelay (@dots{}, @var{n}, "whole", @var{Fs}) @deftypefnx {Function File} {[@var{g}, @var{w}] =} grpdelay (@dots{}, @var{w}) @deftypefnx {Function File} {[@var{g}, @var{f}] =} grpdelay (@dots{}, @var{f}, @var{Fs}) @deftypefnx {Function File} {} grpdelay (@dots{}) Compute the group delay of a filter. [g, w] = grpdelay(b) returns the group delay g of the FIR filter with coefficients b. The response is evaluated at 512 angular frequencies between 0 and pi. w is a vector containing the 512 frequencies. The group delay is in units of samples. It can be converted to seconds by multiplying by the sampling period (or dividing by the sampling rate fs). [g, w] = grpdelay(b,a) returns the group delay of the rational IIR filter whose numerator has coefficients b and denominator coefficients a. [g, w] = grpdelay(b,a,n) returns the group delay evaluated at n angular frequencies. For fastest computation n should factor into a small number of small primes. [g, w] = grpdelay(b,a,n,'whole') evaluates the group delay at n frequencies between 0 and 2*pi. [g, f] = grpdelay(b,a,n,Fs) evaluates the group delay at n frequencies between 0 and Fs/2. [g, f] = grpdelay(b,a,n,'whole',Fs) evaluates the group delay at n frequencies between 0 and Fs. [g, w] = grpdelay(b,a,w) evaluates the group delay at frequencies w (radians per sample). [g, f] = grpdelay(b,a,f,Fs) evaluates the group delay at frequencies f (in Hz). grpdelay(...) plots the group delay vs. frequency. If the denominator of the computation becomes too small, the group delay is set to zero. (The group delay approaches infinity when there are poles or zeros very close to the unit circle in the z plane.) Theory: group delay, g(w) = -d/dw [arg@{H(e^jw)@}], is the rate of change of phase with respect to frequency. It can be computed as: @example d/dw H(e^-jw) g(w) = ------------- H(e^-jw) @end example where @example H(z) = B(z)/A(z) = sum(b_k z^k)/sum(a_k z^k). @end example By the quotient rule, @example A(z) d/dw B(z) - B(z) d/dw A(z) d/dw H(z) = ------------------------------- A(z) A(z) @end example Substituting into the expression above yields: @example A dB - B dA g(w) = ----------- = dB/B - dA/A A B @end example Note that, @example d/dw B(e^-jw) = sum(k b_k e^-jwk) d/dw A(e^-jw) = sum(k a_k e^-jwk) @end example which is just the FFT of the coefficients multiplied by a ramp. As a further optimization when nfft>>length(a), the IIR filter (b,a) is converted to the FIR filter conv(b,fliplr(conj(a))). For further details, see http://ccrma.stanford.edu/~jos/filters/Numerical_Computation_Group_Delay.html @end deftypefn @c Filter Analysis impz @c ----------------------------------------- @subsection impz @cindex impz @deftypefn {Function File} {[@var{x}, @var{t}] =} impz (@var{b}) @deftypefnx {Function File} {[@var{x}, @var{t}] =} impz (@var{b}, @var{a}) @deftypefnx {Function File} {[@var{x}, @var{t}] =} impz (@var{b}, @var{a}, @var{n}) @deftypefnx {Function File} {[@var{x}, @var{t}] =} impz (@var{b}, @var{a}, @var{n}, @var{fs}) @deftypefnx {Function File} {} impz (@dots{}) Generate impulse-response characteristics of the filter. The filter coefficients correspond to the the z-plane rational function with numerator b and denominator a. If a is not specified, it defaults to 1. If n is not specified, or specified as [], it will be chosen such that the signal has a chance to die down to -120dB, or to not explode beyond 120dB, or to show five periods if there is no significant damping. If no return arguments are requested, plot the results. @xseealso{freqz, zplane} @end deftypefn @c Filter Analysis isallpass @c ----------------------------------------- @subsection isallpass @cindex isallpass @deftypefn {Function File} {@var{L} = } isallpass (@var{b}, @var{a}) @deftypefnx {Function File} {@var{L} = } isallpass (@var{sos}) Determine whether a digital filter is allpass. The filter might be defined by the numerator coefficients, @var{b}, and the denominator coefficients, @var{a}, or, alternatively, by a matrix of second-order sections, @var{sos}. Example: @example a = [1 2 3]; b = [3 2 1]; isallpass (b, a) @end example Ref [1] Shyu, Jong-Jy, & Pei, Soo-Chang, A new approach to the design of complex all-pass IIR digital filters, Signal Processing, 40(2–3), 207–215, 1994. https://doi.org/10.1016/0165-1684(94)90068-x Ref [2] Vaidyanathan, P. P. Multirate Systems and Filter Banks. 1st edition, Pearson College Div, 1992. @end deftypefn @c Filter Analysis ismaxphase @c ----------------------------------------- @subsection ismaxphase @cindex ismaxphase @deftypefn {Function File} {@var{L} = } ismaxphase (@var{b}, @var{a}) @deftypefnx {Function File} {@var{L} = } ismaxphase (@var{sos}) @deftypefnx {Function File} {@var{L} = } ismaxphase (@dots{}, @var{tol}) Determine whether a digital filter is maximum phase (maximum energy-delay). The filter might be defined by the numerator coefficients, @var{b}, and the denominator coefficients, @var{a}, or, alternatively, by a matrix of second-order sections, @var{sos}. A tolerance @var{tol} might be given to define when two numbers are close enough to be considered equal. Example: @example b = [1 2 4 4 2 1]; zplane (b); ismaxphase (b) @end example Ref [1] Oppenheim, Alan, and Ronald Schafer. Discrete-Time Signal Processing. 3rd edition, Pearson, 2009. @end deftypefn @c Filter Analysis isminphase @c ----------------------------------------- @subsection isminphase @cindex isminphase @deftypefn {Function File} {@var{L} = } isminphase (@var{b}, @var{a}) @deftypefnx {Function File} {@var{L} = } isminphase (@var{sos}) @deftypefnx {Function File} {@var{L} = } isminphase (@dots{}, @var{tol}) Determine whether a digital filter is minimum phase. The filter might be defined by the numerator coefficients, @var{b}, and the denominator coefficients, @var{a}, or, alternatively, by a matrix of second-order sections, @var{sos}. A toleranve @var{tol} might be given to define when two numbers are close enough to be considered equal. Example: @example a = [1 0.5]; b = [3 1]; isminphase (b, a) @end example Ref [1] Oppenheim, Alan, and Ronald Schafer. Discrete-Time Signal Processing. 3rd edition, Pearson, 2009. @end deftypefn @c Filter Analysis isstable @c ----------------------------------------- @subsection isstable @cindex isstable @deftypefn {Function File} {@var{FLAG} =} isstable (@var{B}, @var{A}) Returns a logical output equal to TRUE, if the filter is stable. This can be done with coeffients of the filer @var{B} and @var{A}. Alternatively by using a second order sections matrix (SOS). Inputs: @itemize @item @var{B}: Numerator coefficients of the filter @item @var{A}: Denominator coeffients of the filter. Can be an empty vector. @end itemize Output: @itemize @item @var{FLAG}: Returns a logical output, equal to TRUE if the filter is stable. @end itemize Examples: @example b = [1 2 3 4 5 5 1 2]; a = [4 5 6 7 9 10 4 6]; flag = isstable (b, a) flag = 0 @end example Using SOS @example [z, p, k] = butter (6, 0.7, 'high'); sos = zp2sos (z, p, k); flag = isstable (sos) flag = 1 @end example @end deftypefn @c Filter Analysis phasez @c ----------------------------------------- @subsection phasez @cindex phasez @deftypefn {Function File} {[@var{phi}, @var{w}] = } phasez (@var{b}, @var{a}, @var{n}) @deftypefnx {Function File} {[@var{phi}, @var{w}] = } phasez (@var{b}, @var{a}) @deftypefnx {Function File} {[@var{phi}, @var{w}] = } phasez (@var{sos}, @var{n}) @deftypefnx {Function File} {[@var{phi}, @var{w}] = } phasez (@var{sos}) @deftypefnx {Function File} {[@var{phi}, @var{w}] = } phasez (@dots{}, @var{n}, "whole") @deftypefnx {Function File} {[@var{phi}, @var{w}] = } phasez (@dots{}, @var{n}, Fs) @deftypefnx {Function File} {} phasez (@dots{}) Compute the phase response of digital filter defined either by its coefficients (@var{b} and @var{a} are the numerator and denominator coefficients respectively) or by its second-order sections representation, given by the matrix @var{sos}. The output @var{phi} is the phase response computed in a vector the vector of frequencies @var{w}. The phase response is evaluated at @var{n} angular frequencies between 0 and @ifnottex pi. @end ifnottex @tex $\pi$. @end tex @noindent If @var{a} is omitted, the denominator is assumed to be 1 (this corresponds to a simple FIR filter). If @var{n} is omitted, a value of 512 is assumed. If the third/forth argument, @qcode{"whole"}, is given, the response is evaluated at @var{n} angular frequencies between 0 and @ifnottex 2*pi. @end ifnottex @tex $\pi$. @end tex It is possible also to pass the value @qcode{"half"}, which will lead to the default behaviour. Example: @example [b, a] = butter (2, [.15,.3]); phasez (b, a); @end example Ref [1] Oppenheim, Alan, and Ronald Schafer. Discrete-Time Signal Processing. 3rd edition, Pearson, 2009. @xseealso{freqz, phasedelay} @end deftypefn @c Filter Analysis zplane @c ----------------------------------------- @subsection zplane @cindex zplane @deftypefn {Function File} {} zplane (@var{z}, @var{p}) @deftypefnx {Function File} {} zplane (@var{b}, @var{a}) Plot the poles and zeros on a complex plane. If the arguments are column vectors @var{z} and @var{p}, the complex zeros @var{z} and poles @var{p} are displayed. If the arguments are row vectors @var{b} and @var{a}, the zeros and poles of the transfer function represented by these filter coefficients are displayed. If @var{z} and @var{p} are matrices, the columns are distinct sets of zeros and poles and are displayed together in distinct colors. Note that due to the nature of the @code{roots} function, poles and zeros may be displayed as occurring around a circle rather than at a single point. The transfer function is @example @group B(z) b0 + b1 z^(-1) + b2 z^(-2) + ... + bM z^(-M) H(z) = ---- = -------------------------------------------- A(z) a0 + a1 z^(-1) + a2 z^(-2) + ... + aN z^(-N) b0 (z - z1) (z - z2) ... (z - zM) = -- z^(-M+N) ------------------------------ a0 (z - p1) (z - p2) ... (z - pN) @end group @end example If called with only one argument, the poles @var{p} defaults to an empty vector, and the denominator coefficient vector @var{a} defaults to 1. @end deftypefn @c --------------------------------------------------- @node Filter Conversion @section Filter Conversion @cindex Filter Conversion @c Filter Conversion polystab @c Filter Conversion residued @c ----------------------------------------- @subsection residued @cindex residued @deftypefn {Function File} {[@var{r}, @var{p}, @var{f}, @var{m}] =} residued (@var{b}, @var{a}) Compute the partial fraction expansion (PFE) of filter @math{H(z) = B(z)/A(z)}. In the usual PFE function @code{residuez}, the IIR part (poles @var{p} and residues @var{r}) is driven @emph{in parallel} with the FIR part (@var{f}). In this variant, the IIR part is driven by the @emph{output} of the FIR part. This structure can be more accurate in signal modeling applications. INPUTS: @var{b} and @var{a} are vectors specifying the digital filter @math{H(z) = B(z)/A(z)}. See @code{help filter} for documentation of the @var{b} and @var{a} filter coefficients. RETURNED: @itemize @item @var{r} = column vector containing the filter-pole residues @item @var{p} = column vector containing the filter poles @item @var{f} = row vector containing the FIR part, if any @item @var{m} = column vector of pole multiplicities @end itemize EXAMPLES: @example See @code{test residued verbose} to see a number of examples. @end example For the theory of operation, see @indicateurl{http://ccrma.stanford.edu/~jos/filters/residued.html} @xseealso{residue, residued} @end deftypefn @c Filter Conversion residuez @c ----------------------------------------- @subsection residuez @cindex residuez @deftypefn {Function File} {[@var{r}, @var{p}, @var{f}, @var{m}] =} residuez (@var{b}, @var{a}) Compute the partial fraction expansion of filter @math{H(z) = B(z)/A(z)}. INPUTS: @var{b} and @var{a} are vectors specifying the digital filter @math{H(z) = B(z)/A(z)}. See @code{help filter} for documentation of the @var{b} and @var{a} filter coefficients. RETURNED: @itemize @item @var{r} = column vector containing the filter-pole residues @item @var{p} = column vector containing the filter poles @item @var{f} = row vector containing the FIR part, if any @item @var{m} = column vector of pole multiplicities @end itemize EXAMPLES: @example See @code{test residuez verbose} to see a number of examples. @end example For the theory of operation, see @indicateurl{http://ccrma.stanford.edu/~jos/filters/residuez.html} @xseealso{residue, residued} @end deftypefn @c Filter Conversion sos2ss @c ----------------------------------------- @subsection sos2ss @cindex sos2ss @deftypefn {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} sos2ss (@var{sos}) Convert series second-order sections to state-space. @xseealso{sos2ss, ss2tf} @end deftypefn @c Filter Conversion sos2tf @c ----------------------------------------- @subsection sos2tf @cindex sos2tf @deftypefn {Function File} {[@var{b}, @var{a}] =} sos2tf (@var{sos}) @deftypefnx {Function File} {[@var{b}, @var{a}] =} sos2tf (@var{sos}, @var{g}) Convert series second-order sections to transfer function. INPUTS: @itemize @item @var{sos} = matrix of series second-order sections, one per row: @example @var{sos} = [@var{B1}.' @var{A1}.'; ...; @var{BN}.' @var{AN}.'] @end example where @code{@var{B1}.' = [b0 b1 b2] and @var{A1}.' = [a0 a1 a2]} for section 1, etc. a0 is usually equal to 1 because all 2nd order transfer functions can be scaled so that a0 = 1. However, this is not mandatory for this implementation, which supports all kinds of transfer functions, including first order transfer functions. See @code{filter} for documentation of the second-order direct-form filter coefficients @var{B}i and @var{A}i. @item @var{g} is an overall gain factor that effectively scales the output @var{b} vector (or any one of the input @var{B}i vectors). If not given the gain is assumed to be 1. @end itemize RETURNED: @var{b} and @var{a} are vectors specifying the analog or digital filter @math{H(s) = B(s)/A(s)} or @math{H(z) = B(z)/A(z)}. See @code{filter} for further details. @xseealso{tf2sos, zp2sos, sos2pz, zp2tf, tf2zp} @end deftypefn @c Filter Conversion sos2zp @c ----------------------------------------- @subsection sos2zp @cindex sos2zp @deftypefn {Function File} {[@var{z}, @var{p}, @var{k}] =} sos2zp (@var{sos}) @deftypefnx {Function File} {[@var{z}, @var{p}, @var{k}] =} sos2zp (@var{sos}, @var{g}) Convert series second-order sections to zeros, poles, and gains (pole residues). INPUTS: @itemize @item @var{sos} = matrix of series second-order sections, one per row: @example @var{sos} = [@var{B1}.' @var{A1}.'; ...; @var{BN}.' @var{AN}.'] @end example where @code{@var{B1}.' = [b0 b1 b2] and @var{A1}.' = [a0 a1 a2]} for section 1, etc. a0 is usually equal to 1 because all 2nd order transfer functions can be scaled so that a0 = 1. However, this is not mandatory for this implementation, which supports all kinds of transfer functions, including first order transfer functions. See @code{filter} for documentation of the second-order direct-form filter coefficients @var{B}i and @var{A}i. @item @var{g} is an overall gain factor that effectively scales any one of the input @var{B}i vectors. If not given the gain is assumed to be 1. @end itemize RETURNED: @itemize @item @var{z} = column-vector containing all zeros (roots of B(z)) @item @var{p} = column-vector containing all poles (roots of A(z)) @item @var{k} = overall gain = @var{B}(Inf) @end itemize EXAMPLE: @example [z, p, k] = sos2zp ([1 0 1, 1 0 -0.81; 1 0 0, 1 0 0.49]) @result{} z = 0 + 1i 0 - 1i 0 + 0i 0 + 0i @result{} p = -0.9000 + 0i 0.9000 + 0i 0 + 0.7000i 0 - 0.7000i @result{} k = 1 @end example @xseealso{zp2sos, sos2tf, tf2sos, zp2tf, tf2zp} @end deftypefn @c Filter Conversion ss2tf @c ----------------------------------------- @subsection ss2tf @cindex ss2tf @deftypefn {Function File} {[@var{num}, @var{den}] =} ss2tf (@var{a}, @var{b}, @var{c}, @var{d}) Conversion from state-space to transfer function representation. The state space system: @tex $$ \dot x = Ax + Bu $$ $$ y = Cx + Du $$ @end tex @ifnottex @example @group . x = Ax + Bu y = Cx + Du @end group @end example @end ifnottex is converted to a transfer function: @tex $$ G(s) = { { \rm num }(s) \over { \rm den }(s) } $$ @end tex @ifnottex @example @group num(s) G(s)=------- den(s) @end group @end example @end ifnottex @end deftypefn @c Filter Conversion ss2zp @c ----------------------------------------- @subsection ss2zp @cindex ss2zp @deftypefn {Function File} {[@var{z}, @var{p}, @var{k}] =} ss2zp (@var{a}, @var{b}, @var{c}, @var{d}) Converts a state space representation to a set of poles and zeros; @var{k} is a gain associated with the zeros. @end deftypefn @c Filter Conversion tf2sos @c ----------------------------------------- @subsection tf2sos @cindex tf2sos @deftypefn {Function File} {[@var{sos}, @var{g}] =} tf2sos (@var{b}, @var{a}) @deftypefnx {Function File} {@var{sos} =} tf2sos (@var{b}, @var{a}) Convert direct-form filter coefficients to series second-order sections. INPUTS: @var{b} and @var{a} are vectors specifying the digital filter @math{H(z) = B(z)/A(z)}. See @code{filter} for documentation of the @var{b} and @var{a} filter coefficients. RETURNED: @itemize @item @var{sos} = matrix of series second-order sections, one per row: @example @var{sos} = [@var{b1}.' @var{a1}.'; ...; @var{bn}.' @var{an}.'] @end example where @code{@var{B1}.' = [b0 b1 b2] and @var{A1}.' = [1 a1 a2]} for section 1, etc. The b0 entry must be nonzero for each section (zeros at infinity not supported). @item @var{g} is an overall gain factor that effectively scales any one of the @var{B}i vectors. @end itemize If called with only one output argument, the overall filter gain is applied to the first second-order section in the matrix @var{sos}. EXAMPLE: @example B = [1 0 0 0 0 1]; A = [1 0 0 0 0 .9]; [sos, g] = tf2sos (B, A) sos = 1.00000 0.61803 1.00000 1.00000 0.60515 0.95873 1.00000 -1.61803 1.00000 1.00000 -1.58430 0.95873 1.00000 1.00000 -0.00000 1.00000 0.97915 -0.00000 g = 1 @end example @xseealso{sos2tf, zp2sos, sos2pz, zp2tf, tf2zp} @end deftypefn @c Filter Conversion tf2ss @c ----------------------------------------- @subsection tf2ss @cindex tf2ss @deftypefn {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} tf2ss (@var{num}, @var{den}) Conversion from transfer function to state-space. The state space system: @tex $$ \dot x = Ax + Bu $$ $$ y = Cx + Du $$ @end tex @ifnottex @example @group . x = Ax + Bu y = Cx + Du @end group @end example @end ifnottex is obtained from a transfer function: @tex $$ G(s) = { { \rm num }(s) \over { \rm den }(s) } $$ @end tex @ifnottex @example @group num(s) G(s)=------- den(s) @end group @end example @end ifnottex The state space system matrices obtained from this function will be in observable companion form as Wolovich's Observable Structure Theorem is used. @end deftypefn @c Filter Conversion tf2zp @c ----------------------------------------- @subsection tf2zp @cindex tf2zp @deftypefn {Function File} {[@var{z}, @var{p}, @var{k}] =} tf2zp (@var{num}, @var{den}) Convert transfer functions to poles-and-zero representations. Returns the zeros and poles of the system defined by @var{num}/@var{den}. @var{k} is a gain associated with the system zeros. @end deftypefn @c Filter Conversion zp2sos @c ----------------------------------------- @subsection zp2sos @cindex zp2sos @deftypefn {Function File} {[@var{sos}, @var{g}] =} zp2sos (@var{z}) @deftypefnx {Function File} {[@var{sos}, @var{g}] =} zp2sos (@var{z}, @var{p}) @deftypefnx {Function File} {[@var{sos}, @var{g}] =} zp2sos (@var{z}, @var{p}, @var{k}) @deftypefnx {Function File} {@var{sos} =} zp2sos (@dots{}) Convert filter poles and zeros to second-order sections. INPUTS: @itemize @item @var{z} = column-vector containing the filter zeros @item @var{p} = column-vector containing the filter poles @item @var{k} = overall filter gain factor. If not given the gain is assumed to be 1. @end itemize RETURNED: @itemize @item @var{sos} = matrix of series second-order sections, one per row: @example @var{sos} = [@var{B1}.' @var{A1}.'; ...; @var{BN}.' @var{AN}.'] @end example where @code{@var{B1}.' = [b0 b1 b2] and @var{A1}.' = [a0 a1 a2]} for section 1, etc. See @code{filter} for documentation of the second-order direct-form filter coefficients @var{B}i and %@var{A}i, i=1:N. @item @var{g} is the overall gain factor that effectively scales any one of the @var{B}i vectors. @end itemize If called with only one output argument, the overall filter gain is applied to the first second-order section in the matrix @var{sos}. EXAMPLE: @example [z, p, k] = tf2zp ([1 0 0 0 0 1], [1 0 0 0 0 .9]); [sos, g] = zp2sos (z, p, k) sos = 1.0000 0.6180 1.0000 1.0000 0.6051 0.9587 1.0000 -1.6180 1.0000 1.0000 -1.5843 0.9587 1.0000 1.0000 0 1.0000 0.9791 0 g = 1 @end example @xseealso{sos2zp, sos2tf, tf2sos, zp2tf, tf2zp} @end deftypefn @c Filter Conversion zp2ss @c ----------------------------------------- @subsection zp2ss @cindex zp2ss @deftypefn {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} zp2ss (@var{z}, @var{p}, @var{k}) Conversion from zero / pole to state space. @strong{Inputs} @table @var @item z @itemx p Vectors of (possibly) complex poles and zeros of a transfer function. Complex values must come in conjugate pairs (i.e., @math{x+jy} in @var{z} means that @math{x-jy} is also in @var{z}). @item k Real scalar (leading coefficient). @end table @strong{Outputs} @table @var @item @var{a} @itemx @var{b} @itemx @var{c} @itemx @var{d} The state space system, in the form: @tex $$ \dot x = Ax + Bu $$ $$ y = Cx + Du $$ @end tex @ifnottex @example @group . x = Ax + Bu y = Cx + Du @end group @end example @end ifnottex @end table @end deftypefn @c Filter Conversion zp2tf @c ----------------------------------------- @subsection zp2tf @cindex zp2tf @deftypefn {Function File} {[@var{num}, @var{den}] =} zp2tf (@var{z}, @var{p}, @var{k}) Converts zeros / poles to a transfer function. @strong{Inputs} @table @var @item z @itemx p Vectors of (possibly complex) poles and zeros of a transfer function. Complex values must appear in conjugate pairs. @item k Real scalar (leading coefficient). @end table @end deftypefn @c --------------------------------------------------- @node IIR Filter Design @section IIR Filter Design @cindex IIR Filter Design @c IIR Filter Design besselap @c ----------------------------------------- @subsection besselap @cindex besselap @deftypefn {Function File} {[@var{zero}, @var{pole}, @var{gain}] =} besselap (@var{n}) Return bessel analog filter prototype. References: http://en.wikipedia.org/wiki/Bessel_polynomials @end deftypefn @c IIR Filter Design besself @c ----------------------------------------- @subsection besself @cindex besself @deftypefn {Function File} {[@var{b}, @var{a}] =} besself (@var{n}, @var{w}) @deftypefnx {Function File} {[@var{b}, @var{a}] =} besself (@var{n}, @var{w}, "high") @deftypefnx {Function File} {[@var{z}, @var{p}, @var{g}] =} besself (@dots{}) @deftypefnx {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} besself (@dots{}) @deftypefnx {Function File} {[@dots{}] =} besself (@dots{}, "z") Generate a Bessel filter. Default is a Laplace space (s) filter. [b,a] = besself(n, Wc) low pass filter with cutoff pi*Wc radians [b,a] = besself(n, Wc, 'high') high pass filter with cutoff pi*Wc radians [z,p,g] = besself(...) return filter as zero-pole-gain rather than coefficients of the numerator and denominator polynomials. [...] = besself(...,'z') return a discrete space (Z) filter, W must be less than 1. [a,b,c,d] = besself(...) return state-space matrices References: Proakis & Manolakis (1992). Digital Signal Processing. New York: Macmillan Publishing Company. @end deftypefn @c IIR Filter Design bilinear @c ----------------------------------------- @subsection bilinear @cindex bilinear @deftypefn {Function File} {[@var{Zb}, @var{Za}] =} bilinear (@var{Sb}, @var{Sa}, @var{T}) @deftypefnx {Function File} {[@var{Zb}, @var{Za}] =} bilinear (@var{Sz}, @var{Sp}, @var{Sg}, @var{T}) @deftypefnx {Function File} {[@var{Zz}, @var{Zp}, @var{Zg}] =} bilinear (@dots{}) Transform a s-plane filter specification into a z-plane specification. Filters can be specified in either zero-pole-gain or transfer function form. The input form does not have to match the output form. 1/T is the sampling frequency represented in the z plane. Note: this differs from the bilinear function in the signal processing toolbox, which uses 1/T rather than T. Theory: Given a piecewise flat filter design, you can transform it from the s-plane to the z-plane while maintaining the band edges by means of the bilinear transform. This maps the left hand side of the s-plane into the interior of the unit circle. The mapping is highly non-linear, so you must design your filter with band edges in the s-plane positioned at 2/T tan(w*T/2) so that they will be positioned at w after the bilinear transform is complete. The following table summarizes the transformation: @example +---------------+-----------------------+----------------------+ | Transform | Zero at x | Pole at x | | H(S) | H(S) = S-x | H(S)=1/(S-x) | +---------------+-----------------------+----------------------+ | 2 z-1 | zero: (2+xT)/(2-xT) | zero: -1 | | S -> - --- | pole: -1 | pole: (2+xT)/(2-xT) | | T z+1 | gain: (2-xT)/T | gain: (2-xT)/T | +---------------+-----------------------+----------------------+ @end example With tedious algebra, you can derive the above formulae yourself by substituting the transform for S into H(S)=S-x for a zero at x or H(S)=1/(S-x) for a pole at x, and converting the result into the form: @example H(Z)=g prod(Z-Xi)/prod(Z-Xj) @end example Please note that a pole and a zero at the same place exactly cancel. This is significant since the bilinear transform creates numerous extra poles and zeros, most of which cancel. Those which do not cancel have a "fill-in" effect, extending the shorter of the sets to have the same number of as the longer of the sets of poles and zeros (or at least split the difference in the case of the band pass filter). There may be other opportunistic cancellations but I will not check for them. Also note that any pole on the unit circle or beyond will result in an unstable filter. Because of cancellation, this will only happen if the number of poles is smaller than the number of zeros. The analytic design methods all yield more poles than zeros, so this will not be a problem. References: Proakis & Manolakis (1992). Digital Signal Processing. New York: Macmillan Publishing Company. @end deftypefn @c IIR Filter Design buttap @c ----------------------------------------- @subsection buttap @cindex buttap @deftypefn {Function File} {[@var{z}, @var{p}, @var{g}] =} buttap (@var{n}) Design lowpass analog Butterworth filter. This function exists for @sc{matlab} compatibility only, and is equivalent to @code{butter (@var{n}, 1, "s")}. @xseealso{butter} @end deftypefn @c IIR Filter Design butter @c ----------------------------------------- @subsection butter @cindex butter @deftypefn {Function File} {[@var{b}, @var{a}] =} butter (@var{n}, @var{wc}) @deftypefnx {Function File} {[@var{b}, @var{a}] =} butter (@var{n}, @var{wc}, @var{filter_type}) @deftypefnx {Function File} {[@var{z}, @var{p}, @var{g}] =} butter (@dots{}) @deftypefnx {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} butter (@dots{}) @deftypefnx {Function File} {[@dots{}] =} butter (@dots{}, "s") Generate a Butterworth filter. Default is a discrete space (Z) filter. The cutoff frequency, @var{wc} should be specified in radians for analog filters. For digital filters, it must be a value between zero and one. For bandpass filters, @var{wc} is a two-element vector with @code{w(1) < w(2)}. The filter type must be one of @qcode{"low"}, @qcode{"high"}, @qcode{"bandpass"}, or @qcode{"stop"}. The default is @qcode{"low"} if @var{wc} is a scalar and @qcode{"bandpass"} if @var{wc} is a two-element vector. If the final input argument is @qcode{"s"} design an analog Laplace space filter. Low pass filter with cutoff @code{pi*Wc} radians: @example [b, a] = butter (n, Wc) @end example High pass filter with cutoff @code{pi*Wc} radians: @example [b, a] = butter (n, Wc, "high") @end example Band pass filter with edges @code{pi*Wl} and @code{pi*Wh} radians: @example [b, a] = butter (n, [Wl, Wh]) @end example Band reject filter with edges @code{pi*Wl} and @code{pi*Wh} radians: @example [b, a] = butter (n, [Wl, Wh], "stop") @end example Return filter as zero-pole-gain rather than coefficients of the numerator and denominator polynomials: @example [z, p, g] = butter (@dots{}) @end example Return a Laplace space filter, @var{Wc} can be larger than 1: @example [@dots{}] = butter (@dots{}, "s") @end example Return state-space matrices: @example [a, b, c, d] = butter (@dots{}) @end example References: Proakis & Manolakis (1992). Digital Signal Processing. New York: Macmillan Publishing Company. @end deftypefn @c IIR Filter Design buttord @c ----------------------------------------- @subsection buttord @cindex buttord @deftypefn {Function File} {@var{n} =} buttord (@var{wp}, @var{ws}, @var{rp}, @var{rs}) @deftypefnx {Function File} {@var{n} =} buttord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}) @deftypefnx {Function File} {@var{n} =} buttord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}, "s") @deftypefnx {Function File} {[@var{n}, @var{wc_p}] =} buttord (@dots{}) @deftypefnx {Function File} {[@var{n}, @var{wc_p}, @var{wc_s}] =} buttord (@dots{}) Compute the minimum filter order of a Butterworth filter with the desired response characteristics. The filter frequency band edges are specified by the passband frequency @var{wp} and stopband frequency @var{ws}. Frequencies are normalized to the Nyquist frequency in the range [0,1]. @var{rp} is the allowable passband ripple measured in decibels, and @var{rs} is the minimum attenuation in the stop band, also in decibels. The output arguments @var{n} and @var{wc_p} (or @var{n} and @var{wc_n}) can be given as inputs to @code{butter}. Using @var{wc_p} makes the filter characteristic touch at least one pass band corner and using @var{wc_s} makes the characteristic touch at least one stop band corner. If @var{wp} and @var{ws} are scalars, then @var{wp} is the passband cutoff frequency and @var{ws} is the stopband edge frequency. If @var{ws} is greater than @var{wp}, the filter is a low-pass filter. If @var{wp} is greater than @var{ws}, the filter is a high-pass filter. If @var{wp} and @var{ws} are vectors of length 2, then @var{wp} defines the passband interval and @var{ws} defines the stopband interval. If @var{wp} is contained within @var{ws} (@var{ws1} < @var{wp1} < @var{wp2} < @var{ws2}), the filter is a band-pass filter. If @var{ws} is contained within @var{wp} (@var{wp1} < @var{ws1} < @var{ws2} < @var{wp2}), the filter is a band-stop or band-reject filter. If the optional argument @code{"s"} is given, the minimum order for an analog elliptic filter is computed. All frequencies @var{wp} and @var{ws} are specified in radians per second. Theory: For Low pass filters, |H(W)|^2 = 1/[1+(W/Wc)^(2N)] = 10^(-R/10). With some algebra, you can solve simultaneously for Wc and N given Ws,Rs and Wp,Rp. Rounding N to the next greater integer, one can recalculate the allowable range for Wc (filter caracteristic touching the pass band edge or the stop band edge). For other types of filter, before making the above calculation, the requirements must be transformed to LP requirements. After calculation, Wc must be transformed back to original filter type. @xseealso{butter, cheb1ord, cheb2ord, ellipord} @end deftypefn @c IIR Filter Design cheb @c ----------------------------------------- @subsection cheb @cindex cheb @deftypefn {Function File} {} cheb (@var{n}, @var{x}) Returns the value of the nth-order Chebyshev polynomial calculated at the point x. The Chebyshev polynomials are defined by the equations: @example @group / cos(n acos(x), |x| <= 1 Tn(x) = | \ cosh(n acosh(x), |x| > 1 @end group @end example If x is a vector, the output is a vector of the same size, where each element is calculated as y(i) = Tn(x(i)). @end deftypefn @c IIR Filter Design cheb1ap @c ----------------------------------------- @subsection cheb1ap @cindex cheb1ap @deftypefn {Function File} {[@var{z}, @var{p}, @var{g}] =} cheb1ap (@var{n}, @var{Rp}) Design lowpass analog Chebyshev type I filter. This function exists for @sc{matlab} compatibility only, and is equivalent to @code{cheby1 (@var{n}, @var{Rp}, 1, "s")}. Input: @itemize @item @var{N} Order of the filter must be a positive integer @item @var{RP} Ripple in the passband in dB @end itemize Output: @itemize @item @var{z} The zero vector @item @var{p} The pole vectorAngle @item @var{g} The gain factor @end itemize Example @example [z, p, g] = cheb1ap (2, 1) z = [](0x1) p = -0.54887 - 0.89513i -0.54887 + 0.89513i g = 0.98261 @end example @xseealso{buttap, cheby1, cheb2ap, ellipap} @end deftypefn @c IIR Filter Design cheb1ord @c ----------------------------------------- @subsection cheb1ord @cindex cheb1ord @deftypefn {Function File} {@var{n} =} cheb1ord (@var{wp}, @var{ws}, @var{rp}, @var{rs}) @deftypefnx {Function File} {@var{n} =} cheb1ord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}) @deftypefnx {Function File} {@var{n} =} cheb1ord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}, "s") @deftypefnx {Function File} {[@var{n}, @var{wc}] =} cheb1ord (@dots{}) @deftypefnx {Function File} {[@var{n}, @var{wc_p}, @var{wc_s}] =} cheb1ord (@dots{}) Compute the minimum filter order of a Chebyshev type I filter with the desired response characteristics. The filter frequency band edges are specified by the passband frequency @var{wp} and stopband frequency @var{ws}. Frequencies are normalized to the Nyquist frequency in the range [0,1]. @var{rp} is the allowable passband ripple measured in decibels, and @var{rs} is the minimum attenuation in the stop band, also in decibels. The output arguments @var{n} and @var{wc_p} (or @var{n} and @var{wc_s}) can be given as inputs to @code{cheby1}. Using @var{wc_p} makes the filter characteristic touch at least one pass band corner and using @var{wc_s} makes the characteristic touch at least one stop band corner. If @var{wp} and @var{ws} are scalars, then @var{wp} is the passband cutoff frequency and @var{ws} is the stopband edge frequency. If @var{ws} is greater than @var{wp}, the filter is a low-pass filter. If @var{wp} is greater than @var{ws}, the filter is a high-pass filter. If @var{wp} and @var{ws} are vectors of length 2, then @var{wp} defines the passband interval and @var{ws} defines the stopband interval. If @var{wp} is contained within @var{ws} (@var{ws1} < @var{wp1} < @var{wp2} < @var{ws2}), the filter is a band-pass filter. If @var{ws} is contained within @var{wp} (@var{wp1} < @var{ws1} < @var{ws2} < @var{wp2}), the filter is a band-stop or band-reject filter. If the optional argument @code{"s"} is given, the minimum order for an analog elliptic filter is computed. All frequencies @var{wp} and @var{ws} are specified in radians per second. @xseealso{buttord, cheby1, cheb2ord, ellipord} @end deftypefn @c IIR Filter Design cheb2ap @c ----------------------------------------- @subsection cheb2ap @cindex cheb2ap @deftypefn {Function File} {[@var{z}, @var{p}, @var{g}] =} cheb2ap (@var{n}, @var{Rs}) Design lowpass analog Chebyshev type II filter. This function exists for @sc{matlab} compatibility only, and is equivalent to @code{cheby2 (@var{n}, @var{Rs}, 1, "s")}. Demo @example demo cheb2ap @end example @xseealso{cheby2} @end deftypefn @c IIR Filter Design cheb2ord @c ----------------------------------------- @subsection cheb2ord @cindex cheb2ord @deftypefn {Function File} {@var{n} =} cheb2ord (@var{wp}, @var{ws}, @var{rp}, @var{rs}) @deftypefnx {Function File} {@var{n} =} cheb2ord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}) @deftypefnx {Function File} {@var{n} =} cheb2ord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}, "s") @deftypefnx {Function File} {[@var{n}, @var{wc_s}] =} cheb2ord (@dots{}) @deftypefnx {Function File} {[@var{n}, @var{wc_s}, @var{wc_p}] =} cheb2ord (@dots{}) Compute the minimum filter order of a Chebyshev type II filter with the desired response characteristics. The filter frequency band edges are specified by the passband frequency @var{wp} and stopband frequency @var{ws}. Frequencies are normalized to the Nyquist frequency in the range [0,1]. @var{rp} is the allowable passband ripple measured in decibels, and @var{rs} is the minimum attenuation in the stop band, also in decibels. The output arguments @var{n} and @var{wc_p} (or @var{n} and @var{wc_s}) can be given as inputs to @code{cheby2}. Using @var{wc_p} makes the filter characteristic touch at least one pass band corner and using @var{wc_s} makes the characteristic touch at least one stop band corner. If @var{wp} and @var{ws} are scalars, then @var{wp} is the passband cutoff frequency and @var{ws} is the stopband edge frequency. If @var{ws} is greater than @var{wp}, the filter is a low-pass filter. If @var{wp} is greater than @var{ws}, the filter is a high-pass filter. If @var{wp} and @var{ws} are vectors of length 2, then @var{wp} defines the passband interval and @var{ws} defines the stopband interval. If @var{wp} is contained within @var{ws} (@var{ws1} < @var{wp1} < @var{wp2} < @var{ws2}), the filter is a band-pass filter. If @var{ws} is contained within @var{wp} (@var{wp1} < @var{ws1} < @var{ws2} < @var{wp2}), the filter is a band-stop or band-reject filter. If the optional argument @code{"s"} is given, the minimum order for an analog elliptic filter is computed. All frequencies @var{wp} and @var{ws} are specified in radians per second. @xseealso{buttord, cheb1ord, cheby2, ellipord} @end deftypefn @c IIR Filter Design cheby1 @c ----------------------------------------- @subsection cheby1 @cindex cheby1 @deftypefn {Function File} {[@var{b}, @var{a}] =} cheby1 (@var{n}, @var{rp}, @var{w}) @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby1 (@var{n}, @var{rp}, @var{w}, "high") @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby1 (@var{n}, @var{rp}, [@var{wl}, @var{wh}]) @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby1 (@var{n}, @var{rp}, [@var{wl}, @var{wh}], "stop") @deftypefnx {Function File} {[@var{z}, @var{p}, @var{g}] =} cheby1 (@dots{}) @deftypefnx {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} cheby1 (@dots{}) @deftypefnx {Function File} {[@dots{}] =} cheby1 (@dots{}, "s") Generate a Chebyshev type I filter with @var{rp} dB of passband ripple. [b, a] = cheby1(n, Rp, Wc) low pass filter with cutoff pi*Wc radians [b, a] = cheby1(n, Rp, Wc, 'high') high pass filter with cutoff pi*Wc radians [b, a] = cheby1(n, Rp, [Wl, Wh]) band pass filter with edges pi*Wl and pi*Wh radians [b, a] = cheby1(n, Rp, [Wl, Wh], 'stop') band reject filter with edges pi*Wl and pi*Wh radians [z, p, g] = cheby1(...) return filter as zero-pole-gain rather than coefficients of the numerator and denominator polynomials. [...] = cheby1(...,'s') return a Laplace space filter, W can be larger than 1. [a,b,c,d] = cheby1(...) return state-space matrices References: Parks & Burrus (1987). Digital Filter Design. New York: John Wiley & Sons, Inc. @end deftypefn @c IIR Filter Design cheby2 @c ----------------------------------------- @subsection cheby2 @cindex cheby2 @deftypefn {Function File} {[@var{b}, @var{a}] =} cheby2 (@var{n}, @var{rs}, @var{wc}) @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby2 (@var{n}, @var{rs}, @var{wc}, "high") @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby2 (@var{n}, @var{rs}, [@var{wl}, @var{wh}]) @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby2 (@var{n}, @var{rs}, [@var{wl}, @var{wh}], "stop") @deftypefnx {Function File} {[@var{z}, @var{p}, @var{g}] =} cheby2 (@dots{}) @deftypefnx {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} cheby2 (@dots{}) @deftypefnx {Function File} {[@dots{}] =} cheby2 (@dots{}, "s") Generate a Chebyshev type II filter with @var{rs} dB of stopband attenuation. [b, a] = cheby2(n, Rs, Wc) low pass filter with cutoff pi*Wc radians [b, a] = cheby2(n, Rs, Wc, 'high') high pass filter with cutoff pi*Wc radians [b, a] = cheby2(n, Rs, [Wl, Wh]) band pass filter with edges pi*Wl and pi*Wh radians [b, a] = cheby2(n, Rs, [Wl, Wh], 'stop') band reject filter with edges pi*Wl and pi*Wh radians [z, p, g] = cheby2(...) return filter as zero-pole-gain rather than coefficients of the numerator and denominator polynomials. [...] = cheby2(...,'s') return a Laplace space filter, W can be larger than 1. [a,b,c,d] = cheby2(...) return state-space matrices References: Parks & Burrus (1987). Digital Filter Design. New York: John Wiley & Sons, Inc. @end deftypefn @c IIR Filter Design ellip @c ----------------------------------------- @subsection ellip @cindex ellip @deftypefn {Function File} {[@var{b}, @var{a}] =} ellip (@var{n}, @var{rp}, @var{rs}, @var{wp}) @deftypefnx {Function File} {[@var{b}, @var{a}] =} ellip (@var{n}, @var{rp}, @var{rs}, @var{wp}, "high") @deftypefnx {Function File} {[@var{b}, @var{a}] =} ellip (@var{n}, @var{rp}, @var{rs}, [@var{wl}, @var{wh}]) @deftypefnx {Function File} {[@var{b}, @var{a}] =} ellip (@var{n}, @var{rp}, @var{rs}, [@var{wl}, @var{wh}], "stop") @deftypefnx {Function File} {[@var{z}, @var{p}, @var{g}] =} ellip (@dots{}) @deftypefnx {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} ellip (@dots{}) @deftypefnx {Function File} {[@dots{}] =} ellip (@dots{}, "s") Generate an elliptic or Cauer filter with @var{rp} dB of passband ripple and @var{rs} dB of stopband attenuation. [b,a] = ellip(n, Rp, Rs, Wp) low pass filter with order n, cutoff pi*Wp radians, Rp decibels of ripple in the passband and a stopband Rs decibels down. [b,a] = ellip(n, Rp, Rs, Wp, 'high') high pass filter with cutoff pi*Wp... [b,a] = ellip(n, Rp, Rs, [Wl, Wh]) band pass filter with band pass edges pi*Wl and pi*Wh ... [b,a] = ellip(n, Rp, Rs, [Wl, Wh], 'stop') band reject filter with edges pi*Wl and pi*Wh, ... [z,p,g] = ellip(...) return filter as zero-pole-gain. [...] = ellip(...,'s') return a Laplace space filter, W can be larger than 1. [a,b,c,d] = ellip(...) return state-space matrices References: - Oppenheim, Alan V., Discrete Time Signal Processing, Hardcover, 1999. - Parente Ribeiro, E., Notas de aula da disciplina TE498 - Processamento Digital de Sinais, UFPR, 2001/2002. @end deftypefn @c IIR Filter Design ellipap @c ----------------------------------------- @subsection ellipap @cindex ellipap @deftypefn {Function File} {[@var{z}, @var{p}, @var{g}] =} ellipap (@var{n}, @var{Rp}, @var{Rs}) Design lowpass analog elliptic filter. This function exists for @sc{matlab} compatibility only, and is equivalent to @code{ellip (@var{n}, @var{Rp}, @var{Rs}, 1, "s")}. @xseealso{ellip} @end deftypefn @c IIR Filter Design ellipord @c ----------------------------------------- @subsection ellipord @cindex ellipord @deftypefn {Function File} {@var{n} =} ellipord (@var{wp}, @var{ws}, @var{rp}, @var{rs}) @deftypefnx {Function File} {@var{n} =} ellipord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}) @deftypefnx {Function File} {@var{n} =} ellipord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}, "s") @deftypefnx {Function File} {[@var{n}, @var{wc}] =} ellipord (@dots{}) Compute the minimum filter order of an elliptic filter with the desired response characteristics. The filter frequency band edges are specified by the passband frequency @var{wp} and stopband frequency @var{ws}. Frequencies are normalized to the Nyquist frequency in the range [0,1]. @var{rp} is the allowable passband ripple measured in decibels, and @var{rs} is the minimum attenuation in the stop band, also in decibels. The output arguments @var{n} and @var{wc} can be given as inputs to @code{ellip}. If @var{wp} and @var{ws} are scalars, then @var{wp} is the passband cutoff frequency and @var{ws} is the stopband edge frequency. If @var{ws} is greater than @var{wp}, the filter is a low-pass filter. If @var{wp} is greater than @var{ws}, the filter is a high-pass filter. If @var{wp} and @var{ws} are vectors of length 2, then @var{wp} defines the passband interval and @var{ws} defines the stopband interval. If @var{wp} is contained within @var{ws} (@var{ws1} < @var{wp1} < @var{wp2} < @var{ws2}), the filter is a band-pass filter. If @var{ws} is contained within @var{wp} (@var{wp1} < @var{ws1} < @var{ws2} < @var{wp2}), the filter is a band-stop or band-reject filter. If the optional argument @code{"s"} is given, the minimum order for an analog elliptic filter is computed. All frequencies @var{wp} and @var{ws} are specified in radians per second. Reference: Lamar, Marcus Vinicius, @cite{Notas de aula da disciplina TE 456 - Circuitos Analogicos II}, UFPR, 2001/2002. @xseealso{buttord, cheb1ord, cheb2ord, ellip} @end deftypefn @c IIR Filter Design firpm @c ----------------------------------------- @subsection firpm @cindex firpm @deftypefn {Loadable Function} {@var{b} =} firpm (@var{n}, @var{f}, @var{a}) @deftypefnx {Loadable Function} {@var{b} =} firpm (@var{n}, @var{f}, @@@var{respFn}) @deftypefnx {Loadable Function} {@var{b} =} firpm (@var{n}, @var{f}, @{@@@var{respFn}, @dots{}@}) @deftypefnx {Loadable Function} {@var{b} =} firpm (@dots{}, @var{w}) @deftypefnx {Loadable Function} {@var{b} =} firpm (@dots{}, @var{class}) @deftypefnx {Loadable Function} {@var{b} =} firpm (@dots{}, @{@var{accuracy, @dots{}@}}) @deftypefnx {Loadable Function} {[@var{b}, @var{minimax}] =} firpm (@dots{}) @deftypefnx {Loadable Function} {[@var{b}, @var{minimax}, @var{res}] =} firpm (@dots{}) @cindex signal processing Designs a linear-phase FIR filter according to given specifications and the `minimax' criterion. The method (per McClellan et al.@footnote{ J. H. McClellan, T. W. Parks and L. R. Rabiner, `A Computer Program for Designing Optimum FIR Linear Phase Digital Filters', IEEE Trans.@: Audio Electroacoust., vol.@: AU-21, 1973, pp.@: 506--525.}) uses successive approximation to minimize the maximum weighted error between the desired and actual frequency response of the filter. Such filters are variably described as being `minimax', `equiripple', or `optimal (in the Chebyshev sense)'. @heading Arguments @table @var @item @dots{} Where shown as the first argument to @code{firpm}, indicates that any previously-indicated list of arguments may substitute for the ellipsis. @item n A positive integer giving the filter order. @item f A vector of real-numbers, increasing in the range [0,1], giving the frequencies of the left and right edges of each band for which a specific amplitude response is desired: [l1 r1 l2 r2 @dots{}]. 1 represents the Nyquist-frequency. Transition-bands are defined implicitly as the regions between or outside the given bands. @item a A vector of real-numbers giving the desired amplitude response. An amplitude value is given either for each band edge: [a(l1) a(r1) a(l2) a(r2) @dots{}], or for each band: [a1 a2 @dots{}]. In the former case, in-band amplitude is determined by linear interpolation between the given band-edge values. 1 represents unity-gain, 0 represents infinite attenuation, and @minus{}1 represents a phase change of pi radians. Note that amplitude response is necessarily zero at @var{f}=0 for type III and IV filters, and at @var{f}=1 for type II and III filters. @item @@respFn A handle to a `response function' that supplies the desired amplitude response and error-weighting. This, unlike @var{a} above, allows the response to be arbitrary (subject to the note above). @qcode{firpm} invokes the response function according to the following syntax: @example @var{ag} = @qcode{respFn} (@var{n},@var{f},@var{g},@var{w}, @dots{}) [@var{ag} @var{wg}] = @qcode{respFn} (@var{n},@var{f},@var{g},@var{w}, @dots{}) @var{symmetry} = @qcode{respFn} ("defaults", @{@var{n},@var{f},@var{g},@var{w}, @dots{}@}) @end example where: @itemize @item @var{n} and @var{f} are as given to @qcode{firpm}. @item @var{w} is as given to @qcode{firpm}, or ones if not given. @item @var{ag} and @var{wg} are the desired amplitude and weighting functions evaluated at each frequency in vector @var{g} (which are frequencies within the non-transition bands of @var{f}). Returning @var{ag} alone gives uniform weighting. @item @var{symmetry} is either @qcode{"even"} or @qcode{"odd"}; this provides an alternative to using the @var{class} values @qcode{"symmetric"} and @qcode{"antisymmetric"}. @item Per the ellipses shown here and above, when @@@var{respFn} is given contained in a cell-array, any additionally contained values are appended to the @var{respFn} invocation argument-list. @end itemize @item w When used in conjunction with @var{a}, @var{w} is a vector of positive real-numbers giving error-weightings to be applied at each given band-edge [w(l1) w(r1) w(l2) w(r2) @dots{}], or for each band [w1 w2 @dots{}]. In the former case, in-band weighting is determined by linear interpolation between the given band-edge values. A higher relative error weighting yields a lower relative error. When used in conjunction with @@@var{respFn}, @var{w} is a vector (constrained as above) that is passed through to @var{respFn}. @item class A string, which may be abbreviated, giving the filter-class: @itemize @item @qcode{"symmetric"} (the default) for type I or II filters, @item @qcode{"antisymmetric"} (or @qcode{"hilbert"}) for standard type III or IV filters, @item @qcode{"differentiator"} for type III or IV filters with inverted phase and with error-weighting (further to @var{w}) of 2/f applied in the pass-band(s). @end itemize @item accuracy, @dots{} Up to three properties contained within a cell-array: @var{accuracy}, @var{persistence}, @var{robustness}, that respectively control how close the computed filter will be to the ideal minimax solution, the number of computation iterations over which the required accuracy will be sought, and the precision of certain internal processing. Each can each be set to a small positive number (typically @leq{}3), to increase the relevant item; this may increase computation time, but the need to do so should be rare. A value of 0 can be used to leave an item unchanged. Alternatively, setting @var{accuracy} @geq{}16 emulates @sc{matlab}'s @var{lgrid} argument. @end table @heading Results If a problem occurs during the computation, a diagnostic message will normally be displayed. If this happens, adjusting @var{accuracy}, @var{persistence}, or @var{robustness} may provide the solution. Some filters however, may not be realizable due to machine-precision limitations. If a filter can be computed, returned values are as follows: @table @var @item b A length @var{N}+1 row-vector containing the computed filter coefficients. @item minimax The absolute value of the minimized, maximum weighted error, or this number negated if the required accuracy could not be achieved. @item res A structure of data relating to the filter computation and a partial response-analysis of the resultant filter; fields are vectors: @quotation @multitable @columnfractions .125 .6 @item @code{fgrid} @tab Analysis frequencies per @var{f}. @item @code{des} @tab Desired amplitude response. @item @code{wt} @tab Error weighting. @item @code{H} @tab Complex frequency response. @item @code{error} @tab Desired minus actual amplitude response. @item @code{iextr} @tab Indices of local peaks in @code{error}. @item @code{fextr} @tab Frequencies of local peaks in @code{error}. @end multitable @end quotation @end table Using @var{res} is not recommended because it can be slow to compute and, since the analysis excludes transition-bands, any `anomalies'@footnote{ Tapio Saram@"aki, `Finite impulse response filter design', Chapter 4 in `Handbook for Digital Signal Processing', edited by S. K. Mitra and J. F. Kaiser, John Wiley and Sons, New York, 1993, pp.@: 155--277. (@url{https://homepages.tuni.fi/tapio.saramaki/Mitra_Kaiser.pdf})} therein are not easy to discern. In general, @code{freqz} suffices to check that the response of the computed filter is satisfactory. @heading Examples @example @group # Low-pass with frequencies in Hz: Fs = 96000; Fn = Fs/2; # Sampling & Nyquist frequencies. b = firpm (50, [0 20000 28000 48000] / Fn, [1 0]); @end group @end example @example @group # Type IV high-pass: b = firpm (31, [0 0.5 0.7 1], [0 1], "antisym"); @end group @end example @example @group # Inverse-sinc (arbitrary response): b = firpm (20, [0 0.5 0.9 1], @@(n,f,g) ... deal ((g<=f(2))./sinc (g), (g>=f(3))*9+1)); @end group @end example @example @group # Band-pass with filter-response check: freqz (firpm (40, [0 3 4 6 8 10]/10, [0 1 0])) @end group @end example Further examples can be found in the @code{firpm} and @code{firpmord} demonstration scripts. @heading Compatibility Given invalid filter specifications, Octave emits an error and does not produce a filter; @sc{matlab} in such circumstances may still produce filter coefficients. Unlike with @sc{matlab}, with Octave @var{minimax} can be negative; for compatibility, take the absolute value. @xseealso{firpmord} @end deftypefn @c IIR Filter Design firpmord @c ----------------------------------------- @subsection firpmord @cindex firpmord @deftypefn {Function File} {[@var{n}, @var{Fout}, @var{a}, @var{w}] =} firpmord (@var{f}, @var{a}, @var{d}) @deftypefnx {Function File} {[@var{n}, @var{Fout}, @var{a}, @var{w}] =} firpmord (@var{f}, @var{a}, @var{d}, @var{fs}) @deftypefnx {Function File} {@var{c} =} firpmord (@var{f}, @var{a}, @var{d}, "cell") @deftypefnx {Function File} {@var{c} =} firpmord (@var{f}, @var{a}, @var{d}, @var{fs}, "cell") @cindex signal processing Estimate the filter-order needed for @code{firpm} to design a type-I or type-II linear-phase FIR filter according to the given specifications. @heading Arguments @table @var @item f A vector of real-numbers, increasing in the range (0, @var{fs}/2), giving the frequencies of the left and right edges of each band for which a specific amplitude response is desired (omitting 0 and @var{fs}/2, which are implied): [r1 l2 r2 @dots{}]. Transition-bands are defined implicitly as the regions between the given bands. @item a A vector of real-numbers giving the ideal amplitude response. An amplitude value is given for each band specified by @var{f}: [a1 a2 @dots{}]. 1 represents unity-gain, 0 represents infinite attenuation, and @minus{}1 represents a phase change of pi radians. @item d A vector of positive real-numbers giving the maximum allowable linear deviation from the amplitudes given in @var{a}, thus constraining the actual amplitude response (where defined by @var{f}) to be within @var{a} +/@minus{} @var{d}. Note that, though related, @var{d} does not equate to @code{firpm}'s @var{w} argument. @item fs The sampling-frequency, which defaults to 2. @end table @heading Usage The function returns the estimated filter-order, together with the other design specification values, in one of two forms suitable for use with @code{firpm}. By default, multiple return values are used; alternatively, by giving @qcode{"cell"} (or @qcode{"c"}) as the last argument to @code{firpmord}, the returned values are contained within a cell-array that can, if desired, be passed directly to @code{firpm}. The following examples illustrate the use of both mechanisms, as well as aspects of @code{firpmord} usage in general: @example @group # Low-pass; frequencies in kHz: [n f a w] = firpmord ([2.5 3], [1 0], [0.01 db2mag(-60)], 8); b = firpm (n, f, a, w); @end group @end example @example @group # Band-pass: c = firpmord ([3 4 8 9], [0 1 0], [1e-3 1e-2 1e-3], 20, "cell"); b = firpm (c@{:@}); @end group @end example @example @group # High-pass: b = firpm (firpmord ([6.4 8]/16, [0 1], [1e-4 0.01], "c")@{:@}); @end group @end example In cases where elements of @var{d} follow a repeating pattern (e.g.@: all the elements are equal, or elements corresponding to pass-bands are equal and elements corresponding to stop-bands are equal), only as many elements as are needed to establish the pattern need be given. For example, the following @code{firpmord} invocation pairs are equivalent: @example @group # Low-pass: firpmord ([0.4 0.5], [0 1], [db2mag(-72) db2mag(-72)]); firpmord ([0.4 0.5], [0 1], [db2mag(-72)]); @end group @end example @example @group # Multi-band-pass: ds = db2mag(-80); dp = 0.01; firpmord ([1 2 3 4 5 6 7 8]/10, [0 1 0 1 0], [ds dp ds dp ds]); firpmord ([1 2 3 4 5 6 7 8]/10, [0 1 0 1 0], [ds dp]); @end group @end example @heading Notes The estimation algorithm used is per Ichige et al.@footnote{ K. Ichige, M. Iwaki, algorithm and R. Ishii, `Accurate Estimation of Minimum Filter Length for Optimum FIR Digital Filters', IEEE Transactions on Circuits and Systems, Vol.@: 47, No.@: 10, 2000, pp.@: 1008--1017} Accuracy tends to decrease as the number of bands increases. Even with two bands (i.e.@: high-pass or low-pass), the algorithm may under- or over-estimate. See the @code{firpmord} demonstrations for some examples. In order to precisely determine the minimum order needed for a particular design, @code{firpmord} could be used to seed an algorithm iterating invocations of @code{firpm} (as exemplified in demonstration number five). @heading Related documentation @xseealso{firpm, kaiserord} @end deftypefn @c IIR Filter Design iirlp2mb @c IIR Filter Design impinvar @c ----------------------------------------- @subsection impinvar @cindex impinvar @deftypefn {Function File} {[@var{b_out}, @var{a_out}] =} impinvar (@var{b}, @var{a}, @var{fs}, @var{tol}) @deftypefnx {Function File} {[@var{b_out}, @var{a_out}] =} impinvar (@var{b}, @var{a}, @var{fs}) @deftypefnx {Function File} {[@var{b_out}, @var{a_out}] =} impinvar (@var{b}, @var{a}) Converts analog filter with coefficients @var{b} and @var{a} to digital, conserving impulse response. If @var{fs} is not specified, or is an empty vector, it defaults to 1Hz. If @var{tol} is not specified, it defaults to 0.0001 (0.1%) This function does the inverse of impinvar so that the following example should restore the original values of @var{a} and @var{b}. @command{invimpinvar} implements the reverse of this function. @example [b, a] = impinvar (b, a); [b, a] = invimpinvar (b, a); @end example Reference: Thomas J. Cavicchi (1996) ``Impulse invariance and multiple-order poles''. IEEE transactions on signal processing, Vol 44 (9): 2344--2347 @xseealso{bilinear, invimpinvar} @end deftypefn @c IIR Filter Design invimpinvar @c ----------------------------------------- @subsection invimpinvar @cindex invimpinvar @deftypefn {Function File} {[@var{b_out}, @var{a_out}] =} invimpinvar (@var{b}, @var{a}, @var{fs}, @var{tol}) @deftypefnx {Function File} {[@var{b_out}, @var{a_out}] =} invimpinvar (@var{b}, @var{a}, @var{fs}) @deftypefnx {Function File} {[@var{b_out}, @var{a_out}] =} invimpinvar (@var{b}, @var{a}) Converts digital filter with coefficients @var{b} and @var{a} to analog, conserving impulse response. This function does the inverse of impinvar so that the following example should restore the original values of @var{a} and @var{b}. @example [b, a] = impinvar (b, a); [b, a] = invimpinvar (b, a); @end example If @var{fs} is not specified, or is an empty vector, it defaults to 1Hz. If @var{tol} is not specified, it defaults to 0.0001 (0.1%) Reference: Thomas J. Cavicchi (1996) ``Impulse invariance and multiple-order poles''. IEEE transactions on signal processing, Vol 40 (9): 2344--2347 @xseealso{bilinear, impinvar} @end deftypefn @c IIR Filter Design ncauer @c ----------------------------------------- @subsection ncauer @cindex ncauer @deftypefn {Function File} {[@var{z}, @var{p}, @var{g}] =} cauer(@var{Rp}, @var{Rs}, @var{n}) Analog prototype for Cauer filter. @table @asis @item Rp Passband ripple @item Rs Stopband ripple @item n Desired order @item z complex vector of zeros for the model. @item p complex vector of poles for the model. @item g gain value. @end table References: - Serra, Celso Penteado, Teoria e Projeto de Filtros, Campinas: CARTGRAF, 1983. - Lamar, Marcus Vinicius, Notas de aula da disciplina TE 456 - Circuitos Analogicos II, UFPR, 2001/2002. @end deftypefn @c IIR Filter Design pei_tseng_notch @c ----------------------------------------- @subsection pei_tseng_notch @cindex pei_tseng_notch @deftypefn {Function File} {[@var{b}, @var{a}] =} pei_tseng_notch (@var{frequencies}, @var{bandwidths}) Return coefficients for an IIR notch-filter with one or more filter frequencies and according (very narrow) bandwidths to be used with @code{filter} or @code{filtfilt}. The filter construction is based on an allpass which performs a reversal of phase at the filter frequencies. Thus, the mean of the phase-distorted and the original signal has the respective frequencies removed. See the demo for an illustration. Original source: Pei, Soo-Chang, and Chien-Cheng Tseng "IIR Multiple Notch Filter Design Based on Allpass Filter" 1996 IEEE Tencon doi: 10.1109/TENCON.1996.608814) @end deftypefn @c IIR Filter Design sftrans @c ----------------------------------------- @subsection sftrans @cindex sftrans @deftypefn {Function File} {[@var{Sz}, @var{Sp}, @var{Sg}] =} sftrans (@var{Sz}, @var{Sp}, @var{Sg}, @var{W}, @var{stop}) Transform band edges of a generic lowpass filter (cutoff at W=1) represented in splane zero-pole-gain form. W is the edge of the target filter (or edges if band pass or band stop). Stop is true for high pass and band stop filters or false for low pass and band pass filters. Filter edges are specified in radians, from 0 to pi (the nyquist frequency). Theory: Given a low pass filter represented by poles and zeros in the splane, you can convert it to a low pass, high pass, band pass or band stop by transforming each of the poles and zeros individually. The following table summarizes the transformation: @example Transform Zero at x Pole at x ---------------- ------------------------- ------------------------ Low Pass zero: Fc x/C pole: Fc x/C S -> C S/Fc gain: C/Fc gain: Fc/C ---------------- ------------------------- ------------------------ High Pass zero: Fc C/x pole: Fc C/x S -> C Fc/S pole: 0 zero: 0 gain: -x gain: -1/x ---------------- ------------------------- ------------------------ Band Pass zero: b +- sqrt(b^2-FhFl) pole: b +- sqrt(b^2-FhFl) S^2+FhFl pole: 0 zero: 0 S -> C -------- gain: C/(Fh-Fl) gain: (Fh-Fl)/C S(Fh-Fl) b=x/C (Fh-Fl)/2 b=x/C (Fh-Fl)/2 ---------------- ------------------------- ------------------------ Band Stop zero: b +- sqrt(b^2-FhFl) pole: b +- sqrt(b^2-FhFl) S(Fh-Fl) pole: +-sqrt(-FhFl) zero: +-sqrt(-FhFl) S -> C -------- gain: -x gain: -1/x S^2+FhFl b=C/x (Fh-Fl)/2 b=C/x (Fh-Fl)/2 ---------------- ------------------------- ------------------------ Bilinear zero: (2+xT)/(2-xT) pole: (2+xT)/(2-xT) 2 z-1 pole: -1 zero: -1 S -> - --- gain: (2-xT)/T gain: (2-xT)/T T z+1 ---------------- ------------------------- ------------------------ @end example where C is the cutoff frequency of the initial lowpass filter, Fc is the edge of the target low/high pass filter and [Fl,Fh] are the edges of the target band pass/stop filter. With abundant tedious algebra, you can derive the above formulae yourself by substituting the transform for S into H(S)=S-x for a zero at x or H(S)=1/(S-x) for a pole at x, and converting the result into the form: @example H(S)=g prod(S-Xi)/prod(S-Xj) @end example The transforms are from the references. The actual pole-zero-gain changes I derived myself. Please note that a pole and a zero at the same place exactly cancel. This is significant for High Pass, Band Pass and Band Stop filters which create numerous extra poles and zeros, most of which cancel. Those which do not cancel have a "fill-in" effect, extending the shorter of the sets to have the same number of as the longer of the sets of poles and zeros (or at least split the difference in the case of the band pass filter). There may be other opportunistic cancellations but I will not check for them. Also note that any pole on the unit circle or beyond will result in an unstable filter. Because of cancellation, this will only happen if the number of poles is smaller than the number of zeros and the filter is high pass or band pass. The analytic design methods all yield more poles than zeros, so this will not be a problem. References: Proakis & Manolakis (1992). Digital Signal Processing. New York: Macmillan Publishing Company. @end deftypefn @c --------------------------------------------------- @node FIR Filter Design @section FIR Filter Design @cindex FIR Filter Design @c FIR Filter Design cl2bp @c ----------------------------------------- @subsection cl2bp @cindex cl2bp @deftypefn {Loadable Function} {@var{h} =} cl2bp (@var{m}, @var{w1}, @var{w2}, @var{up}, @var{lo}) @deftypefnx {Loadable Function} {@var{h} =} cl2bp (@var{m}, @var{w1}, @var{w2}, @var{up}, @var{lo}, @var{gridsize}) Constrained L2 bandpass FIR filter design. This is a fast implementation of the algorithm cited below. Compared to @dfn{remez}, it offers implicit specification of transition bands, a higher likelihood of convergence, and an error criterion combining features of both L2 and Chebyshev approaches. Inputs: @table @var @item m degree of cosine polynomial, i.e. the number of output coefficients will be @var{m}*2+1 @item w1 @itemx w2 bandpass filter cutoffs in the range 0 <= @var{w1} < @var{w2} <= pi, where pi is the Nyquist frequency @item up vector of 3 upper bounds for [stopband1, passband, stopband2] @item lo vector of 3 lower bounds for [stopband1, passband, stopband2] @item gridsize search grid size; larger values may improve accuracy, but greatly increase calculation time. Default value is 2048, max value is 1e6. @end table Output: A vector of @var{m}*2+1 FIR coefficients, or an empty value if the solver failed to converge. Example: @example @code{h = cl2bp(30, 0.3*pi, 0.6*pi, [0.02, 1.02, 0.02], [-0.02, 0.98, -0.02], 2^11);} @end example Original Paper: I. W. Selesnick, M. Lang, and C. S. Burrus. A modified algorithm for constrained least square design of multiband FIR filters without specified transition bands. IEEE Trans. on Signal Processing, 46(2):497-501, February 1998. @end deftypefn @xseealso{remez} @c FIR Filter Design fir1 @c ----------------------------------------- @subsection fir1 @cindex fir1 @deftypefn {Function File} {@var{b} =} fir1 (@var{n}, @var{w}) @deftypefnx {Function File} {@var{b} =} fir1 (@var{n}, @var{w}, @var{type}) @deftypefnx {Function File} {@var{b} =} fir1 (@var{n}, @var{w}, @var{type}, @var{window}) @deftypefnx {Function File} {@var{b} =} fir1 (@var{n}, @var{w}, @var{type}, @var{window}, @var{noscale}) Produce an order @var{n} FIR filter with the given frequency cutoff @var{w}, returning the @var{n}+1 filter coefficients in @var{b}. If @var{w} is a scalar, it specifies the frequency cutoff for a lowpass or highpass filter. If @var{w} is a two-element vector, the two values specify the edges of a bandpass or bandstop filter. If @var{w} is an N-element vector, each value specifies a band edge of a multiband pass/stop filter. The filter @var{type} can be specified with one of the following strings: "low", "high", "stop", "pass", "bandpass", "DC-0", or "DC-1". The default is "low" is @var{w} is a scalar, "pass" if @var{w} is a pair, or "DC-0" if @var{w} is a vector with more than 2 elements. An optional shaping @var{window} can be given as a vector with length @var{n}+1. If not specified, a Hamming window of length @var{n}+1 is used. With the option "noscale", the filter coefficients are not normalized. The default is to normalize the filter such that the magnitude response of the center of the first passband is 1. To apply the filter, use the return vector @var{b} with the @code{filter} function, for example @code{y = filter (b, 1, x)}. Examples: @example freqz (fir1 (40, 0.3)); freqz (fir1 (15, [0.2, 0.5], "stop")); # note the zero-crossing at 0.1 freqz (fir1 (15, [0.2, 0.5], "stop", "noscale")); @end example @xseealso{filter, fir2} @end deftypefn @c FIR Filter Design fir2 @c ----------------------------------------- @subsection fir2 @cindex fir2 @deftypefn {Function File} {@var{b} =} fir2 (@var{n}, @var{f}, @var{m}) @deftypefnx {Function File} {@var{b} =} fir2 (@var{n}, @var{f}, @var{m}, @var{grid_n}) @deftypefnx {Function File} {@var{b} =} fir2 (@var{n}, @var{f}, @var{m}, @var{grid_n}, @var{ramp_n}) @deftypefnx {Function File} {@var{b} =} fir2 (@var{n}, @var{f}, @var{m}, @var{grid_n}, @var{ramp_n}, @var{window}) Produce an order @var{n} FIR filter with arbitrary frequency response @var{m} over frequency bands @var{f}, returning the @var{n}+1 filter coefficients in @var{b}. The vector @var{f} specifies the frequency band edges of the filter response and @var{m} specifies the magnitude response at each frequency. The vector @var{f} must be nondecreasing over the range [0,1], and the first and last elements must be 0 and 1, respectively. A discontinuous jump in the frequency response can be specified by duplicating a band edge in @var{f} with different values in @var{m}. The resolution over which the frequency response is evaluated can be controlled with the @var{grid_n} argument. The default is 512 or the next larger power of 2 greater than the filter length. The band transition width for discontinuities can be controlled with the @var{ramp_n} argument. The default is @var{grid_n}/25. Larger values will result in wider band transitions but better stopband rejection. An optional shaping @var{window} can be given as a vector with length @var{n}+1. If not specified, a Hamming window of length @var{n}+1 is used. To apply the filter, use the return vector @var{b} with the @code{filter} function, for example @code{y = filter (b, 1, x)}. Example: @example f = [0, 0.3, 0.3, 0.6, 0.6, 1]; m = [0, 0, 1, 1/2, 0, 0]; [h, w] = freqz (fir2 (100, f, m)); plot (f, m, ";target response;", w/pi, abs (h), ";filter response;"); @end example @xseealso{filter, fir1} @end deftypefn @c FIR Filter Design firls @c ----------------------------------------- @subsection firls @cindex firls @deftypefn {Function File} {@var{b} =} firls (@var{n}, @var{f}, @var{a}) @deftypefnx {Function File} {@var{b} =} firls (@var{n}, @var{f}, @var{a}, @var{w}) FIR filter design using least squares method. Returns a length @var{n}+1 linear phase filter such that the integral of the weighted mean squared error in the specified bands is minimized. The vector @var{f} specifies the frequencies of the band edges, normalized so that half the sample frequency is equal to 1. Each band is specified by two frequencies, to the vector must have an even length. The vector @var{a} specifies the amplitude of the desired response at each band edge. The optional argument @var{w} is a weighting function that contains one value for each band that weights the mean squared error in that band. @var{a} must be the same length as @var{f}, and @var{w} must be half the length of @var{f}. @var{n} must be even. If given an odd value, @code{firls} increments it by 1. The least squares optimization algorithm for computing FIR filter coefficients is derived in detail in: I. Selesnick, "Linear-Phase FIR Filter Design by Least Squares," http://cnx.org/content/m10577 @end deftypefn @c FIR Filter Design kaiserord @c ----------------------------------------- @subsection kaiserord @cindex kaiserord @deftypefn {Function File} {[@var{n}, @var{Wn}, @var{beta}, @var{ftype}] =} kaiserord (@var{f}, @var{m}, @var{dev}) @deftypefnx {Function File} {[@dots{}] =} kaiserord (@var{f}, @var{m}, @var{dev}, @var{fs}) Return the parameters needed to produce a filter of the desired specification from a Kaiser window. The vector @var{f} contains pairs of frequency band edges in the range [0,1]. The vector @var{m} specifies the magnitude response for each band. The values of @var{m} must be zero for all stop bands and must have the same magnitude for all pass bands. The deviation of the filter @var{dev} can be specified as a scalar or a vector of the same length as @var{m}. The optional sampling rate @var{fs} can be used to indicate that @var{f} is in Hz in the range [0,@var{fs}/2]. The returned value @var{n} is the required order of the filter (the length of the filter minus 1). The vector @var{Wn} contains the band edges of the filter suitable for passing to @code{fir1}. The value @var{beta} is the parameter of the Kaiser window of length @var{n}+1 to shape the filter. The string @var{ftype} contains the type of filter to specify to @code{fir1}. The Kaiser window parameters n and beta are computed from the relation between ripple (A=-20*log10(dev)) and transition width (dw in radians) discovered empirically by Kaiser: @example @group / 0.1102(A-8.7) A > 50 beta = | 0.5842(A-21)^0.4 + 0.07886(A-21) 21 <= A <= 50 \ 0.0 A < 21 n = (A-8)/(2.285 dw) @end group @end example Example: @example @group [n, w, beta, ftype] = kaiserord ([1000, 1200], [1, 0], [0.05, 0.05], 11025); b = fir1 (n, w, kaiser (n+1, beta), ftype, "noscale"); freqz (b, 1, [], 11025); @end group @end example @xseealso{fir1, kaiser} @end deftypefn @c FIR Filter Design qp_kaiser @c ----------------------------------------- @subsection qp_kaiser @cindex qp_kaiser @deftypefn {Function File} {} qp_kaiser (@var{nb}, @var{at}) @deftypefnx {Function File} {} qp_kaiser (@var{nb}, @var{at}, @var{linear}) Computes a finite impulse response (FIR) filter for use with a quasi-perfect reconstruction polyphase-network filter bank. This version utilizes a Kaiser window to shape the frequency response of the designed filter. Tha number nb of bands and the desired attenuation at in the stop-band are given as parameters. The Kaiser window is multiplied by the ideal impulse response h(n)=a.sinc(a.n) and converted to its minimum-phase version by means of a Hilbert transform. By using a third non-null argument, the minimum-phase calculation is omitted at all. @end deftypefn @c FIR Filter Design remez @c ----------------------------------------- @subsection remez @cindex remez @deftypefn {Loadable Function} {@var{b} =} remez (@var{n}, @var{f}, @var{a}) @deftypefnx {Loadable Function} {@var{b} =} remez (@var{n}, @var{f}, @var{a}, @var{w}) @deftypefnx {Loadable Function} {@var{b} =} remez (@var{n}, @var{f}, @var{a}, @var{w}, @var{ftype}) @deftypefnx {Loadable Function} {@var{b} =} remez (@var{n}, @var{f}, @var{a}, @var{w}, @var{ftype}, @var{griddensity}) Parks-McClellan optimal FIR filter design. @table @var @item n gives the filter order, where the generated filter length taps is n+1 @item f gives frequency at the band edges [b1 e1 b2 e2 b3 e3 @dots{}] @item a gives amplitude at the band edges [a(b1) a(e1) a(b2) a(e2) @dots{}] @item w gives weighting applied to each band @item ftype is "bandpass", "hilbert" or "differentiator" @item griddensity determines how accurately the filter will be constructed. The minimum value is 16, but higher numbers are slower to compute. @end table Frequency is in the range (0, 1), with 1 being the Nyquist frequency. @end deftypefn @c FIR Filter Design sgolay @c ----------------------------------------- @subsection sgolay @cindex sgolay @deftypefn {Function File} {@var{f} =} sgolay (@var{p}, @var{n}) @deftypefnx {Function File} {@var{f} =} sgolay (@var{p}, @var{n}, @var{m}) @deftypefnx {Function File} {@var{f} =} sgolay (@var{p}, @var{n}, @var{m}, @var{ts}) Computes the filter coefficients for all Savitzsky-Golay smoothing filters of order p for length n (odd). m can be used in order to get directly the mth derivative. In this case, ts is a scaling factor. The early rows of F smooth based on future values and later rows smooth based on past values, with the middle row using half future and half past. In particular, you can use row i to estimate x(k) based on the i-1 preceding values and the n-i following values of x values as y(k) = F(i,:) * x(k-i+1:k+n-i). Normally, you would apply the first (n-1)/2 rows to the first k points of the vector, the last k rows to the last k points of the vector and middle row to the remainder, but for example if you were running on a realtime system where you wanted to smooth based on the all the data collected up to the current time, with a lag of five samples, you could apply just the filter on row n-5 to your window of length n each time you added a new sample. Reference: Numerical recipes in C. p 650 @xseealso{sgolayfilt} @end deftypefn @c --------------------------------------------------- @node Transforms @section Transforms @cindex Transforms @c Transforms bitrevorder @c ----------------------------------------- @subsection bitrevorder @cindex bitrevorder @deftypefn {Function File} {@var{y} =} bitrevorder (@var{x}) @deftypefnx {Function File} {[@var{y} @var{i}] =} bitrevorder (@var{x}) Reorder the elements of the vector @var{x} in bit-reversed order. Equivalent to calling @code{digitrevorder (@var{x}, 2)}. @xseealso{digitrevorder, fft, ifft} @end deftypefn @c Transforms cceps @c ----------------------------------------- @subsection cceps @cindex cceps @deftypefn {Function File} {} cceps (@var{x}) @deftypefnx {Function File} {} cceps (@var{x}, @var{correct}) Return the complex cepstrum of the vector @var{x}. If the optional argument @var{correct} has the value 1, a correction method is applied. The default is not to do this. @end deftypefn @c Transforms cplxreal @c ----------------------------------------- @subsection cplxreal @cindex cplxreal @deftypefn {Function File} {[@var{zc}, @var{zr}] =} cplxreal (@var{z}) @deftypefnx {Function File} {[@var{zc}, @var{zr}] =} cplxreal (@var{z}, @var{tol}) @deftypefnx {Function File} {[@var{zc}, @var{zr}] =} cplxreal (@var{z}, @var{tol}, @var{dim}) Sort the numbers @var{z} into complex-conjugate-valued and real-valued elements. The positive imaginary complex numbers of each complex conjugate pair are returned in @var{zc} and the real numbers are returned in @var{zr}. @var{tol} is a weighting factor in the range [0, 1) which determines the tolerance of the matching. The default value is @code{100 * eps} and the resulting tolerance for a given complex pair is @code{@var{tol} * abs (@var{z}(i)))}. By default the complex pairs are sorted along the first non-singleton dimension of @var{z}. If @var{dim} is specified, then the complex pairs are sorted along this dimension. Signal an error if some complex numbers could not be paired. Signal an error if all complex numbers are not exact conjugates (to within @var{tol}). Note that there is no defined order for pairs with identical real parts but differing imaginary parts. @xseealso{cplxpair} @end deftypefn @c Transforms czt @c ----------------------------------------- @subsection czt @cindex czt @deftypefn {Function File} {} czt (@var{x}) @deftypefnx {Function File} {} czt (@var{x}, @var{m}) @deftypefnx {Function File} {} czt (@var{x}, @var{m}, @var{w}) @deftypefnx {Function File} {} czt (@var{x}, @var{m}, @var{w}, @var{a}) Chirp z-transform. Compute the frequency response starting at a and stepping by w for m steps. a is a point in the complex plane, and w is the ratio between points in each step (i.e., radius increases exponentially, and angle increases linearly). To evaluate the frequency response for the range f1 to f2 in a signal with sampling frequency Fs, use the following: @example @group m = 32; ## number of points desired w = exp(-j*2*pi*(f2-f1)/((m-1)*Fs)); ## freq. step of f2-f1/m a = exp(j*2*pi*f1/Fs); ## starting at frequency f1 y = czt(x, m, w, a); @end group @end example If you don't specify them, then the parameters default to a Fourier transform: m=length(x), w=exp(-j*2*pi/m), a=1 If x is a matrix, the transform will be performed column-by-column. @end deftypefn @c Transforms dct @c ----------------------------------------- @subsection dct @cindex dct @deftypefn {Function File} {} dct (@var{x}) @deftypefnx {Function File} {} dct (@var{x}, @var{n}) Compute the discrete cosine transform of @var{x}. If @var{n} is given, then @var{x} is padded or trimmed to length @var{n} before computing the transform. If @var{x} is a matrix, compute the transform along the columns of the the matrix. The transform is faster if @var{x} is real-valued and has even length. The discrete cosine transform @var{x} can be defined as follows: @example @group N-1 X[k] = w(k) sum x[n] cos (pi (2n+1) k / 2N ), k = 0, ..., N-1 n=0 @end group @end example with w(0) = sqrt(1/N) and w(k) = sqrt(2/N), k = 1, ..., N-1. There are other definitions with different scaling of X[k], but this form is common in image processing. @xseealso{idct, dct2, idct2, dctmtx} @end deftypefn @c Transforms dct2 @c ----------------------------------------- @subsection dct2 @cindex dct2 @deftypefn {Function File} {} dct2 (@var{x}) @deftypefnx {Function File} {} dct2 (@var{x}, @var{m}, @var{n}) @deftypefnx {Function File} {} dct2 (@var{x}, [@var{m}, @var{n}]) Compute the 2-D discrete cosine transform of matrix @var{x}. If @var{m} and @var{n} are specified, the input is padded or trimmed to the desired size. @xseealso{dct, idct, idct2} @end deftypefn @c Transforms dctmtx @c ----------------------------------------- @subsection dctmtx @cindex dctmtx @deftypefn {Function File} {} dctmtx (@var{n}) Return the DCT transformation matrix of size @var{n}-by-@var{n}. If A is an @var{n}-by-@var{n} matrix, then the following are true: @example @group T*A == dct(A), T'*A == idct(A) T*A*T' == dct2(A), T'*A*T == idct2(A) @end group @end example A DCT transformation matrix is useful for doing things like jpeg image compression, in which an 8x8 DCT matrix is applied to non-overlapping blocks throughout an image and only a subblock on the top left of each block is kept. During restoration, the remainder of the block is filled with zeros and the inverse transform is applied to the block. @xseealso{dct, idct, dct2, idct2} @end deftypefn @c Transforms dftmtx @c ----------------------------------------- @subsection dftmtx @cindex dftmtx @deftypefn {Function File} {@var{d} =} dftmtx (@var{n}) Compute the @var{n}-by-@var{n} Fourier transformation matrix. This is the matrix @var{d} such that the Fourier transform of a column vector of length @var{n} is given by @code{dftmtx(@var{n}) * @var{x}} and the inverse Fourier transform is given by @code{inv(dftmtx(@var{n})) * @var{x}}. In general this is less efficient than calling the @code{fft} and @code{ifft} functions directly. @xseealso{fft, ifft} @end deftypefn @c Transforms digitrevorder @c ----------------------------------------- @subsection digitrevorder @cindex digitrevorder @deftypefn {Function File} {@var{y} =} digitrevorder (@var{x}, @var{r}) @deftypefnx {Function File} {[@var{y}, @var{i}] =} digitrevorder (@var{x}, @var{r}) Reorder the elements of the vector @var{x} in digit-reversed order. The elements of @var{x} are converted to radix @var{r} and reversed. The reordered indices of the elements of @var{x} are returned in @var{i}. @xseealso{bitrevorder, fft, ifft} @end deftypefn @c Transforms dst @c ----------------------------------------- @subsection dst @cindex dst @deftypefn {Function File} {@var{y} =} dst (@var{x}) @deftypefnx {Function File} {@var{y} =} dst (@var{x}, @var{n}) Computes the type I discrete sine transform of @var{x}. If @var{n} is given, then @var{x} is padded or trimmed to length @var{n} before computing the transform. If @var{x} is a matrix, compute the transform along the columns of the the matrix. The discrete sine transform X of x can be defined as follows: @verbatim N X[k] = sum x[n] sin (pi n k / (N+1) ), k = 1, ..., N n=1 @end verbatim @xseealso{idst} @end deftypefn @c Transforms dwt @c ----------------------------------------- @subsection dwt @cindex dwt @deftypefn {Function File} {[@var{u}, @var{v}] =} dwt (@var{x}, @var{wname}) @deftypefnx {Function File} {[@var{u}, @var{v}] =} dwt (@var{x}, @var{Hp}, @var{Gp}) @deftypefnx {Function File} {[@var{u}, @var{v}] =} dwt (@var{x}, @var{Hp}, @var{Gp}, @dots{}) Discrete wavelet transform (1D). @strong{Inputs} @table @var @item x Signal vector. @item wname Wavelet name. @item Hp Coefficients of low-pass decomposition @acronym{FIR} filter. @item Gp Coefficients of high-pass decomposition @acronym{FIR} filter. @end table @strong{Outputs} @table @var @item u Signal vector of average, approximation. @item v Signal vector of difference, detail. @end table @end deftypefn @c Transforms fht @c ----------------------------------------- @subsection fht @cindex fht @deftypefn {Function File} {@var{m} =} fht (@var{d}) @deftypefnx {Function File} {@var{m} =} fht (@var{d}, @var{n}) @deftypefnx {Function File} {@var{m} =} fht (@var{d}, @var{n}, @var{dim}) Calculate the Fast Hartley Transform of real input @var{d}. If @var{d} is a matrix, the Hartley transform is calculated along the columns by default. The options @var{n} and @var{dim} are similar to the options of FFT function. The forward and inverse Hartley transforms are the same (except for a scale factor of 1/N for the inverse Hartley transform), but implemented using different functions. The definition of the forward hartley transform for vector d, @math{ m[K] = \sum_{i=0}^{N-1} d[i]*(cos[K*2*pi*i/N] + sin[K*2*pi*i/N]), for 0 <= K < N. m[K] = \sum_{i=0}^{N-1} d[i]*CAS[K*i], for 0 <= K < N. } @example fht(1:4) @end example @xseealso{ifht, fft} @end deftypefn @c Transforms fwht @c ----------------------------------------- @subsection fwht @cindex fwht @deftypefn {Function File} {} fwht (@var{x}) @deftypefnx {Function File} {} fwht (@var{x}, @var{n}) @deftypefnx {Function File} {} fwht (@var{x}, @var{n}, @var{order}) Compute the Walsh-Hadamard transform of @var{x} using the Fast Walsh-Hadamard Transform (FWHT) algorithm. If the input is a matrix, the FWHT is calculated along the columns of @var{x}. The number of elements of @var{x} must be a power of 2; if not, the input will be extended and filled with zeros. If a second argument is given, the input is truncated or extended to have length @var{n}. The third argument specifies the @var{order} in which the returned Walsh-Hadamard transform coefficients should be arranged. The @var{order} may be any of the following strings: @table @asis @item "sequency" The coefficients are returned in sequency order. This is the default if @var{order} is not given. @item "hadamard" The coefficients are returned in Hadamard order. @item "dyadic" The coefficients are returned in Gray code order. @end table @xseealso{ifwht} @end deftypefn @c Transforms hilbert @c ----------------------------------------- @subsection hilbert @cindex hilbert @deftypefn {Function File} {@var{h} =} hilbert (@var{f}, @var{N}, @var{dim}) Analytic extension of real valued signal. @code{@var{h} = hilbert (@var{f})} computes the extension of the real valued signal @var{f} to an analytic signal. If @var{f} is a matrix, the transformation is applied to each column. For N-D arrays, the transformation is applied to the first non-singleton dimension. @code{real (@var{h})} contains the original signal @var{f}. @code{imag (@var{h})} contains the Hilbert transform of @var{f}. @code{hilbert (@var{f}, @var{N})} does the same using a length @var{N} Hilbert transform. The result will also have length @var{N}. @code{hilbert (@var{f}, [], @var{dim})} or @code{hilbert (@var{f}, @var{N}, @var{dim})} does the same along dimension @var{dim}. @end deftypefn @c Transforms idct @c ----------------------------------------- @subsection idct @cindex idct @deftypefn {Function File} {@var{y} =} idct (@var{x}) @deftypefnx {Function File} {@var{y} =} idct (@var{x}, @var{n}) Compute the inverse discrete cosine transform of @var{x}. If @var{n} is given, then @var{x} is padded or trimmed to length @var{n} before computing the transform. If @var{x} is a matrix, compute the transform along the columns of the the matrix. The transform is faster if @var{x} is real-valued and even length. The inverse discrete cosine transform @var{x} can be defined as follows: @example N-1 x[n] = sum w(k) X[k] cos (pi (2n+1) k / 2N ), n = 0, ..., N-1 k=0 @end example with w(0) = sqrt(1/N) and w(k) = sqrt(2/N), k = 1, ..., N-1 @xseealso{dct, dct2, idct2, dctmtx} @end deftypefn @c Transforms idct2 @c ----------------------------------------- @subsection idct2 @cindex idct2 @deftypefn {Function File} {@var{y} =} idct2 (@var{x}) @deftypefnx {Function File} {@var{y} =} idct2 (@var{x}, @var{m}, @var{n}) @deftypefnx {Function File} {@var{y} =} idct2 (@var{x}, [@var{m}, @var{n}]) Compute the inverse 2-D discrete cosine transform of matrix @var{x}. If @var{m} and @var{n} are specified, the input is either padded or truncated to have @var{m} rows and @var{n} columns. @end deftypefn @c Transforms idst @c ----------------------------------------- @subsection idst @cindex idst @deftypefn {Function File} {@var{y} =} idst (@var{x}) @deftypefnx {Function File} {@var{y} =} idst (@var{x}, @var{n}) Computes the inverse type I discrete sine transform of @var{y}. If @var{n} is given, then @var{y} is padded or trimmed to length @var{n} before computing the transform. If @var{y} is a matrix, compute the transform along the columns of the the matrix. @xseealso{dst} @end deftypefn @c Transforms ifht @c ----------------------------------------- @subsection ifht @cindex ifht @deftypefn {Function File} {@var{m} =} ifht (@var{d}, @var{n}, @var{dim}) Calculate the inverse Fast Hartley Transform of real input @var{d}. If @var{d} is a matrix, the inverse Hartley transform is calculated along the columns by default. The options @var{n} and @var{dim} are similar to the options of FFT function. The forward and inverse Hartley transforms are the same (except for a scale factor of 1/N for the inverse hartley transform), but implemented using different functions. The definition of the forward hartley transform for vector d, @math{ m[K] = 1/N \sum_{i=0}^{N-1} d[i]*(cos[K*2*pi*i/N] + sin[K*2*pi*i/N]), for 0 <= K < N. m[K] = 1/N \sum_{i=0}^{N-1} d[i]*CAS[K*i], for 0 <= K < N. } @example ifht(1:4) @end example @xseealso{fht, fft} @end deftypefn @c Transforms ifwht @c ----------------------------------------- @subsection ifwht @cindex ifwht @deftypefn {Function File} {} ifwht (@var{x}) @deftypefnx {Function File} {} ifwht (@var{x}, @var{n}) @deftypefnx {Function File} {} ifwht (@var{x}, @var{n}, @var{order}) Compute the inverse Walsh-Hadamard transform of @var{x} using the Fast Walsh-Hadamard Transform (FWHT) algorithm. If the input is a matrix, the inverse FWHT is calculated along the columns of @var{x}. The number of elements of @var{x} must be a power of 2; if not, the input will be extended and filled with zeros. If a second argument is given, the input is truncated or extended to have length @var{n}. The third argument specifies the @var{order} in which the returned inverse Walsh-Hadamard transform coefficients should be arranged. The @var{order} may be any of the following strings: @table @asis @item "sequency" The coefficients are returned in sequency order. This is the default if @var{order} is not given. @item "hadamard" The coefficients are returned in Hadamard order. @item "dyadic" The coefficients are returned in Gray code order. @end table @xseealso{fwht} @end deftypefn @c Transforms rceps @c ----------------------------------------- @subsection rceps @cindex rceps @deftypefn {Function File} {[@var{y}, @var{ym}] =} rceps (@var{x}) Return the cepstrum of the signal @var{x}. If @var{x} is a matrix, return the cepstrum of each column. If called with two output arguments, the minimum phase reconstruction of the signal @var{x} is returned in @var{ym}. For example: @example @group f0 = 70; Fs = 10000; # 100 Hz fundamental, 10kHz sampling rate a = poly (0.985 * exp (1i * pi * [0.1, -0.1, 0.3, -0.3])); # two formants s = 0.005 * randn (1024, 1); # Noise excitation signal s(1:Fs/f0:length(s)) = 1; # Impulse glottal wave x = filter (1, a, s); # Speech signal [y, ym] = rceps (x .* hanning (1024)); @end group @end example Reference: @cite{Programs for Digital Signal Processing}, IEEE Press, John Wiley & Sons, New York, 1979. @end deftypefn @c --------------------------------------------------- @node Power Spectrum Analysis @section Power Spectrum Analysis @cindex Power Spectrum Analysis @c Power Spectrum Analysis __power @c ----------------------------------------- @subsection __power @cindex __power @deftypefn {Function File} {[@var{P}, @var{w}] =} __power (@var{b}, @var{a}) @deftypefnx {Function File} {[@dots{}] =} __power (@var{b}, @var{a}, @var{nfft}) @deftypefnx {Function File} {[@dots{}] =} __power (@var{b}, @var{a}, @var{nfft}, @var{Fs}) @deftypefnx {Function File} {[@dots{}] =} __power (@var{b}, @var{a}, @var{nfft}, @var{Fs}, @var{range}) @deftypefnx {Function File} {[@dots{}] =} __power (@var{b}, @var{a}, @var{nfft}, @var{Fs}, @var{range}, @var{units}) @deftypefnx {Function File} {} __power (@dots{}) Plot the power spectrum of the given ARMA model. b, a: filter coefficients (b=numerator, a=denominator) nfft is number of points at which to sample the power spectrum Fs is the sampling frequency of x range is 'half' (default) or 'whole' units is 'squared' or 'db' (default) range and units may be specified any time after the filter, in either order Returns P, the magnitude vector, and w, the frequencies at which it is sampled. If there are no return values requested, then plot the power spectrum and don't return anything. @end deftypefn @c Power Spectrum Analysis ar_psd @c ----------------------------------------- @subsection ar_psd @cindex ar_psd @deftypefn {Function File} {} ar_psd (@var{a}, @var{v}) @deftypefnx {Function File} {} ar_psd (@var{a}, @var{v}, @var{freq}) @deftypefnx {Function File} {} ar_psd (@var{a}, @var{v}, @var{freq}, @var{Fs}) @deftypefnx {Function File} {} ar_psd (@dots{}, @var{range}) @deftypefnx {Function File} {} ar_psd (@dots{}, @var{method}) @deftypefnx {Function File} {} ar_psd (@dots{}, @var{plottype}) @deftypefnx {Function File} {[@var{psd}, @var{f_out}] =} ar_psd (@dots{}) Calculate the power spectrum of the autoregressive model @example @group M x(n) = sqrt(v).e(n) + SUM a(k).x(n-k) k=1 @end group @end example where @math{x(n)} is the output of the model and @math{e(n)} is white noise. This function is intended for use with @code{[a, v, k] = arburg (x, poles, criterion)} which use the Burg (1968) method to calculate a "maximum entropy" autoregressive model of @var{x}. If the @var{freq} argument is a vector (of frequencies) the spectrum is calculated using the polynomial method and the @var{method} argument is ignored. For scalar @var{freq}, an integer power of 2, or @var{method} = "FFT", causes the spectrum to be calculated by FFT. Otherwise, the spectrum is calculated as a polynomial. It may be computationally more efficient to use the FFT method if length of the model is not much smaller than the number of frequency values. The spectrum is scaled so that spectral energy (area under spectrum) is the same as the time-domain energy (mean square of the signal). ARGUMENTS: All but the first two arguments are optional and may be empty. @itemize @item @var{a} list of M=(order+1) autoregressive model coefficients. The first element of "ar_coeffs" is the zero-lag coefficient, which always has a value of 1. @item @var{v} square of the moving-average coefficient of the AR model. @item @var{freq} frequencies at which power spectral density is calculated, or a scalar indicating the number of uniformly distributed frequency values at which spectral density is calculated. (default = 256) @item @var{Fs} sampling frequency (Hertz) (default=1) @end itemize CONTROL-STRING ARGUMENTS -- each of these arguments is a character string. Control-string arguments can be in any order after the other arguments. Range: 'half', 'onesided' : frequency range of the spectrum is from zero up to but not including sample_f/2. Power from negative frequencies is added to the positive side of the spectrum. 'whole', 'twosided' : frequency range of the spectrum is -sample_f/2 to sample_f/2, with negative frequencies stored in "wrap around" order after the positive frequencies; e.g. frequencies for a 10-point 'twosided' spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 'shift', 'centerdc' : same as 'whole' but with the first half of the spectrum swapped with second half to put the zero-frequency value in the middle. (See "help fftshift". If "freq" is vector, 'shift' is ignored. If model coefficients "ar_coeffs" are real, the default range is 'half', otherwise default range is 'whole'. Method: 'fft': use FFT to calculate power spectrum. 'poly': calculate power spectrum as a polynomial of 1/z N.B. this argument is ignored if the "freq" argument is a vector. The default is 'poly' unless the "freq" argument is an integer power of 2. Plot type: 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': specifies the type of plot. The default is 'plot', which means linear-linear axes. 'squared' is the same as 'plot'. 'dB' plots "10*log10(psd)". This argument is ignored and a spectrum is not plotted if the caller requires a returned value. RETURNED VALUES: If returned values are not required by the caller, the spectrum is plotted and nothing is returned. @itemize @item @var{psd} estimate of power-spectral density @item @var{f_out} frequency values @end itemize REFERENCE [1] Equation 2.28 from Steven M. Kay and Stanley Lawrence Marple Jr.: "Spectrum analysis -- a modern perspective", Proceedings of the IEEE, Vol 69, pp 1380-1419, Nov., 1981 @end deftypefn @c Power Spectrum Analysis cohere @c ----------------------------------------- @subsection cohere @cindex cohere @deftypefn {Function File} {[@var{Pxx}, @var{freq}]} = cohere(@var{x},@var{y},@var{Nfft},@var{Fs},@var{window},@var{overlap},@var{range},@var{plot_type},@var{detrend}) Estimate (mean square) coherence of signals "x" and "y". Use the Welch (1967) periodogram/FFT method. Compatible with Matlab R11 cohere and earlier. See "help pwelch" for description of arguments, hints and references --- especially hint (7) for Matlab R11 defaults. @end deftypefn @c Power Spectrum Analysis cpsd @c ----------------------------------------- @subsection cpsd @cindex cpsd @deftypefn {Function File} {[@var{Pxx}, @var{freq}] =} cpsd (@var{x}, @var{y}) @deftypefnx {Function File} {[@dots{}] =} cpsd (@var{x}, @var{y}, @var{window}) @deftypefnx {Function File} {[@dots{}] =} cpsd (@var{x}, @var{y}, @var{window}, @var{overlap}) @deftypefnx {Function File} {[@dots{}] =} cpsd (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}) @deftypefnx {Function File} {[@dots{}] =} cpsd (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}) @deftypefnx {Function File} {[@dots{}] =} cpsd (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}, @var{range}) @deftypefnx {Function File} {} cpsd (@dots{}) Estimate cross power spectrum of data @var{x} and @var{y} by the Welch (1967) periodogram/FFT method. @xseealso{pwelch} @end deftypefn @c Power Spectrum Analysis csd @c ----------------------------------------- @subsection csd @cindex csd @deftypefn {Function File} {[@var{Pxx},@var{freq}]} = csd(@var{x}, @var{y}, @var{Nfft}, @var{Fs}, @var{window}, @var{overlap}, @var{range}, @var{plot_type}, @var{detrend}) Estimate cross power spectrum of data "x" and "y" by the Welch (1967) periodogram/FFT method. Compatible with Matlab R11 csd and earlier. See "help pwelch" for description of arguments, hints and references --- especially hint (7) for Matlab R11 defaults. @end deftypefn @c Power Spectrum Analysis db2pow @c ----------------------------------------- @subsection db2pow @cindex db2pow @deftypefn {Function File} {} db2pow (@var{x}) Convert decibels (dB) to power. The power of @var{x} is defined as @tex $p = 10^{x/10}$. @end tex @ifnottex @var{p} = @code{10 ^ (x/10)}. @end ifnottex If @var{x} is a vector, matrix, or N-dimensional array, the power is computed over the elements of @var{x}. Example: @example @group db2pow ([-10, 0, 10]) @result{} 0.1000 1.0000 10.0000 @end group @end example @xseealso{pow2db} @end deftypefn @c Power Spectrum Analysis mscohere @c ----------------------------------------- @subsection mscohere @cindex mscohere @deftypefn {Function File} {[@var{Pxx}, @var{freq}] =} mscohere (@var{x}, @var{y}) @deftypefnx {Function File} {[@dots{}] =} mscohere (@var{x}, @var{y}, @var{window}) @deftypefnx {Function File} {[@dots{}] =} mscohere (@var{x}, @var{y}, @var{window}, @var{overlap}) @deftypefnx {Function File} {[@dots{}] =} mscohere (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}) @deftypefnx {Function File} {[@dots{}] =} mscohere (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}) @deftypefnx {Function File} {[@dots{}] =} mscohere (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}, @var{range}) @deftypefnx {Function File} {} mscohere (@dots{}) Estimate (mean square) coherence of signals @var{x} and @var{y}. Use the Welch (1967) periodogram/FFT method. @xseealso{pwelch} @end deftypefn @c Power Spectrum Analysis pburg @c ----------------------------------------- @subsection pburg @cindex pburg @deftypefn {Function File} {[@var{psd},@var{f_out}] =} pburg(@var{x}, @var{poles}, @var{freq}, @var{Fs}, @var{range}, @var{method}, @var{plot_type}, @var{criterion}) Calculate Burg maximum-entropy power spectral density. The functions "arburg" and "ar_psd" do all the work. See "help arburg" and "help ar_psd" for further details. ARGUMENTS: All but the first two arguments are optional and may be empty. @table @asis @item x [vector] sampled data @item poles [integer scalar] required number of poles of the AR model @item freq [real vector] frequencies at which power spectral density is calculated. [integer scalar] number of uniformly distributed frequency values at which spectral density is calculated. [default=256] @item Fs [real scalar] sampling frequency (Hertz) [default=1] @end table CONTROL-STRING ARGUMENTS -- each of these arguments is a character string. Control-string arguments can be in any order after the other arguments. @table @asis @item range 'half', 'onesided' : frequency range of the spectrum is from zero up to but not including sample_f/2. Power from negative frequencies is added to the positive side of the spectrum. 'whole', 'twosided' : frequency range of the spectrum is -sample_f/2 to sample_f/2, with negative frequencies stored in "wrap around" order after the positive frequencies; e.g. frequencies for a 10-point 'twosided' spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 'shift', 'centerdc' : same as 'whole' but with the first half of the spectrum swapped with second half to put the zero-frequency value in the middle. (See "help fftshift". If "freq" is vector, 'shift' is ignored. If model coefficients "ar_coeffs" are real, the default range is 'half', otherwise default range is 'whole'. @item method 'fft': use FFT to calculate power spectral density. 'poly': calculate spectral density as a polynomial of 1/z N.B. this argument is ignored if the "freq" argument is a vector. The default is 'poly' unless the "freq" argument is an integer power of 2. @item plot_type 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': specifies the type of plot. The default is 'plot', which means linear-linear axes. 'squared' is the same as 'plot'. 'dB' plots "10*log10(psd)". This argument is ignored and a spectrum is not plotted if the caller requires a returned value. @item criterion [optional string arg] model-selection criterion. Limits the number of poles so that spurious poles are not added when the whitened data has no more information in it (see Kay & Marple, 1981). Recognized values are 'AKICc' -- approximate corrected Kullback information criterion (recommended), 'KIC' -- Kullback information criterion 'AICc' -- corrected Akaike information criterion 'AIC' -- Akaike information criterion 'FPE' -- final prediction error" criterion The default is to NOT use a model-selection criterion @end table RETURNED VALUES: If return values are not required by the caller, the spectrum is plotted and nothing is returned. @table @asis @item psd [real vector] power-spectral density estimate @item f_out [real vector] frequency values @end table HINTS This function is a wrapper for arburg and ar_psd. See "help arburg", "help ar_psd". @end deftypefn @c Power Spectrum Analysis pow2db @c ----------------------------------------- @subsection pow2db @cindex pow2db @deftypefn {Function File} {} pow2db (@var{x}) Convert power to decibels (dB). The decibel value of @var{x} is defined as @tex $d = 10 * \log_{10} (x)$. @end tex @ifnottex @var{d} = @code{10 * log10 (x)}. @end ifnottex If @var{x} is a vector, matrix, or N-dimensional array, the decibel value is computed over the elements of @var{x}. Examples: @example @group pow2db ([0, 10, 100]) @result{} -Inf 10 20 @end group @end example @xseealso{db2pow} @end deftypefn @c Power Spectrum Analysis pwelch @c ----------------------------------------- @subsection pwelch @cindex pwelch @deftypefn {Function File} {[@var{spectra},@var{freq}] =} pwelch(@var{x}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}, @var{range}, @var{plot_type}, @var{detrend}, @var{sloppy}) Estimate power spectral density of data "x" by the Welch (1967) periodogram/FFT method. All arguments except "x" are optional. The data is divided into segments. If "window" is a vector, each segment has the same length as "window" and is multiplied by "window" before (optional) zero-padding and calculation of its periodogram. If "window" is a scalar, each segment has a length of "window" and a Hamming window is used. The spectral density is the mean of the periodograms, scaled so that area under the spectrum is the same as the mean square of the data. This equivalence is supposed to be exact, but in practice there is a mismatch of up to 0.5% when comparing area under a periodogram with the mean square of the data. [spectra,freq] = pwelch(x,y,window,overlap,Nfft,Fs, range,plot_type,detrend,sloppy,results) Two-channel spectrum analyser. Estimate power spectral density, cross- spectral density, transfer function and/or coherence functions of time- series input data "x" and output data "y" by the Welch (1967) periodogram/FFT method. pwelch treats the second argument as "y" if there is a control-string argument "cross", "trans", "coher" or "ypower"; "power" does not force the 2nd argument to be treated as "y". All other arguments are optional. All spectra are returned in matrix "spectra". [spectra,Pxx_ci,freq] = pwelch(x,window,overlap,Nfft,Fs,conf, range,plot_type,detrend,sloppy) [spectra,Pxx_ci,freq] = pwelch(x,y,window,overlap,Nfft,Fs,conf, range,plot_type,detrend,sloppy,results) Estimates confidence intervals for the spectral density. See Hint (7) below for compatibility options. Confidence level "conf" is the 6th or 7th numeric argument. If "results" control-string arguments are used, one of them must be "power" when the "conf" argument is present; pwelch can estimate confidence intervals only for the power spectrum of the "x" data. It does not know how to estimate confidence intervals of the cross-power spectrum, transfer function or coherence; if you can suggest a good method, please send a bug report. ARGUMENTS All but the first argument are optional and may be empty, except that the "results" argument may require the second argument to be "y". @table @asis @item x [non-empty vector] system-input time-series data @item y [non-empty vector] system-output time-series data @item window [real vector] of window-function values; the data segment has the same length as the window. Default window shape is Hamming. [integer scalar] length of each data segment. The default value is window=sqrt(length(x)) rounded up to the nearest integer power of 2; see 'sloppy' argument. @item overlap [real scalar] segment overlap expressed as a multiple of window or segment length. 0 <= overlap < 1, The default is overlap=0.5 . @item Nfft [integer scalar] Length of FFT. The default is the length of the "window" vector or has the same value as the scalar "window" argument. If Nfft is larger than the segment length, "seg_len", the data segment is padded with "Nfft-seg_len" zeros. The default is no padding. Nfft values smaller than the length of the data segment (or window) are ignored silently. @item Fs [real scalar] sampling frequency (Hertz); default=1.0 @item conf [real scalar] confidence level between 0 and 1. Confidence intervals of the spectral density are estimated from scatter in the periodograms and are returned as Pxx_ci. Pxx_ci(:,1) is the lower bound of the confidence interval and Pxx_ci(:,2) is the upper bound. If there are three return values, or conf is an empty matrix, confidence intervals are calculated for conf=0.95 . If conf is zero or is not given, confidence intervals are not calculated. Confidence intervals can be obtained only for the power spectral density of x; nothing else. @end table CONTROL-STRING ARGUMENTS -- each of these arguments is a character string. Control-string arguments must be after the other arguments but can be in any order. @table @asis @item range 'half', 'onesided' : frequency range of the spectrum is zero up to but not including Fs/2. Power from negative frequencies is added to the positive side of the spectrum, but not at zero or Nyquist (Fs/2) frequencies. This keeps power equal in time and spectral domains. See reference [2]. 'whole', 'twosided' : frequency range of the spectrum is -Fs/2 to Fs/2, with negative frequencies stored in "wrap around" order after the positive frequencies; e.g. frequencies for a 10-point 'twosided' spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 'shift', 'centerdc' : same as 'whole' but with the first half of the spectrum swapped with second half to put the zero-frequency value in the middle. (See "help fftshift". If data (x and y) are real, the default range is 'half', otherwise default range is 'whole'. @item plot_type 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': specifies the type of plot. The default is 'plot', which means linear-linear axes. 'squared' is the same as 'plot'. 'dB' plots "10*log10(psd)". This argument is ignored and a spectrum is not plotted if the caller requires a returned value. @item detrend 'no-strip', 'none' -- do NOT remove mean value from the data 'short', 'mean' -- remove the mean value of each segment from each segment of the data. 'linear', -- remove linear trend from each segment of the data. 'long-mean' -- remove the mean value from the data before splitting it into segments. This is the default. @item sloppy 'sloppy': FFT length is rounded up to the nearest integer power of 2 by zero padding. FFT length is adjusted after addition of padding by explicit Nfft argument. The default is to use exactly the FFT and window/ segment lengths specified in argument list. @item results specifies what results to return (in the order specified and as many as desired). 'power' calculate power spectral density of "x" 'cross' calculate cross spectral density of "x" and "y" 'trans' calculate transfer function of a system with input "x" and output "y" 'coher' calculate coherence function of "x" and "y" 'ypower' calculate power spectral density of "y" The default is 'power', with argument "y" omitted. @end table RETURNED VALUES: If return values are not required by the caller, the results are plotted and nothing is returned. @table @asis @item spectra [real-or-complex matrix] columns of the matrix contain results in the same order as specified by "results" arguments. Each column contains one of the result vectors. @item Pxx_ci [real matrix] estimate of confidence interval for power spectral density of x. First column is the lower bound. Second column is the upper bound. @item freq [real column vector] frequency values @end table HINTS @enumerate @item EMPTY ARGS: if you don't want to use an optional argument you can leave it empty by writing its value as []. @item FOR BEGINNERS: The profusion of arguments may make pwelch difficult to use, and an unskilled user can easily produce a meaningless result or can easily mis-interpret the result. With real data "x" and sampling frequency "Fs", the easiest and best way for a beginner to use pwelch is probably "pwelch(x,[],[],[],Fs)". Use the "window" argument to control the length of the spectrum vector. For real data and integer scalar M, "pwelch(x,2*M,[],[],Fs)" gives an M+1 point spectrum. Run "demo pwelch" (octave only). @item WINDOWING FUNCTIONS: Without a window function, sharp spectral peaks can have strong sidelobes because the FFT of a data in a segment is in effect convolved with a rectangular window. A window function which tapers off (gradually) at the ends produces much weaker sidelobes in the FFT. Hann (hanning), hamming, bartlett, blackman, flattopwin etc are available as separate Matlab/sigproc or Octave functions. The sidelobes of the Hann window have a roll-off rate of 60dB/decade of frequency. The first sidelobe of the Hamming window is suppressed and is about 12dB lower than the first Hann sidelobe, but the roll-off rate is only 20dB/decade. You can inspect the FFT of a Hann window by plotting "abs(fft(postpad(hanning(256),4096,0)))". The default window is Hamming. @item ZERO PADDING: Zero-padding reduces the frequency step in the spectrum, and produces an artificially smoothed spectrum. For example, "Nfft=2*length(window)" gives twice as many frequency values, but adjacent PSD (power spectral density) values are not independent; adjacent PSD values are independent if "Nfft=length(window)", which is the default value of Nfft. @item REMOVING MEAN FROM SIGNAL: If the mean is not removed from the signal there is a large spectral peak at zero frequency and the sidelobes of this peak are likely to swamp the rest of the spectrum. For this reason, the default behavior is to remove the mean. However, the matlab pwelch does not do this. @item WARNING ON CONFIDENCE INTERVALS Confidence intervals are obtained by measuring the sample variance of the periodograms and assuming that the periodograms have a Gaussian probability distribution. This assumption is not accurate. If, for example, the data (x) is Gaussian, the periodogram has a Rayleigh distribution. However, the confidence intervals may still be useful. @item COMPATIBILITY WITH Matlab R11, R12, etc When used without the second data (y) argument, arguments are compatible with the pwelch of Matlab R12, R13, R14, 2006a and 2006b except that 1) overlap is expressed as a multiple of window length --- effect of overlap scales with window length 2) default values of length(window), Nfft and Fs are more sensible, and 3) Goertzel algorithm is not available so Nfft cannot be an array of frequencies as in Matlab 2006b. Pwelch has four persistent Matlab-compatibility levels. Calling pwelch with an empty first argument sets the order of arguments and defaults specified above in the USAGE and ARGUMENTS section of this documentation. @example prev_compat=pwelch([]); [Pxx,f]=pwelch(x,window,overlap,Nfft,Fs,conf,...); @end example Calling pwelch with a single string argument (as described below) gives compatibility with Matlab R11 or R12, or the R14 spectrum.welch defaults. The returned value is the PREVIOUS compatibility string. Matlab R11: For compatibility with the Matlab R11 pwelch: @example prev_compat=pwelch('R11-'); [Pxx,f]=pwelch(x,Nfft,Fs,window,overlap,conf,range,units); %% units of overlap are "number of samples" %% defaults: Nfft=min(length(x),256), Fs=2*pi, length(window)=Nfft, %% window=Hanning, do not detrend, %% N.B. "Sloppy" is not available. @end example Matlab R12: For compatibility with Matlab R12 to 2006a pwelch: @example prev_compat=pwelch('R12+'); [Pxx,f]=pwelch(x,window,overlap,nfft,Fs,...); %% units of overlap are "number of samples" %% defaults: length(window)==length(x)/8, window=Hamming, %% Nfft=max(256,NextPow2), Fs=2*pi, do not detrend %% NextPow2 is the next power of 2 greater than or equal to the %% window length. "Sloppy", "conf" are not available. Default %% window length gives very poor amplitude resolution. @end example To adopt defaults of the Matlab R14 "spectrum.welch" spectrum object associated "psd" method. @example prev_compat=pwelch('psd'); [Pxx,f] = pwelch(x,window,overlap,Nfft,Fs,conf,...); %% overlap is expressed as a percentage of window length, %% defaults: length(window)==64, Nfft=max(256,NextPow2), Fs=2*pi %% do not detrend %% NextPow2 is the next power of 2 greater than or equal to the %% window length. "Sloppy" is not available. %% Default window length gives coarse frequency resolution. @end example @end enumerate REFERENCES [1] Peter D. Welch (June 1967): "The use of fast Fourier transform for the estimation of power spectra: a method based on time averaging over short, modified periodograms." IEEE Transactions on Audio Electroacoustics, Vol AU-15(6), pp 70-73 [2] William H. Press and Saul A. Teukolsky and William T. Vetterling and Brian P. Flannery", "Numerical recipes in C, The art of scientific computing", 2nd edition, Cambridge University Press, 2002 --- Section 13.7. @end deftypefn @c Power Spectrum Analysis pyulear @c ----------------------------------------- @subsection pyulear @cindex pyulear @deftypefn {Function File} {[psd,f_out] =} pyulear(x,poles,freq,Fs,range,method,plot_type) Calculates a Yule-Walker autoregressive (all-pole) model of the data "x" and computes the power spectrum of the model. This is a wrapper for functions "aryule" and "ar_psd" which perform the argument checking. See "help aryule" and "help ar_psd" for further details. ARGUMENTS: All but the first two arguments are optional and may be empty. @table @asis @item x [vector] sampled data @item poles [integer scalar] required number of poles of the AR model @item freq [real vector] frequencies at which power spectral density is calculated [integer scalar] number of uniformly distributed frequency values at which spectral density is calculated. [default=256] @item Fs [real scalar] sampling frequency (Hertz) [default=1] @end table CONTROL-STRING ARGUMENTS -- each of these arguments is a character string. Control-string arguments can be in any order after the other arguments. @table @asis @item range 'half', 'onesided' : frequency range of the spectrum is from zero up to but not including sample_f/2. Power from negative frequencies is added to the positive side of the spectrum. 'whole', 'twosided' : frequency range of the spectrum is -sample_f/2 to sample_f/2, with negative frequencies stored in "wrap around" order after the positive frequencies; e.g. frequencies for a 10-point 'twosided' spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 'shift', 'centerdc' : same as 'whole' but with the first half of the spectrum swapped with second half to put the zero-frequency value in the middle. (See "help fftshift". If "freq" is vector, 'shift' is ignored. If model coefficients "ar_coeffs" are real, the default range is 'half', otherwise default range is 'whole'. @item method 'fft': use FFT to calculate power spectrum. 'poly': calculate power spectrum as a polynomial of 1/z N.B. this argument is ignored if the "freq" argument is a vector. The default is 'poly' unless the "freq" argument is an integer power of 2. @item plot_type 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': specifies the type of plot. The default is 'plot', which means linear-linear axes. 'squared' is the same as 'plot'. 'dB' plots "10*log10(psd)". This argument is ignored and a spectrum is not plotted if the caller requires a returned value. @end table RETURNED VALUES: If return values are not required by the caller, the spectrum is plotted and nothing is returned. @table @asis @item psd [real vector] power-spectrum estimate @item f_out [real vector] frequency values @end table HINTS This function is a wrapper for aryule and ar_psd. See "help aryule", "help ar_psd". @end deftypefn @c Power Spectrum Analysis tfe @c ----------------------------------------- @subsection tfe @cindex tfe @deftypefn {Function File} {[Pxx,freq] =} tfe(x,y,Nfft,Fs,window,overlap,range,plot_type,detrend) Estimate transfer function of system with input "x" and output "y". Use the Welch (1967) periodogram/FFT method. Compatible with Matlab R11 tfe and earlier. See "help pwelch" for description of arguments, hints and references --- especially hint (7) for Matlab R11 defaults. @end deftypefn @c Power Spectrum Analysis tfestimate @c ----------------------------------------- @subsection tfestimate @cindex tfestimate @deftypefn {Function File} {} tfestimate (@var{x}, @var{y}) @deftypefnx {Function File} {} tfestimate (@var{x}, @var{y}, @var{window}) @deftypefnx {Function File} {} tfestimate (@var{x}, @var{y}, @var{window}, @var{overlap}) @deftypefnx {Function File} {} tfestimate (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}) @deftypefnx {Function File} {} tfestimate (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}) @deftypefnx {Function File} {} tfestimate (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}, @var{range}) @deftypefnx {Function File} {[@var{Pxx}, @var{freq}] =} tfestimate (@dots{}) Estimate transfer function of system with input @var{x} and output @var{y}. Use the Welch (1967) periodogram/FFT method. @xseealso{pwelch} @end deftypefn @c --------------------------------------------------- @node Window Functions @section Window Functions @cindex Window Functions @c Window Functions barthannwin @c ----------------------------------------- @subsection barthannwin @cindex barthannwin @deftypefn {Function File} {} barthannwin (@var{m}) Return the filter coefficients of a modified Bartlett-Hann window of length @var{m}. @xseealso{rectwin, bartlett} @end deftypefn @c Window Functions blackmanharris @c ----------------------------------------- @subsection blackmanharris @cindex blackmanharris @deftypefn {Function File} {} blackmanharris (@var{m}) @deftypefnx {Function File} {} blackmanharris (@var{m}, "periodic") @deftypefnx {Function File} {} blackmanharris (@var{m}, "symmetric") Return the filter coefficients of a Blackman-Harris window of length @var{m}. If the optional argument @code{"periodic"} is given, the periodic form of the window is returned. This is equivalent to the window of length @var{m}+1 with the last coefficient removed. The optional argument @code{"symmetric"} is equivalent to not specifying a second argument. @xseealso{rectwin, bartlett} @end deftypefn @c Window Functions blackmannuttall @c ----------------------------------------- @subsection blackmannuttall @cindex blackmannuttall @deftypefn {Function File} {} blackmannuttall (@var{m}) @deftypefnx {Function File} {} blackmannuttall (@var{m}, "periodic") @deftypefnx {Function File} {} blackmannuttall (@var{m}, "symmetric") Return the filter coefficients of a Blackman-Nuttall window of length @var{m}. If the optional argument @code{"periodic"} is given, the periodic form of the window is returned. This is equivalent to the window of length @var{m}+1 with the last coefficient removed. The optional argument @code{"symmetric"} is equivalent to not specifying a second argument. @xseealso{nuttallwin, kaiser} @end deftypefn @c Window Functions bohmanwin @c ----------------------------------------- @subsection bohmanwin @cindex bohmanwin @deftypefn {Function File} {} bohmanwin (@var{m}) Return the filter coefficients of a Bohman window of length @var{m}. @xseealso{rectwin, bartlett} @end deftypefn @c Window Functions boxcar @c ----------------------------------------- @subsection boxcar @cindex boxcar @deftypefn {Function File} {} boxcar (@var{m}) Return the filter coefficients of a rectangular window of length @var{m}. @end deftypefn @c Window Functions chebwin @c ----------------------------------------- @subsection chebwin @cindex chebwin @deftypefn {Function File} {} chebwin (@var{m}) @deftypefnx {Function File} {} chebwin (@var{m}, @var{at}) Return the filter coefficients of a Dolph-Chebyshev window of length @var{m}. The Fourier transform of the window has a stop-band attenuation of @var{at} dB. The default attenuation value is 100 dB. For the definition of the Chebyshev window, see * Peter Lynch, "The Dolph-Chebyshev Window: A Simple Optimal Filter", Monthly Weather Review, Vol. 125, pp. 655-660, April 1997. (http://www.maths.tcd.ie/~plynch/Publications/Dolph.pdf) * C. Dolph, "A current distribution for broadside arrays which optimizes the relationship between beam width and side-lobe level", Proc. IEEE, 34, pp. 335-348. The window is described in frequency domain by the expression: @example @group Cheb(m-1, beta * cos(pi * k/m)) W(k) = ------------------------------- Cheb(m-1, beta) @end group @end example with @example @group beta = cosh(1/(m-1) * acosh(10^(at/20)) @end group @end example and Cheb(m,x) denoting the m-th order Chebyshev polynomial calculated at the point x. Note that the denominator in W(k) above is not computed, and after the inverse Fourier transform the window is scaled by making its maximum value unitary. @xseealso{kaiser} @end deftypefn @c Window Functions expwin @c ----------------------------------------- @subsection expwin @cindex expwin @deftypefn {Function File} expwin (@var{m}, @var{alpha}) @deftypefnx {Function File} expwin (@var{m}, @var{sll}) @deftypefnx {Function File} expwin (@dots{}, "canonical") Return the coefficients of an exponential window@footnote{K. Avci & A. Nacaroglu, `Exponential Window Family', SIPIJ Vol.@: 4 No.@: 4, August 2013.} of length @var{m}. The window's adjustable parameter can be set directly as @var{alpha} (@geq{}0) or indirectly with @var{sll} (<0), the latter being the desired side-lobe level in dBc. By default, the returned window is both symmetric and periodic. With the optional argument @qcode{"canonical"}, the canonical form of the window is returned, which is symmetric but not periodic. @xseealso{kaiser, poisswin} @end deftypefn @c Window Functions flattopwin @c ----------------------------------------- @subsection flattopwin @cindex flattopwin @deftypefn {Function File} {} flattopwin (@var{m}) @deftypefnx {Function File} {} flattopwin (@var{m}, "periodic") @deftypefnx {Function File} {} flattopwin (@var{m}, "symmetric") Return the filter coefficients of a Flat Top window of length @var{m}. The Flat Top window is defined by the function f(w): @example @group f(w) = 1 - 1.93 cos(2 pi w) + 1.29 cos(4 pi w) - 0.388 cos(6 pi w) + 0.0322cos(8 pi w) @end group @end example where w = i/(m-1) for i=0:m-1 for a symmetric window, or w = i/m for i=0:m-1 for a periodic window. The default is symmetric. The returned window is normalized to a peak of 1 at w = 0.5. This window has low pass-band ripple, but high bandwidth. According to [1]: The main use for the Flat Top window is for calibration, due to its negligible amplitude errors. [1] Gade, S; Herlufsen, H; (1987) "Use of weighting functions in DFT/FFT analysis (Part I)", Bruel & Kjaer Technical Review No.3. @end deftypefn @c Window Functions gaussian @c ----------------------------------------- @subsection gaussian @cindex gaussian @deftypefn {Function File} {} gaussian (@var{m}) @deftypefnx {Function File} {} gaussian (@var{m}, @var{a}) Return a Gaussian convolution window of length @var{m}. The width of the window is inversely proportional to the parameter @var{a}. Use larger @var{a} for a narrower window. Use larger @var{m} for longer tails. w = exp ( -(a*x)^2/2 ) for x = linspace ( -(m-1)/2, (m-1)/2, m ). Width a is measured in frequency units (sample rate/num samples). It should be f when multiplying in the time domain, but 1/f when multiplying in the frequency domain (for use in convolutions). @end deftypefn @c Window Functions gausswin @c ----------------------------------------- @subsection gausswin @cindex gausswin @deftypefn {Function File} {} gausswin (@var{m}) @deftypefnx {Function File} {} gausswin (@var{m}, @var{a}) Return the filter coefficients of a Gaussian window of length @var{m}. The width of the window is inversely proportional to the parameter @var{a}. Use larger @var{a} for a narrow window. Use larger @var{m} for a smoother curve. w = exp ( -(a*x)^2/2 ) for x = linspace(-(m-1)/m, (m-1)/m, m) @end deftypefn @c Window Functions hann @c ----------------------------------------- @subsection hann @cindex hann @deftypefn {Function File} {} hann (@var{m}) @deftypefnx {Function File} {} hann (@var{m}, "periodic") @deftypefnx {Function File} {} hann (@var{m}, "symmetric") Return the filter coefficients of a Hanning window of length @var{m}. If the optional argument @code{"periodic"} is given, the periodic form of the window is returned. This is equivalent to the window of length @var{m}+1 with the last coefficient removed. The optional argument @code{"symmetric"} is equivalent to not specifying a second argument. This function exists for @sc{matlab} compatibility only, and is equivalent to @code{hanning (@var{m})}. @xseealso{hanning} @end deftypefn @c Window Functions kaiser @c ----------------------------------------- @subsection kaiser @cindex kaiser @deftypefn {Function File} {} kaiser (@var{m}) @deftypefnx {Function File} {} kaiser (@var{m}, @var{beta}) Return the filter coefficients of a Kaiser window of length @var{m}. The Fourier transform of the window has a stop-band attenuation that is derived from the parameter @var{beta}. For the definition of the Kaiser window, see A. V. Oppenheim & R. W. Schafer, "Discrete-Time Signal Processing". The continuous version of width m centered about x=0 is: @example @group besseli(0, beta * sqrt(1-(2*x/m).^2)) k(x) = -------------------------------------, m/2 <= x <= m/2 besseli(0, beta) @end group @end example @xseealso{kaiserord} @end deftypefn @c Window Functions nuttallwin @c ----------------------------------------- @subsection nuttallwin @cindex nuttallwin @deftypefn {Function File} {} nuttallwin (@var{m}) @deftypefnx {Function File} {} nuttallwin (@var{m}, "periodic") @deftypefnx {Function File} {} nuttallwin (@var{m}, "symmetric") Return the filter coefficients of a Blackman-Harris window defined by Nuttall of length @var{m}. If the optional argument @code{"periodic"} is given, the periodic form of the window is returned. This is equivalent to the window of length @var{m}+1 with the last coefficient removed. The optional argument @code{"symmetric"} is equivalent to not specifying a second argument. @xseealso{blackman, blackmanharris} @end deftypefn @c Window Functions parzenwin @c ----------------------------------------- @subsection parzenwin @cindex parzenwin @deftypefn {Function File} {} parzenwin (@var{m}) Return the filter coefficients of a Parzen window of length @var{m}. @xseealso{rectwin, bartlett} @end deftypefn @c Window Functions poisswin @c ----------------------------------------- @subsection poisswin @cindex poisswin @deftypefn {Function File} poisswin (@var{m}, @var{alpha}) Return the coefficients of a Poisson (a.k.a. exponential) window@footnote{S. Gade & H. Herlufsen, `Windows to FFT analysis (Part I)', Technical Review 3, Bruel & Kjaer, 1987} of length @var{m} and adjustable parameter @var{alpha}. @end deftypefn @c Window Functions rectwin @c ----------------------------------------- @subsection rectwin @cindex rectwin @deftypefn {Function File} {} rectwin (@var{m}) Return the filter coefficients of a rectangular window of length @var{m}. @xseealso{boxcar, hamming, hanning} @end deftypefn @c Window Functions taylorwin @c ----------------------------------------- @subsection taylorwin @cindex taylorwin @deftypefn {Function File} taylorwin (@var{m}) @deftypefnx {Function File} taylorwin (@var{m}, @var{nbar}) @deftypefnx {Function File} taylorwin (@var{m}, @var{nbar}, @var{sll}) @deftypefnx {Function File} taylorwin (@var{m}, @var{nbar}, @var{sll}, @var{plots}) Return the coefficients of a Taylor window of length @var{m}, whose Fourier transform has @var{nbar} (default 4) quasi-equiripple side-lobes adjacent to the main-lobe, at a nominal level of @var{sll} (default @minus{}30) dBc. If @var{plots} is non-zero then time and frequency domains plots of the resultant window are shown. Reference: Doerry, `Catalog of Window Taper Functions for Sidelobe Control', 2017. @xseealso{chebwin} @end deftypefn @c Window Functions triang @c ----------------------------------------- @subsection triang @cindex triang @deftypefn {Function File} {} triang (@var{m}) Return the filter coefficients of a triangular window of length @var{m}. Unlike the Bartlett window, @code{triang} does not go to zero at the edges of the window. For odd @var{m}, @code{triang (@var{m})} is equal to @code{bartlett (@var{m} + 2)} except for the zeros at the edges of the window. @xseealso{bartlett} @end deftypefn @c Window Functions tukeywin @c ----------------------------------------- @subsection tukeywin @cindex tukeywin @deftypefn {Function File} {} tukeywin (@var{m}) @deftypefnx {Function File} {} tukeywin (@var{m}, @var{r}) Return the filter coefficients of a Tukey window (also known as the cosine-tapered window) of length @var{m}. @var{r} defines the ratio between the constant section and and the cosine section. It has to be between 0 and 1. The function returns a Hanning window for @var{r} equal to 1 and a rectangular window for @var{r} equal to 0. The default value of @var{r} is 1/2. For a definition of the Tukey window, see e.g. Fredric J. Harris, "On the Use of Windows for Harmonic Analysis with the Discrete Fourier Transform, Proceedings of the IEEE", Vol. 66, No. 1, January 1978, Page 67, Equation 38. @xseealso{hanning} @end deftypefn @c Window Functions ultrwin @c ----------------------------------------- @subsection ultrwin @cindex ultrwin @deftypefn {Function File} {[@var{w}, @var{xmu}] =} ultrwin (@var{m}, @var{mu}, @var{beta}) @deftypefnx {Function File} {[@var{w}, @var{xmu}] =} ultrwin (@var{m}, @var{mu}, @var{att}, "att") @deftypefnx {Function File} {[@var{w}, @var{xmu}] =} ultrwin (@var{m}, @var{mu}, @var{latt}, "latt") @deftypefnx {Function File} {@var{w} =} ultrwin (@var{m}, @var{mu}, @var{xmu}, "xmu") Return the coefficients of an Ultraspherical window of length @var{m}. The parameter @var{mu} controls the window's Fourier transform's side-lobe to side-lobe ratio, and the third given parameter controls the transform's main-lobe width/side-lobe-ratio; normalize @var{w} such that the central coefficient(s) value is unitary. By default, the third parameter is @var{beta}, which sets the main lobe width to @var{beta} times that of a rectangular window. Alternatively, giving @var{att} or @var{latt} sets the ripple ratio at the first or last side-lobe respectively, or giving @var{xmu} sets the (un-normalized) window's Fourier transform according to its canonical definition: @verbatim (MU) W(k) = C [ XMU cos(pi k/M) ], k = 0, 1, ..., M-1, M-1 @end verbatim where C is the Ultraspherical (a.k.a. Gegenbauer) polynomial, which can be defined using the recurrence relationship: @verbatim (l) 1 (l) (l) C (x) = - [ 2x(m + l - 1) C (x) - (m + 2l - 2) C (x) ] m m m-1 m-2 (l) (l) for m an integer > 1, and C (x) = 1, C (x) = 2lx. 0 1 @end verbatim For given @var{beta}, @var{att}, or @var{latt}, the corresponding (determined) value of @var{xmu} is also returned. The Dolph-Chebyshev and Saramaki windows are special cases of the Ultraspherical window, with @var{mu} set to 0 and 1 respectively. Note that when not giving @var{xmu}, stability issues may occur with @var{mu} <= -1.5. For further information about the window, see @itemize @bullet @item Kabal, P., 2009: Time Windows for Linear Prediction of Speech. Technical Report, Dept. Elec. & Comp. Eng., McGill University. @item Bergen, S., Antoniou, A., 2004: Design of Ultraspherical Window Functions with Prescribed Spectral Characteristics. Proc. JASP, 13/13, pp. 2053-2065. @item Streit, R., 1984: A two-parameter family of weights for nonrecursive digital filters and antennas. Trans. ASSP, 32, pp. 108-118. @end itemize @xseealso{chebwin, kaiser} @end deftypefn @c Window Functions welchwin @c ----------------------------------------- @subsection welchwin @cindex welchwin @deftypefn {Function File} {} welchwin (@var{m}) @deftypefnx {Function File} {} welchwin (@var{m}, "periodic") @deftypefnx {Function File} {} welchwin (@var{m}, "symmetric") Return the filter coefficients of a Welch window of length @var{m}. The Welch window is given by @var{w}(n)=1-(n/N-1)^2, n=[0,1, ... @var{m}-1]. The optional argument specifies a "symmetric" window (the default) or a "periodic" window. A symmetric window has zero at each end and maximum in the middle, and the length must be an integer greater than 2. The variable @var{N} in the formula above is @code{(@var{m}-1)/2}. A periodic window wraps around the cyclic interval [0,1, ... @var{m}-1], and is intended for use with the DFT. The length must be an integer greater than 1. The variable @var{N} in the formula above is @code{@var{m}/2}. @xseealso{blackman, kaiser} @end deftypefn @c Window Functions window @c ----------------------------------------- @subsection window @cindex window @deftypefn {Function File} {@var{w} =} window (@var{f}, @var{m}) @deftypefnx {Function File} {@var{w} =} window (@var{f}, @var{m}, @var{opts}) Create an @var{m}-point window from the function @var{f}. The function @var{f} can be for example @code{@@blackman}. Any additional arguments @var{opt} are passed to the windowing function. @end deftypefn @c --------------------------------------------------- @node System Identification @section System Identification @cindex System Identification @c System Identification arburg @c ----------------------------------------- @subsection arburg @cindex arburg @deftypefn {Function File} {[@var{a}, @var{v}, @var{k}] =} arburg (@var{x}, @var{poles}) @deftypefnx {Function File} {[@var{a}, @var{v}, @var{k}] =} arburg (@var{x}, @var{poles}, @var{criterion}) Calculate coefficients of an autoregressive (AR) model of complex data @var{x} using the whitening lattice-filter method of Burg (1968). The inverse of the model is a moving-average filter which reduces @var{x} to white noise. The power spectrum of the AR model is an estimate of the maximum entropy power spectrum of the data. The function @code{ar_psd} calculates the power spectrum of the AR model. ARGUMENTS: @itemize @item @var{x} sampled data @item @var{poles} number of poles in the AR model or limit to the number of poles if a valid @var{criterion} is provided. @item @var{criterion} model-selection criterion. Limits the number of poles so that spurious poles are not added when the whitened data has no more information in it (see Kay & Marple, 1981). Recognized values are 'AKICc' -- approximate corrected Kullback information criterion (recommended), 'KIC' -- Kullback information criterion 'AICc' -- corrected Akaike information criterion 'AIC' -- Akaike information criterion 'FPE' -- final prediction error" criterion The default is to NOT use a model-selection criterion @end itemize RETURNED VALUES: @itemize @item @var{a} list of (P+1) autoregression coefficients; for data input @math{x(n)} and white noise @math{e(n)}, the model is @example @group P+1 x(n) = sqrt(v).e(n) + SUM a(k).x(n-k) k=1 @end group @end example @var{v} mean square of residual noise from the whitening operation of the Burg lattice filter. @item @var{k} reflection coefficients defining the lattice-filter embodiment of the model @end itemize HINTS: (1) arburg does not remove the mean from the data. You should remove the mean from the data if you want a power spectrum. A non-zero mean can produce large errors in a power-spectrum estimate. See "help detrend". (2) If you don't know what the value of "poles" should be, choose the largest (reasonable) value you could want and use the recommended value, criterion='AKICc', so that arburg can find it. E.g. arburg(x,64,'AKICc') The AKICc has the least bias and best resolution of the available model-selection criteria. (3) Autoregressive and moving-average filters are stored as polynomials which, in matlab, are row vectors. NOTE ON SELECTION CRITERION: AIC, AICc, KIC and AKICc are based on information theory. They attempt to balance the complexity (or length) of the model against how well the model fits the data. AIC and KIC are biased estimates of the asymmetric and the symmetric Kullback-Leibler divergence respectively. AICc and AKICc attempt to correct the bias. See reference [4]. REFERENCES: [1] John Parker Burg (1968) "A new analysis technique for time series data", NATO advanced study Institute on Signal Processing with Emphasis on Underwater Acoustics, Enschede, Netherlands, Aug. 12-23, 1968. [2] Steven M. Kay and Stanley Lawrence Marple Jr.: "Spectrum analysis -- a modern perspective", Proceedings of the IEEE, Vol 69, pp 1380-1419, Nov., 1981 [3] William H. Press and Saul A. Teukolsky and William T. Vetterling and Brian P. Flannery "Numerical recipes in C, The art of scientific computing", 2nd edition, Cambridge University Press, 2002 --- Section 13.7. [4] Abd-Krim Seghouane and Maiza Bekara "A small sample model selection criterion based on Kullback's symmetric divergence", IEEE Transactions on Signal Processing, Vol. 52(12), pp 3314-3323, Dec. 2004 @xseealso{ar_psd} @end deftypefn @c System Identification aryule @c ----------------------------------------- @subsection aryule @cindex aryule @deftypefn {Function File} {@var{a} =} aryule (@var{x}, @var{p}) @deftypefnx {Function File} {[@var{a}, @var{v}, @var{k}] =} aryule (@var{x}, @var{p}) Fit an AR (@var{p})-model with Yule-Walker estimates. @table @var @item x data vector to estimate @item a AR coefficients @item v variance of white noise @item k reflection coefficients for use in lattice filter @end table The power spectrum of the resulting filter can be plotted with pyulear(x, p), or you can plot it directly with ar_psd(a,v,...). See also: pyulear, power, freqz, impz -- for observing characteristics of the model arburg -- for alternative spectral estimators Example: Use example from arburg, but substitute aryule for arburg. Note: Orphanidis '85 claims lattice filters are more tolerant of truncation errors, which is why you might want to use them. However, lacking a lattice filter processor, I haven't tested that the lattice filter coefficients are reasonable. @end deftypefn @c System Identification invfreq @c ----------------------------------------- @subsection invfreq @cindex invfreq @deftypefn {Function File} {[B,A] =} invfreq(H,F,nB,nA) @deftypefnx {} {[B,A] =} invfreq(H,F,nB,nA,W) @deftypefnx {} {[B,A] =} invfreq(H,F,nB,nA,W,[],[],plane) @deftypefnx {} {[B,A] =} invfreq(H,F,nB,nA,W,iter,tol,plane) Fit filter B(z)/A(z) or B(s)/A(s) to complex frequency response at frequency points F. A and B are real polynomial coefficients of order nA and nB respectively. Optionally, the fit-errors can be weighted vs frequency according to the weights W. Also, the transform plane can be specified as either 's' for continuous time or 'z' for discrete time. 'z' is chosen by default. Eventually, Steiglitz-McBride iterations will be specified by iter and tol. H: desired complex frequency response It is assumed that A and B are real polynomials, hence H is one-sided. F: vector of frequency samples in radians nA: order of denominator polynomial A nB: order of numerator polynomial B plane='z': F on unit circle (discrete-time spectra, z-plane design) plane='s': F on jw axis (continuous-time spectra, s-plane design) H(k) = spectral samples of filter frequency response at points zk, where zk=exp(sqrt(-1)*F(k)) when plane='z' (F(k) in [0,.5]) and zk=(sqrt(-1)*F(k)) when plane='s' (F(k) nonnegative) Example: @example [B,A] = butter(12,1/4); [H,w] = freqz(B,A,128); [Bh,Ah] = invfreq(H,F,4,4); Hh = freqz(Bh,Ah); disp(sprintf('||frequency response error|| = %f',norm(H-Hh))); @end example References: J. O. Smith, "Techniques for Digital Filter Design and System Identification with Application to the Violin, Ph.D. Dissertation, Elec. Eng. Dept., Stanford University, June 1983, page 50; or, http://ccrma.stanford.edu/~jos/filters/FFT_Based_Equation_Error_Method.html @end deftypefn @c System Identification invfreqs @c ----------------------------------------- @subsection invfreqs @cindex invfreqs @deftypefn {Function File} {[B,A] =} invfreqs(H,F,nB,nA) @deftypefnx {} {[B,A] =} invfreqs(H,F,nB,nA,W) @deftypefnx {} {[B,A] =} invfreqs(H,F,nB,nA,W,iter,tol,'trace') Fit filter B(s)/A(s)to the complex frequency response H at frequency points F. A and B are real polynomial coefficients of order nA and nB. Optionally, the fit-errors can be weighted vs frequency according to the weights W. Note: all the guts are in invfreq.m H: desired complex frequency response F: frequency (must be same length as H) nA: order of the denominator polynomial A nB: order of the numerator polynomial B W: vector of weights (must be same length as F) Example: @example B = [1/2 1]; A = [1 1]; w = linspace(0,4,128); H = freqs(B,A,w); [Bh,Ah] = invfreqs(H,w,1,1); Hh = freqs(Bh,Ah,w); plot(w,[abs(H);abs(Hh)]) legend('Original','Measured'); err = norm(H-Hh); disp(sprintf('L2 norm of frequency response error = %f',err)); @end example @end deftypefn @c System Identification invfreqz @c ----------------------------------------- @subsection invfreqz @cindex invfreqz @deftypefn {Function File} {[B,A] =} invfreqz(H,F,nB,nA) @deftypefnx {} {[B,A] =} invfreqz(H,F,nB,nA,W) @deftypefnx {} {[B,A] =} invfreqz(H,F,nB,nA,W,iter,tol,'trace') Fit filter B(z)/A(z)to the complex frequency response H at frequency points F. A and B are real polynomial coefficients of order nA and nB. Optionally, the fit-errors can be weighted vs frequency according to the weights W. Note: all the guts are in invfreq.m H: desired complex frequency response F: normalized frequency (0 to pi) (must be same length as H) nA: order of the denominator polynomial A nB: order of the numerator polynomial B W: vector of weights (must be same length as F) Example: @example [B,A] = butter(4,1/4); [H,F] = freqz(B,A); [Bh,Ah] = invfreq(H,F,4,4); Hh = freqz(Bh,Ah); disp(sprintf('||frequency response error|| = %f',norm(H-Hh))); @end example @end deftypefn @c System Identification levinson @c ----------------------------------------- @subsection levinson @cindex levinson @deftypefn {Function File} {[@var{a}, @var{v}, @var{ref}] =} levinson (@var{acf}) @deftypefnx {Function File} {[@dots{}] =} levinson (@var{acf}, @var{p}) Use the Durbin-Levinson algorithm to solve: toeplitz(acf(1:p)) * x = -acf(2:p+1). The solution [1, x'] is the denominator of an all pole filter approximation to the signal x which generated the autocorrelation function acf. acf is the autocorrelation function for lags 0 to p. p defaults to length(acf)-1. Returns a=[1, x'] the denominator filter coefficients. v= variance of the white noise = square of the numerator constant ref = reflection coefficients = coefficients of the lattice implementation of the filter Use freqz(sqrt(v),a) to plot the power spectrum. REFERENCE [1] Steven M. Kay and Stanley Lawrence Marple Jr.: "Spectrum analysis -- a modern perspective", Proceedings of the IEEE, Vol 69, pp 1380-1419, Nov., 1981 @end deftypefn @c System Identification lpc @c ----------------------------------------- @subsection lpc @cindex lpc @deftypefn {Function File} {@var{a} = } lpc (@var{x}) @deftypefnx {Function File} {@var{a} = } lpc (@var{x}, @var{p}) @deftypefnx {Function File} {[@var{a}, @var{g}] = } lpc (@dots{}) @deftypefnx {Function File} {[@var{a}, @var{g}] = } lpc (@var{x}, @var{p}) Determines the forward linear predictor by minimizing the prediction error in the least squares sense. Use the Durbin-Levinson algorithm to solve the Yule-Walker equations obtained by the autocorrelation of the input signal. @var{x} is a data vector used to estimate the lpc model of @var{p}-th order, given by the prediction polynomial @code{@var{a} = [1 @var{a}(2) @dots{} @var{a}(@var{p}+1)]}. If @var{p} is not provided, @code{length(@var{p}) - 1} is used as default. @var{x} might also be a matrix, in which case each column is regarded as a separate signal. @code{lpc} will return a model estimate for each column of @var{x}. @var{g} is the variance (power) of the prediction error for each signal in @var{x}. @xseealso{aryule,levinson} @end deftypefn @c --------------------------------------------------- @node Sample Rate Change @section Sample Rate Change @cindex Sample Rate Change @c Sample Rate Change data2fun @c ----------------------------------------- @subsection data2fun @cindex data2fun @deftypefn {Function File} {[@var{fhandle}, @var{fullname}] =} data2fun (@var{ti}, @var{yi}) @deftypefnx {Function File} {[@dots{}] =} data2fun (@dots{}, @var{property}, @var{value}) Create a vectorized function based on data samples using interpolation. The values given in @var{yi} (N-by-k matrix) correspond to evaluations of the function y(t) at the points @var{ti} (N-by-1 matrix). The data is interpolated and the function handle to the generated interpolant is returned. The function accepts @var{property}-@var{value} pairs described below. @table @samp @item file Code is generated and .m file is created. The @var{value} contains the name of the function. The returned function handle is a handle to that file. If @var{value} is empty, then a name is automatically generated using @code{tempname} and the file is created in the current directory. @var{value} must not have an extension, since .m will be appended. Numerical values used in the function are stored in a .mat file with the same name as the function. @item interp Type of interpolation. See @code{interp1}. @end table @xseealso{interp1} @end deftypefn @c Sample Rate Change decimate @c ----------------------------------------- @subsection decimate @cindex decimate @deftypefn {Function File} {@var{y} =} decimate (@var{x}, @var{q}) @deftypefnx {Function File} {@var{y} =} decimate (@var{x}, @var{q}, @var{n}) @deftypefnx {Function File} {@var{y} =} decimate (@dots{}, "fir") Downsample the signal @var{x} by a reduction factor of @var{q}. A lowpass antialiasing filter is applied to the signal prior to reducing the input sequence. By default, an order @var{n} Chebyshev type I filter is used. If @var{n} is not specified, the default is 8. If the optional argument @code{"fir"} is given, an order @var{n} FIR filter is used, with a default order of 30 if @var{n} is not given. Note that @var{q} must be an integer for this rate change method. Example: @example ## Generate a signal that starts away from zero, is slowly varying ## at the start and quickly varying at the end, decimate and plot. ## Since it starts away from zero, you will see the boundary ## effects of the antialiasing filter clearly. Next you will see ## how it follows the curve nicely in the slowly varying early ## part of the signal, but averages the curve in the quickly ## varying late part of the signal. t = 0:0.01:2; x = chirp (t, 2, .5, 10, "quadratic") + sin (2*pi*t*0.4); y = decimate (x, 4); stem (t(1:121) * 1000, x(1:121), "-g;Original;"); hold on; # original stem (t(1:4:121) * 1000, y(1:31), "-r;Decimated;"); hold off; # decimated @end example @end deftypefn @c Sample Rate Change downsample @c ----------------------------------------- @subsection downsample @cindex downsample @deftypefn {Function File} {@var{y} =} downsample (@var{x}, @var{n}) @deftypefnx {Function File} {@var{y} =} downsample (@var{x}, @var{n}, @var{offset}) Downsample the signal, selecting every @var{n}th element. If @var{x} is a matrix, downsample every column. For most signals you will want to use @code{decimate} instead since it prefilters the high frequency components of the signal and avoids aliasing effects. If @var{offset} is defined, select every @var{n}th element starting at sample @var{offset}. @xseealso{decimate, interp, resample, upfirdn, upsample} @end deftypefn @c Sample Rate Change interp @c ----------------------------------------- @subsection interp @cindex interp @deftypefn {Function File} {@var{y} =} interp (@var{x}, @var{q}) @deftypefnx {Function File} {@var{y} =} interp (@var{x}, @var{q}, @var{n}) @deftypefnx {Function File} {@var{y} =} interp (@var{x}, @var{q}, @var{n}, @var{Wc}) Upsample the signal x by a factor of q, using an order 2*q*n+1 FIR filter. Note that q must be an integer for this rate change method. n defaults to 4 and Wc defaults to 0.5. Example @example @group # Generate a signal. t=0:0.01:2; x=chirp(t,2,.5,10,'quadratic')+sin(2*pi*t*0.4); y = interp(x(1:4:length(x)),4,4,1); # interpolate a sub-sample stem(t(1:121)*1000,x(1:121),"-g;Original;"); hold on; stem(t(1:121)*1000,y(1:121),"-r;Interpolated;"); stem(t(1:4:121)*1000,x(1:4:121),"-b;Subsampled;"); hold off; @end group @end example @xseealso{decimate, resample} @end deftypefn @c Sample Rate Change resample @c ----------------------------------------- @subsection resample @cindex resample @deftypefn {Function File} {[@var{y}, @var{h}] =} resample (@var{x}, @var{p}, @var{q}) @deftypefnx {Function File} {@var{y} =} resample (@var{x}, @var{p}, @var{q}, @var{h}) Change the sample rate of @var{x} by a factor of @var{p}/@var{q}. This is performed using a polyphase algorithm. The impulse response @var{h} of the antialiasing filter is either specified or either designed with a Kaiser-windowed sinecard. Ref [1] J. G. Proakis and D. G. Manolakis, Digital Signal Processing: Principles, Algorithms, and Applications, 4th ed., Prentice Hall, 2007. Chap. 6 Ref [2] A. V. Oppenheim, R. W. Schafer and J. R. Buck, Discrete-time signal processing, Signal processing series, Prentice-Hall, 1999 @end deftypefn @c Sample Rate Change upfirdn @c ----------------------------------------- @subsection upfirdn @cindex upfirdn @deftypefn {Loadable Function} {@var{y} =} upfirdn (@var{x}, @var{h}, @var{p}, @var{q}) Upsample, FIR filtering, and downsample. @end deftypefn @c Sample Rate Change upsample @c ----------------------------------------- @subsection upsample @cindex upsample @deftypefn {Function File} {@var{y} =} upsample (@var{x}, @var{n}) @deftypefnx {Function File} {@var{y} =} upsample (@var{x}, @var{n}, @var{offset}) Upsample the signal, inserting @var{n}-1 zeros between every element. If @var{x} is a matrix, upsample every column. If @var{offset} is specified, control the position of the inserted sample in the block of @var{n} zeros. @xseealso{decimate, downsample, interp, resample, upfirdn} @end deftypefn @c --------------------------------------------------- @node Pulse Metrics @section Pulse Metrics @cindex Pulse Metrics @c Pulse Metrics statelevels @c ----------------------------------------- @subsection statelevels @cindex statelevels @deftypefn {Function File} {@var{levels} =} statelevels (@var{A}) @deftypefnx {Function File} {@var{levels} =} statelevels (@var{A}, @var{nbins}) @deftypefnx {Function File} {@var{levels} =} statelevels (@var{A}, @var{nbins}, @var{method}) @deftypefnx {Function File} {@var{levels} =} statelevels (@var{A}, @var{nbins}, @var{method}, @var{bounds}) @deftypefnx {Function File} {[@var{levels}, @var{histograms}] =} statelevels (@dots{}) @deftypefnx {Function File} {[@var{levels}, @var{histograms}, @var{binlevels}] =} statelevels (@dots{}) @deftypefnx {Function File} {} statelevels (@dots{}) Estimate state-level for bilevel waveform @var{A} using histogram method INPUTS: @table @var @item A Bylevel waveform @item nbins Number of histogram bins (100 default) @item method State-level estimation method 'mode' (default) or 'mean'. @item bounds 2 element vector for histogram lower and upper bounds. Values outside of this will be ignored. @end table OUTPUTS: @table @var @item levels Levels of high and low states @item histograms Histogram counts @item binlevels Histogram bincenters @end table If no outputs are provided, the signal and histogram will be plotted, and display the levels. @end deftypefn @c --------------------------------------------------- @node Utility @section Utility @cindex Utility @c Utility buffer @c ----------------------------------------- @subsection buffer @cindex buffer @deftypefn {Function File} {@var{y} =} buffer (@var{x}, @var{n}, @var{p}, @var{opt}) @deftypefnx {Function File} {[@var{y}, @var{z}, @var{opt}] =} buffer (@dots{}) Buffer a signal into a data frame. The arguments to @code{buffer} are @table @asis @item @var{x} The data to be buffered. @item @var{n} The number of rows in the produced data buffer. This is an positive integer value and must be supplied. @item @var{p} An integer less than @var{n} that specifies the under- or overlap between column in the data frame. The default value of @var{p} is 0. @item @var{opt} In the case of an overlap, @var{opt} can be either a vector of length @var{p} or the string 'nodelay'. If @var{opt} is a vector, then the first @var{p} entries in @var{y} will be filled with these values. If @var{opt} is the string 'nodelay', then the first value of @var{y} corresponds to the first value of @var{x}. In the can of an underlap, @var{opt} must be an integer between 0 and @code{-@var{p}}. The represents the initial underlap of the first column of @var{y}. The default value for @var{opt} the vector @code{zeros (1, @var{p})} in the case of an overlap, or 0 otherwise. @end table In the case of a single output argument, @var{y} will be padded with zeros to fill the missing values in the data frame. With two output arguments @var{z} is the remaining data that has not been used in the current data frame. Likewise, the output @var{opt} is the overlap, or underlap that might be used for a future call to @code{code} to allow continuous buffering. @end deftypefn @c Utility clustersegment @c ----------------------------------------- @subsection clustersegment @cindex clustersegment @deftypefn {Function File} {@var{clusteridx} =} clustersegment (@var{unos}) Calculate boundary indexes of clusters of 1's. The function calculates the initial index and end index of the sequences of 1's in the rows of @var{unos}. The clusters are sought in the rows of the array @var{unos}. The result is returned in a cell array of size 1-by-@var{Np}, where @var{Np} is the number of rows in @var{unos}. Each element of the cell has two rows. The first row is the initial index of a sequence of 1's and the second row is the end index of that sequence. If @var{Np} == 1 the output is a matrix with two rows. The function works by finding the indexes of jumps between consecutive values in the rows of @var{unos}. @end deftypefn @c Utility fracshift @c ----------------------------------------- @subsection fracshift @cindex fracshift @deftypefn {Function File} {[@var{y}, @var{h}] =} fracshift (@var{x}, @var{d}) @deftypefnx {Function File} {@var{y} =} fracshift (@var{x}, @var{d}, @var{h}) Shift the series @var{x} by a (possibly fractional) number of samples @var{d}. The interpolator @var{h} is either specified or either designed with a Kaiser-windowed sinecard. @xseealso{circshift} @end deftypefn @c Utility marcumq @c ----------------------------------------- @subsection marcumq @cindex marcumq @deftypefn {Function File} {@var{q} =} marcumq (@var{a}, @var{b}) @deftypefnx {Function File} {@var{q} =} marcumq (@var{a}, @var{b}, @var{m}) @deftypefnx {Function File} {@var{q} =} marcumq (@var{a}, @var{b}, @var{m}, @var{tol}) Compute the generalized Marcum Q function of order @var{m} with noncentrality parameter @var{a} and argument @var{b}. If the order @var{m} is omitted it defaults to 1. An optional relative tolerance @var{tol} may be included, the default is @code{eps}. If the input arguments are commensurate vectors, this function will produce a table of values. This function computes Marcum's Q function using the infinite Bessel series, truncated when the relative error is less than the specified tolerance. The accuracy is limited by that of the Bessel functions, so reducing the tolerance is probably not useful. Reference: Marcum, "Tables of Q Functions", Rand Corporation. Reference: R.T. Short, "Computation of Noncentral Chi-squared and Rice Random Variables", www.phaselockedsystems.com/publications @end deftypefn @c Utility primitive @c ----------------------------------------- @subsection primitive @cindex primitive @deftypefn {Function File} {@var{F} =} primitive (@var{f}, @var{t}, @var{F0}) Calculate the primitive of a function. The function approximates the primitive (indefinite integral) of the univariate function handle @var{f} with constant of integration @var{F0}. The output is the primitive evaluated at the points @var{t}. The vector @var{t} must be ordered and ascending. This function is a fancy way of calculating the cumulative sum, @command{F = cumsum (f(t).*diff (t)([1 1:end]))}. Example: @example @group f = @@(t) sin (2 * pi * 3 * t); t = [0; sort(rand (100, 1))]; F = primitive (f, t, 0); t_true = linspace (0, 1, 1e3).'; F_true = (1 - cos (2 * pi * 3 * t_true)) / (2 * pi * 3); plot (t, F, 'o', t_true, F_true); @end group @end example @xseealso{quadgk, cumsum} @end deftypefn @c Utility sampled2continuous @c ----------------------------------------- @subsection sampled2continuous @cindex sampled2continuous @deftypefn {Function File} {@var{xt} =} sampled2continuous (@var{xn}, @var{T}, @var{t}) Calculate the x(t) reconstructed from samples x[n] sampled at a rate 1/T samples per unit time. t is all the instants of time when you need x(t) from x[n]; this time is relative to x[0] and not an absolute time. This function can be used to calculate sampling rate effects on aliasing, actual signal reconstruction from discrete samples. @end deftypefn @c Utility schtrig @c ----------------------------------------- @subsection schtrig @cindex schtrig @deftypefn {@var{v} =} schtrig (@var{x},@var{lvl},@var{rst}=1) @deftypefnx {[@var{v},@var{rng}] =} schtrig (@dots{}) Implements a multisignal Schmitt trigger with levels @var{lvl}. The triger works along the first dimension of the 2-dimensional array @var{x}. It compares each column in @var{x} to the levels in @var{lvl}, when the value is higher @code{max (@var{lvl})} the output @var{v} is high (i.e. 1); when the value is below @code{min (@var{lvl})} the output is low (i.e. 0); and when the value is between the two levels the output retains its value. The threshold levels are passed in the array @var{lvl}. If this is a scalar, the thresholds are symmetric around 0, i.e. @code{[-lvl lvl]}. The second output argument stores the ranges in which the output is high, so the indexes @var{rng(1,i):rng(2,i)} point to the i-th segment of 1s in @var{v}. See @code{clustersegment} for a detailed explanation. The function conserves the state of the trigger across calls (persistent variable). If the reset flag is active, i.e. @code{@var{rst}== true}, then the state of the trigger for all signals is set to the low state (i.e. 0). Example: @example x = [0 0.5 1 1.5 2 1.5 1.5 1.2 1 0 0].'; y = schtrig (x, [1.3 1.6]); disp ([x y]); 0.0 0 0.5 0 1.0 0 1.5 0 2.0 1 1.5 1 1.5 1 1.2 0 1.0 0 0.0 0 0.0 0 @end example Run @code{demo schtrig} to see further examples. @xseealso{clustersegment} @end deftypefn @c Utility upsamplefill @c ----------------------------------------- @subsection upsamplefill @cindex upsamplefill @deftypefn {Function File} {@var{y} =} upsamplefill (@var{x}, @var{v}) @deftypefnx {Function File} {@var{y} =} upsamplefill (@dots{}, @var{copy}) Upsamples a vector interleaving given values or copies of the vector elements. The values in the vector @var{v} are placed between the elements of @var{x}. If the optional argument @var{copy} is @var{true} then @var{v} should be a scalar and each value in @var{x} are repeat @var{v} times. Example: @example @group upsamplefill (eye (2), 2, true) @result{} 1 0 1 0 1 0 0 1 0 1 0 1 upsamplefill (eye (2), [-1 -1 -1]) @result{} 1 0 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 @end group @end example @xseealso{upsample} @end deftypefn @c Utility wkeep @c ----------------------------------------- @subsection wkeep @cindex wkeep @deftypefn {Function File} {@var{y} =} wkeep (@var{x}, @var{l}) @deftypefnx {Function File} {@var{y} =} wkeep (@var{x}, @var{l}, @var{opt}) Extract the elements of @var{x} of size @var{l} from the center, the right or the left. @end deftypefn @c Utility wrev @c ----------------------------------------- @subsection wrev @cindex wrev @deftypefn {Function File} {@var{y} =} wrev (@var{x}) Reverse the order of the element of the vector @var{x}. @xseealso{flipud, fliplr} @end deftypefn @c Utility zerocrossing @c ----------------------------------------- @subsection zerocrossing @cindex zerocrossing @deftypefn {Function File} {@var{x0} =} zerocrossing (@var{x}, @var{y}) Estimates the points at which a given waveform y=y(x) crosses the x-axis using linear interpolation. @xseealso{fzero, roots} @end deftypefn signal-1.4.6/doc/gpl.texi0000644000000000000000000010433014673270174012163 0ustar00@node Copying @appendix GNU General Public License @cindex warranty @cindex copyright @center Version 3, 29 June 2007 @display Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/} Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end display @heading 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. @heading TERMS AND CONDITIONS @enumerate 0 @item 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. @item 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. @item 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. @item 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. @item 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. @item 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: @enumerate a @item The work must carry prominent notices stating that you modified it, and giving a relevant date. @item 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''. @item 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. @item 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. @end enumerate 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. @item 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: @enumerate a @item 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. @item 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. @item 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. @item 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. @item 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. @end enumerate 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. @item 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: @enumerate a @item Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or @item 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 @item 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 @item Limiting the use for publicity purposes of names of licensors or authors of the material; or @item Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or @item 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. @end enumerate 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. @item 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. @item 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. @item 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. @item 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. @item 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. @item 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. @item 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. @item 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. @item 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. @item 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 enumerate @heading END OF TERMS AND CONDITIONS @heading 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. @smallexample @var{one line to give the program's name and a brief idea of what it does.} Copyright (C) @var{year} @var{name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 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 @url{http://www.gnu.org/licenses/}. @end smallexample 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: @smallexample @var{program} Copyright (C) @var{year} @var{name of author} This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}. This is free software, and you are welcome to redistribute it under certain conditions; type @samp{show c} for details. @end smallexample The hypothetical commands @samp{show w} and @samp{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 @url{http://www.gnu.org/licenses/}. 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 @url{http://www.gnu.org/philosophy/why-not-lgpl.html}. signal-1.4.6/doc/macros.texi0000644000000000000000000000624114673270174012667 0ustar00@c Copyright (C) 2012-2019 John W. Eaton @c @c This file is part of Octave. @c @c Octave is free software: you can redistribute it and/or modify it @c under the terms of the GNU General Public License as published by @c the Free Software Foundation, either version 3 of the License, or @c (at your option) any later version. @c @c Octave is distributed in the hope that it will be useful, but @c WITHOUT ANY WARRANTY; without even the implied warranty of @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @c GNU General Public License for more details. @c @c You should have received a copy of the GNU General Public License @c along with Octave; see the file COPYING. If not, see @c . @c The following macro marks words that aspell should ignore during @c spellchecking. Within Texinfo it has no effect as it merely replaces @c the macro call with the argument itself. @macro nospell {arg} \arg\ @end macro @c The following macro works around the Info/plain text expansion of @code{XXX} @c which is `XXX'. This looks particularly bad when the macro body is @c single or double-quoted text, such as a property value `"position"' @ifinfo @macro qcode{arg} \arg\ @end macro @end ifinfo @ifnotinfo @macro qcode{arg} @code{\arg\} @end macro @end ifnotinfo @c The following macro is used for the on-line help system, but we don't @c want lots of `See also: foo, bar, and baz' strings cluttering the @c printed manual (that information should be in the supporting text for @c each group of functions and variables). @c @c Implementation Note: @c For TeX, @vskip produces a nice separation. @c For Texinfo, '@sp 1' should work, but in practice produces ugly results @c for HTML. We use a simple blank line to produce the correct @c behavior. @c @c We use @xseealso now because Texinfo introduced its own @seealso @c command. But instead of modifying all source files, we'll have the @c munge-texi script convert @seealso to @xseealso. @macro xseealso {args} @iftex @vskip 2pt @end iftex @ifnottex @end ifnottex @ifnotinfo @noindent @strong{See also:} \args\. @end ifnotinfo @ifinfo @noindent See also: \args\. @end ifinfo @end macro @c The following macro works around a situation where the Info/plain text @c expansion of the @code{XXX} macro is `XXX'. The use of the apostrophe @c can be confusing if the code segment itself ends with a transpose operator. @ifinfo @macro tcode{arg} \arg\ @end macro @end ifinfo @ifnotinfo @macro tcode{arg} @code{\arg\} @end macro @end ifnotinfo @c FIXME: someday, when Texinfo 5.X is standard, we might replace this with @c @backslashchar, which is a new addition to Texinfo. @macro xbackslashchar \\ @end macro @c These may be useful for all, not just for octave.texi. @tex \ifx\rgbDarkRed\thisisundefined \def\rgbDarkRed{0.50 0.09 0.12} \fi \ifx\linkcolor\thisisundefined \relax \else \global\def\linkcolor{\rgbDarkRed} \fi \ifx\urlcolor\thisisundefined \relax \else \global\def\urlcolor{\rgbDarkRed} \fi \ifx\urefurlonlylinktrue\thisisundefined \relax \else \global\urefurlonlylinktrue \fi @end tex @c Make the apostrophe in code examples cut-and-paste friendly. @codequoteundirected on signal-1.4.6/doc/mkfuncdocs.py0000755000000000000000000002766114673270174013232 0ustar00#!/usr/bin/python3 ## Copyright 2018-2024 John Donoghue ## ## 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 ## . ## mkfuncdocs v1.0.8 ## mkfuncdocs.py will attempt to extract the help texts from functions in src ## dirs, extracting only those that are in the specifed INDEX file and output them ## to stdout in texi format ## ## It will extract from both .m and the help text for DEFUN_DLD help in .cc/.cpp ## files. ## ## It attempts to find the help text for each function in a file within the src search ## folders that match in order: [ functionname.m functionname.cc functionname.cpp ## functionname_withoutprefix.cc functionname_withoutprefix.cpp ] ## ## Usage: ## mkfundocs.py options INDEXfile ## Options can be 0 or more of: ## --verbose : Turn on verbose mode ## --src-dir=xxxxx : Add dir xxxxx to the dirs searched for the function file. ## If no directories are provided, it will default to looking in the ## 'inst' directory. ## --ignore=xxxxx : dont attempt to generate help for function xxxxx. ## --funcprefix=xxxxx : remove xxxxx from the function name when searching for matching ## source file. ## --allowscan : if can not find function, attemp to scan .cc,cpp,cxx files for match ## ## --standalone : generate a texinfo file expected to be used with being included in ## another document file. import sys import os import re import tempfile import shutil import fnmatch import subprocess import glob import calendar; import time; class Group: name = "Functions" functions = [] def __init__ (self, name=""): if name: self.name = name self.functions = [] class Index: name = "" groups = [] def texify_line(line): # convert any special chars in a line to texinfo format # currently just used for group formatting ? line = line.replace("@", "@@") line = line.replace("{", "@{") line = line.replace("}", "@}") line = line.replace(",", "@comma{}") return line def find_defun_line_in_file(filename, fnname): linecnt = 0 defun_line=re.compile(r"^DEFUN_DLD\s*\(\s*{}".format(fnname)) with open(filename, 'rt') as f: for line in f: if re.match(defun_line, line): return linecnt linecnt = linecnt + 1 return -1 def find_function_line_in_file(filename, fnname): linecnt = 0 func = False defun_line=re.compile(r"^\s*function \s*") with open(filename, 'rt') as f: for line in f: if func == True: x = line.strip() if x.startswith("## -*- texinfo -*-"): return linecnt else: func = False if re.match(defun_line, line): if line.find("=") != -1: x = line.split("=") x = x[-1] else: x = line.replace("function ", "") x = x.split("(") x = x[0].strip() if x == fnname: func = True linecnt = linecnt + 1 return -1 def read_m_file(filename, skip=0): help = [] inhelp = False havehelp = False; with open(filename, 'rt') as f: for line in f: line = line.lstrip() if skip > 0: skip = skip - 1 elif not havehelp: if havehelp == False and inhelp == False and line.startswith('##'): if "texinfo" in line: inhelp = True elif inhelp == True: if not line.startswith('##'): inhelp = False havehelp = True else: if line.startswith("## @"): line = line[3:] else: line = line[2:] help.append (line.rstrip()); return help def read_cc_file(filename, skip=0): help = [] inhelp = False havehelp = False; with open(filename, 'rt') as f: for line in f: line = line.lstrip() if skip > 0: skip = skip - 1 elif not havehelp: if havehelp == False and inhelp == False: if "texinfo" in line: inhelp = True elif inhelp == True: line = line.rstrip() if len(line) > 0 and line[-1] == '\\': line = line[:-1] line = line.rstrip() line = line.replace("\\n", "\n") line = line.replace("\\\"", "\"") if len(line) > 0 and line[-1] == '\n': line = line[:-1] # endif a texinfo line elif line.endswith('")'): line = line[:-2] if line.startswith('{'): inhelp = False havehelp = True else: help.append (line); return help def read_help (filename, skip=0): help = [] if filename[-2:] == ".m": help = read_m_file(filename, skip) else: help = read_cc_file(filename, skip) return help def read_index (filename, ignore): index = Index () with open(filename, 'rt') as f: lines = f.read().splitlines() #print ("read", lines) first = True category = Group() for l in lines: if l.startswith("#"): pass elif first: index.name = l; first = False elif l.startswith(" "): l = l.strip() # may be multiple functions here funcs = l.split() for f in funcs: if f not in ignore: category.functions.append(f); else: # new category name if len(category.functions) > 0: index.groups.append(category) category = Group(l.strip()) # left over category ? if len(category.functions) > 0: index.groups.append(category) return index; def find_class_file(fname, paths): for f in paths: # class constructor ? name = f + "/@" + fname + "/" + fname + ".m" if os.path.isfile(name): return name, 0 # perhaps classname.func format ? x = fname.split(".") if len(x) > 0: zname = x.pop() cname = ".".join(x) name = f + "/" + cname + ".m" if os.path.isfile(name): idx = find_function_line_in_file(name, zname) if idx >= 0: return name, idx name = f + "/@" + cname + "/" + zname + ".m" if os.path.isfile(name): return name, 0 return None, -1 def find_func_file(fname, paths, prefix, scanfiles=False): for f in paths: name = f + "/" + fname + ".m" if os.path.isfile(name): return name, 0 # class constructor ? name = f + "/@" + fname + "/" + fname + ".m" if os.path.isfile(name): return name, 0 name = f + "/" + fname + ".cc" if os.path.isfile(name): return name, 0 name = f + "/" + fname + ".cpp" if os.path.isfile(name): return name, 0 # if have a prefix, remove and try if prefix and fname.startswith(prefix): fname = fname[len(prefix):] name = f + "/" + fname + ".cc" if os.path.isfile(name): return name, 0 name = f + "/" + fname + ".cpp" if os.path.isfile(name): return name, 0 # if here, we still dont have a file match # if allowed to scan files, do that if scanfiles: #sys.stderr.write("Warning: Scaning for {}\n".format(fname)) for f in paths: files = list(f + "/" + a for a in os.listdir(f)) cc_files = fnmatch.filter(files, "*.cc") cpp_files = fnmatch.filter(files, "*.cpp") cxx_files = fnmatch.filter(files, "*.cxx") for fn in cc_files + cpp_files + cxx_files: line = find_defun_line_in_file(fn, fname) if line >= 0: #sys.stderr.write("Warning: Found function for {} in {} at {}\n".format(fname, fn, line)) return fn, line return None, -1 def display_standalone_header(): # make a file that doesnt need to be included in a texinfo file to # be valid print("@c mkfuncdocs output for a standalone function list") print("@include macros.texi") print("@ifnottex") print("@node Top") print("@top Function Documentation") print("Function documentation extracted from texinfo source in octave source files.") print("@contents") print("@end ifnottex") print("@node Function Reference") print("@chapter Function Reference") print("@cindex Function Reference") def display_standalone_footer(): print("@bye") def display_func(name, ref, help): print ("@c -----------------------------------------") print ("@subsection {}".format(name)) print ("@cindex {}".format(ref)) for l in help: print ("{}".format(l)) def process (args): options = { "verbose": False, "srcdir": [], "funcprefix": "", "ignore": [], "standalone": False, "allowscan": False } indexfile = "" for a in args: #print ("{}".format(a)) c=a.split("=") key=c[0] if len(c) > 1: val=c[1] else: val="" if key == "--verbose": options["verbose"] = True; if key == "--standalone": options["standalone"] = True; elif key == "--allowscan": options["allowscan"] = True; elif key == "--src-dir": if val: options["srcdir"].append(val); elif key == "--ignore": if val: options["ignore"].append(val); elif key == "--func-prefix": if val: options["funcprefix"] = val; elif val == "": if indexfile == "": indexfile = key if indexfile == "": raise Exception("No index filename") if len(options["srcdir"]) == 0: options["srcdir"].append("inst") #print "options=", options if options['standalone']: display_standalone_header() idx = read_index(indexfile, options["ignore"]) for g in idx.groups: #print ("************ {}".format(g.name)) g_name = texify_line(g.name) print ("@c ---------------------------------------------------") print ("@node {}".format(g_name)) print ("@section {}".format(g_name)) print ("@cindex {}".format(g_name)) for f in sorted(g.functions): print ("@c {} {}".format(g_name, f)) h = "" filename = "" path = "" if "@" in f: #print ("class func") path = f name = "@" + f ref = f.split("/")[-1] filename, lineno = find_func_file(path, options["srcdir"], options["funcprefix"]) elif "." in f: path = f ref = f.split(".")[-1] name = f.split(".")[-1] filename, lineno = find_class_file(path, options["srcdir"]) if not filename: parts = f.split('.') cnt = 0 path = "" for p in parts: if cnt < len(parts)-1: path = path + "/+" else: path = path + "/" path = path + p cnt = cnt + 1 name = f; ref = parts[-1] filename, lineno = find_func_file(path, options["srcdir"], options["funcprefix"]) elif "/" in f: path = f name = f ref = f.split("/")[-1] filename, lineno = find_func_file(path, options["srcdir"], options["funcprefix"]) else: path = f name = f ref = f filename, lineno = find_func_file(path, options["srcdir"], options["funcprefix"], options['allowscan']) if not filename: sys.stderr.write("Warning: Cant find source file for {}\n".format(f)) else: h = read_help (filename, lineno) if h: display_func (name, ref, h) if options['standalone']: display_standalone_footer() def show_usage(): print (sys.argv[0], "[options] indexfile") if __name__ == "__main__": if len(sys.argv) > 1: status = process(sys.argv[1:]) sys.exit(status) else: show_usage() signal-1.4.6/doc/mkqhcp.py0000755000000000000000000001212114673270174012342 0ustar00#!/usr/bin/python3 ## mkqhcp.py ## Version 1.0.3 ## Copyright 2022-2023 John Donoghue ## ## 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 ## . import sys import os import re def process(name): with open(name + ".qhcp", 'wt') as f: f.write ('\n') f.write ('\n') f.write (' \n') f.write (' \n') f.write (' \n') f.write (' {0}.qhp\n'.format(name)) f.write (' {0}.qch\n'.format(name)) f.write (' \n') f.write (' \n') f.write (' \n') f.write (' {0}.qch\n'.format(name)) f.write (' \n') f.write (' \n') f.write ('\n') title = name pat_match = re.compile(r".*(?P<title>[^<]+).*") with open(name + ".html", 'rt') as fin: # find html for line in fin: line = line.strip() e = pat_match.match(line) if e: title = e.group("title") break h2_match = re.compile(r'.*

]*>(?P[^<]+)</h2>.*') h3_match = re.compile(r'.*<h3 class="section"[^>]*>(?P<title>[^<]+)</h3>.*') h4_match = re.compile(r'.*<h4 class="subsection"[^>]*>(?P<title>[^<]+)</h4>.*') tag_match1 = re.compile(r'.*<span id="(?P<tag>[^"]+)"[^>]*></span>.*') #tag_match2 = re.compile(r'.*<div class="[sub]*section" id="(?P<tag>[^"]+)"[^>]*>.*') tag_match2 = re.compile(r'.*<div class="[sub]*section[^"]*" id="(?P<tag>[^"]+)"[^>]*>.*') tag_match3 = re.compile(r'.*<div class="chapter-level-extent" id="(?P<tag>[^"]+)"[^>]*>.*') index_match = re.compile(r'.*<h4 class="subsection"[^>]*>[\d\.\s]*(?P<name>[^<]+)</h4>.*') tag = "top" has_h2 = False has_h3 = False #pat_match = re.compile(r'.*<span id="(?P<tag>[^"])"></span>(?P<title>[.]+)$') with open(name + ".html", 'rt') as fin: with open(name + ".qhp", 'wt') as f: f.write('<?xml version="1.0" encoding="UTF-8"?>\n') f.write('<QtHelpProject version="1.0">\n') f.write(' <namespace>octave.community.{}</namespace>\n'.format(name)) f.write(' <virtualFolder>doc</virtualFolder>\n') f.write(' <filterSection>\n') f.write(' <toc>\n') f.write(' <section title="{} Manual" ref="{}.html">\n'.format(title, name)) # chapters here for line in fin: line = line.strip() e = tag_match1.match(line) if not e: e = tag_match2.match(line) if not e: e = tag_match3.match(line) if e: tag = e.group("tag") e = h2_match.match(line) if e: if has_h3: f.write(' </section>\n') has_h3 = False if has_h2: f.write(' </section>\n') has_h2 = True f.write(' <section title="{}" ref="{}.html#{}">\n'.format(e.group("title"), name, tag)) e = h3_match.match(line) if e: if has_h3: f.write(' </section>\n') has_h3 = True f.write(' <section title="{}" ref="{}.html#{}">\n'.format(e.group("title"), name, tag)) e = h4_match.match(line) if e: f.write(' <section title="{}" ref="{}.html#{}"></section>\n'.format(e.group("title"), name, tag)) if has_h3: f.write(' </section>\n') if has_h2: f.write(' </section>\n') f.write(' </section>\n') f.write(' </toc>\n') f.write(' <keywords>\n') fin.seek(0) for line in fin: line = line.strip() e = tag_match1.match(line) if not e: e = tag_match2.match(line) if e: tag = e.group("tag") e = index_match.match(line) if e: f.write(' <keyword name="{}" ref="{}.html#{}"></keyword>\n'.format(e.group("name"), name, tag)) f.write(' </keywords>\n') f.write(' <files>\n') f.write(' <file>{}.html</file>\n'.format(name)) f.write(' <file>{}.css</file>\n'.format(name)) f.write(' </files>\n') f.write(' </filterSection>\n') f.write('</QtHelpProject>\n') def show_usage(): print (sys.argv[0], "projname") if __name__ == "__main__": if len(sys.argv) > 1: status = process(sys.argv[1]) sys.exit(status) else: show_usage() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/doc/signal.css�������������������������������������������������������������������������0000644�0000000�0000000�00000001337�14673270174�012500� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pre.example, .header, .float-caption, hr { /* base00 ~ body text in light solarized theme */ color: #657b83; border-color: #657b83; } pre.example { /* base3 ~ background color in light solarized theme */ background-color: #fdf6e3; padding: 0.5em; } table.cartouche { border: 1px solid #948473; background-color: #FFE3C6; width: 100%; } table.cartouche td, table.cartouche th { border: 1px solid #948473; padding: 4px 4px; } /* newer texinfo generation styles */ div.example { /* base00 ~ body text in light solarized theme */ color: #657b83; border-color: #657b83; } pre.example-preformatted { /* base3 ~ background color in light solarized theme */ background-color: #fdf6e3; padding: 0.5em; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/doc/signal.info������������������������������������������������������������������������0000644�0000000�0000000�00000565414�14673270174�012656� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������This is signal.info, produced by makeinfo version 7.1 from signal.texi. INFO-DIR-SECTION Math START-INFO-DIR-ENTRY * Octave Signal: (signal). Signal Toolkit for Octave END-INFO-DIR-ENTRY  File: signal.info, Node: Top, Next: Overview, Up: (dir) Octave Signal Toolkit ********************* Copyright © The Octave Project Developers Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions. * Menu: * Overview:: * Installing and loading:: * Function Reference:: -- The Detailed Node Listing -- Function Reference * Signals:: * Signal Measurement:: * Correlation and Convolution:: * Filtering:: * Filter Analysis:: * Filter Conversion:: * IIR Filter Design:: * FIR Filter Design:: * Transforms:: * Power Spectrum Analysis:: * Window Functions:: * System Identification:: * Sample Rate Change:: * Pulse Metrics:: * Utility::  File: signal.info, Node: Overview, Next: Installing and loading, Prev: Top, Up: Top 1 Overview ********** The Signal Toolkit contains signal processing tools, including filtering, windowing and display functions.  File: signal.info, Node: Installing and loading, Next: Function Reference, Prev: Overview, Up: Top 2 Installing and loading ************************ The Signal Toolkit must be installed and then loaded to be used. It can be installed in GNU Octave directly from octave-forge, 2.1 Windows install =================== If running in Windows, the package may already be installed, to check run: pkg list signal 2.2 Installing ============== With an internet connection available, the Signal package can be installed from octave-forge using the following command within GNU Octave: pkg install -forge signal The latest released version of the toolkit will be downloaded and installed. Otherwise, if the package file has already been downloaded it can be installed using the follwoing command in GNU Octave: pkg install signal-1.4.6.tar.gz 2.3 Loading =========== Regardless of the method of installing the toolkit, in order to use its functions, the toolkit must be loaded using the pkg load command: pkg load signal The toolkit must be loaded on each GNU Octave session.  File: signal.info, Node: Function Reference, Prev: Installing and loading, Up: Top 3 Function Reference ******************** * Menu: * Signals:: * Signal Measurement:: * Correlation and Convolution:: * Filtering:: * Filter Analysis:: * Filter Conversion:: * IIR Filter Design:: * FIR Filter Design:: * Transforms:: * Power Spectrum Analysis:: * Window Functions:: * System Identification:: * Sample Rate Change:: * Pulse Metrics:: * Utility::  File: signal.info, Node: Signals, Next: Signal Measurement, Up: Function Reference 3.1 Signals =========== 3.1.1 buffer ------------ -- Function File: Y = buffer (X, N, P, OPT) -- Function File: [Y, Z, OPT] = buffer (...) Buffer a signal into a data frame. The arguments to ‘buffer’ are X The data to be buffered. N The number of rows in the produced data buffer. This is an positive integer value and must be supplied. P An integer less than N that specifies the under- or overlap between column in the data frame. The default value of P is 0. OPT In the case of an overlap, OPT can be either a vector of length P or the string 'nodelay'. If OPT is a vector, then the first P entries in Y will be filled with these values. If OPT is the string 'nodelay', then the first value of Y corresponds to the first value of X. In the can of an underlap, OPT must be an integer between 0 and ‘-P’. The represents the initial underlap of the first column of Y. The default value for OPT the vector ‘zeros (1, P)’ in the case of an overlap, or 0 otherwise. In the case of a single output argument, Y will be padded with zeros to fill the missing values in the data frame. With two output arguments Z is the remaining data that has not been used in the current data frame. Likewise, the output OPT is the overlap, or underlap that might be used for a future call to ‘code’ to allow continuous buffering. 3.1.2 chirp ----------- -- Function File: chirp (T) -- Function File: chirp (T, F0) -- Function File: chirp (T, F0, T1) -- Function File: chirp (T, F0, T1, F1) -- Function File: chirp (T, F0, T1, F1, SHAPE) -- Function File: chirp (T, F0, T1, F1, SHAPE, PHASE) Evaluate a chirp signal at time T. A chirp signal is a frequency swept cosine wave. T vector of times to evaluate the chirp signal F0 frequency at time t=0 [ 0 Hz ] T1 time t1 [ 1 sec ] F1 frequency at time t=t1 [ 100 Hz ] SHAPE shape of frequency sweep 'linear' f(t) = (f1-f0)*(t/t1) + f0 'quadratic' f(t) = (f1-f0)*(t/t1)^2 + f0 'logarithmic' f(t) = (f1/f0)^(t/t1) * f0 PHASE phase shift at t=0 For example: specgram (chirp ([0:0.001:5])); # default linear chirp of 0-100Hz in 1 sec specgram (chirp ([-2:0.001:15], 400, 10, 100, "quadratic")); soundsc (chirp ([0:1/8000:5], 200, 2, 500, "logarithmic"), 8000); If you want a different sweep shape f(t), use the following: y = cos (2 * pi * integral (f(t)) + phase); 3.1.3 cmorwavf -------------- -- Function File: [PSI, X] = cmorwavf (LB, UB, N, FB, FC) Compute the Complex Morlet wavelet. 3.1.4 diric ----------- -- Function File: Y = diric (X,N) Compute the dirichlet function. See also: sinc, gauspuls, sawtooth. 3.1.5 gauspuls -------------- -- Function File: Y = gauspuls (T) -- Function File: Y = gauspuls (T, FC) -- Function File: Y = gauspuls (T, FC, BW) Generate a Gaussian modulated sinusoidal pulse sampled at times T. See also: pulstran, rectpuls, tripuls. 3.1.6 gmonopuls --------------- -- Function File: Y = gmonopuls (T,FC) Return the gaussian monopulse. 3.1.7 mexihat ------------- -- Function File: [PSI, X] = mexihat (LB, UB, N) Compute the Mexican hat wavelet. 3.1.8 meyeraux -------------- -- Function File: Y = meyeraux (X) Compute the Meyer wavelet auxiliary function. 3.1.9 morlet ------------ -- Function File: [PSI, X] = morlet (LB, UB, N) Compute the Morlet wavelet. 3.1.10 pulstran --------------- -- Function File: Y = pulstran (T, D, FUNC, ...) -- Function File: Y = pulstran (T, D, P) -- Function File: Y = pulstran (T, D, P, FS) -- Function File: Y = pulstran (T, D, P, FS, METHOD) Generate the signal y=sum(func(t+d,...)) for each d. If d is a matrix of two columns, the first column is the delay d and the second column is the amplitude a, and y=sum(a*func(t+d)) for each d,a. Clearly, func must be a function which accepts a vector of times. Any extra arguments needed for the function must be tagged on the end. Example: fs = 11025; # arbitrary sample rate f0 = 100; # pulse train sample rate w = 0.001; # pulse width of 1 millisecond auplot (pulstran (0:1/fs:0.1, 0:1/f0:0.1, "rectpuls", w), fs); If instead of a function name you supply a pulse shape sampled at frequency Fs (default 1 Hz), an interpolated version of the pulse is added at each delay d. The interpolation stays within the the time range of the delayed pulse. The interpolation method defaults to linear, but it can be any interpolation method accepted by the function interp1. Example: fs = 11025; # arbitrary sample rate f0 = 100; # pulse train sample rate w = boxcar(10); # pulse width of 1 millisecond at 10 kHz auplot (pulstran (0:1/fs:0.1, 0:1/f0:0.1, w, 10000), fs); 3.1.11 rectpuls --------------- -- Function File: Y = rectpuls (T) -- Function File: Y = rectpuls (T, W) Generate a rectangular pulse over the interval [-W/2,W/2), sampled at times T. This is useful with the function ‘pulstran’ for generating a series of pulses. Example: fs = 11025; # arbitrary sample rate f0 = 100; # pulse train sample rate w = 0.3/f0; # pulse width 3/10th the distance between pulses plot (pulstran (0:1/fs:4/f0, 0:1/f0:4/f0, "rectpuls", w)); See also: gauspuls, pulstran, tripuls. 3.1.12 sawtooth --------------- -- Function File: Y = sawtooth (T) -- Function File: Y = sawtooth (T, WIDTH) Generates a sawtooth wave of period ‘2 * pi’ with limits ‘+1/-1’ for the elements of T. WIDTH is a real number between ‘0’ and ‘1’ which specifies the point between ‘0’ and ‘2 * pi’ where the maximum is. The function increases linearly from ‘-1’ to ‘1’ in ‘[0, 2 * pi * WIDTH]’ interval, and decreases linearly from ‘1’ to ‘-1’ in the interval ‘[2 * pi * WIDTH, 2 * pi]’. If WIDTH is 0.5, the function generates a standard triangular wave. If WIDTH is not specified, it takes a value of 1, which is a standard sawtooth function. 3.1.13 shanwavf --------------- -- Function File: [PSI, X] = shanwavf (LB, UB, N, FB, FC) Compute the Complex Shannon wavelet. 3.1.14 shiftdata ---------------- -- Function File: [OUT PERM SHIFTS] = shiftdata (IN) -- Function File: [OUT PERM SHIFTS] = shiftdata (IN, DIM) Shift data IN to permute the dimension DIM to the first column. See also: unshiftdata. 3.1.15 sigmoid_train -------------------- -- Function File: [Y S] = sigmoid_train (T, RANGES, RC) Evaluate a train of sigmoid functions at T. The number and duration of each sigmoid is determined from RANGES. Each row of RANGES represents a real interval, e.g. if sigmoid ‘i’ starts at ‘t=0.1’ and ends at ‘t=0.5’, then ‘RANGES(i,:) = [0.1 0.5]’. The input RC is an array that defines the rising and falling time constants of each sigmoid. Its size must equal the size of RANGES. The individual sigmoids are returned in S. The combined sigmoid train is returned in the vector Y of length equal to T, and such that ‘Y = max (S)’. Run ‘demo sigmoid_train’ to some examples of the use of this function. 3.1.16 specgram --------------- -- Function File: specgram (X) -- Function File: specgram (X, N) -- Function File: specgram (X, N, FS) -- Function File: specgram (X, N, FS, WINDOW) -- Function File: specgram (X, N, FS, WINDOW, OVERLAP) -- Function File: [S, F, T] = specgram (...) Generate a spectrogram for the signal X. The signal is chopped into overlapping segments of length N, and each segment is windowed and transformed into the frequency domain using the FFT. The default segment size is 256. If FS is given, it specifies the sampling rate of the input signal. The argument WINDOW specifies an alternate window to apply rather than the default of ‘hanning (N)’. The argument OVERLAP specifies the number of samples overlap between successive segments of the input signal. The default overlap is ‘length (WINDOW)/2’. If no output arguments are given, the spectrogram is displayed. Otherwise, S is the complex output of the FFT, one row per slice, F is the frequency indices corresponding to the rows of S, and T is the time indices corresponding to the columns of S. Example: x = chirp([0:0.001:2],0,2,500); # freq. sweep from 0-500 over 2 sec. Fs=1000; # sampled every 0.001 sec so rate is 1 kHz step=ceil(20*Fs/1000); # one spectral slice every 20 ms window=ceil(100*Fs/1000); # 100 ms data window specgram(x, 2^nextpow2(window), Fs, window, window-step); ## Speech spectrogram [x, Fs] = auload(file_in_loadpath("sample.wav")); # audio file step = fix(5*Fs/1000); # one spectral slice every 5 ms window = fix(40*Fs/1000); # 40 ms data window fftn = 2^nextpow2(window); # next highest power of 2 [S, f, t] = specgram(x, fftn, Fs, window, window-step); S = abs(S(2:fftn*4000/Fs,:)); # magnitude in range 0<f<=4000 Hz. S = S/max(S(:)); # normalize magnitude so that max is 0 dB. S = max(S, 10^(-40/10)); # clip below -40 dB. S = min(S, 10^(-3/10)); # clip above -3 dB. imagesc (t, f, log(S)); # display in log scale set (gca, "ydir", "normal"); # put the 'y' direction in the correct direction The choice of window defines the time-frequency resolution. In speech for example, a wide window shows more harmonic detail while a narrow window averages over the harmonic detail and shows more formant structure. The shape of the window is not so critical so long as it goes gradually to zero on the ends. Step size (which is window length minus overlap) controls the horizontal scale of the spectrogram. Decrease it to stretch, or increase it to compress. Increasing step size will reduce time resolution, but decreasing it will not improve it much beyond the limits imposed by the window size (you do gain a little bit, depending on the shape of your window, as the peak of the window slides over peaks in the signal energy). The range 1-5 msec is good for speech. FFT length controls the vertical scale. Selecting an FFT length greater than the window length does not add any information to the spectrum, but it is a good way to interpolate between frequency points which can make for prettier spectrograms. After you have generated the spectral slices, there are a number of decisions for displaying them. First the phase information is discarded and the energy normalized: S = abs(S); S = S/max(S(:)); Then the dynamic range of the signal is chosen. Since information in speech is well above the noise floor, it makes sense to eliminate any dynamic range at the bottom end. This is done by taking the max of the magnitude and some minimum energy such as minE=-40dB. Similarly, there is not much information in the very top of the range, so clipping to a maximum energy such as maxE=-3dB makes sense: S = max(S, 10^(minE/10)); S = min(S, 10^(maxE/10)); The frequency range of the FFT is from 0 to the Nyquist frequency of one half the sampling rate. If the signal of interest is band limited, you do not need to display the entire frequency range. In speech for example, most of the signal is below 4 kHz, so there is no reason to display up to the Nyquist frequency of 10 kHz for a 20 kHz sampling rate. In this case you will want to keep only the first 40% of the rows of the returned S and f. More generally, to display the frequency range [minF, maxF], you could use the following row index: idx = (f >= minF & f <= maxF); Then there is the choice of colormap. A brightness varying colormap such as copper or bone gives good shape to the ridges and valleys. A hue varying colormap such as jet or hsv gives an indication of the steepness of the slopes. The final spectrogram is displayed in log energy scale and by convention has low frequencies on the bottom of the image: imagesc(t, f, flipud(log(S(idx,:)))); 3.1.17 square ------------- -- Function File: S = square (T, DUTY) -- Function File: S = square (T) Generate a square wave of period 2 pi with limits +1/-1. If DUTY is specified, it is the percentage of time the square wave is "on". The square wave is +1 for that portion of the time. on time * 100 duty cycle = ------------------ on time + off time See also: cos, sawtooth, sin, tripuls. 3.1.18 tripuls -------------- -- Function File: Y = tripuls (T) -- Function File: Y = tripuls (T, W) -- Function File: Y = tripuls (T, W, SKEW) Generate a triangular pulse over the interval [-W/2,W/2), sampled at times T. This is useful with the function ‘pulstran’ for generating a series of pulses. SKEW is a value between -1 and 1, indicating the relative placement of the peak within the width. -1 indicates that the peak should be at -W/2, and 1 indicates that the peak should be at W/2. The default value is 0. Example: fs = 11025; # arbitrary sample rate f0 = 100; # pulse train sample rate w = 0.3/f0; # pulse width 3/10th the distance between pulses plot (pulstran (0:1/fs:4/f0, 0:1/f0:4/f0, "tripuls", w)); See also: gauspuls, pulstran, rectpuls. 3.1.19 udecode -------------- -- Function File: OUT = udecode (IN, N) -- Function File: OUT = udecode (IN, N, V) -- Function File: OUT = udecode (IN, N, V, OVERFLOWS) Invert the operation of uencode. See also: uencode. 3.1.20 uencode -------------- -- Function File: OUT = uencode (IN, N) -- Function File: OUT = uencode (IN, N, V) -- Function File: OUT = uencode (IN, N, V, SIGNED) Quantize the entries of the array IN using 2^N quantization levels. See also: udecode. 3.1.21 unshiftdata ------------------ -- Function File: [OUT] = unshiftdata (IN, PERM, SHIFTS) Reverse what is done by shiftdata. See also: shiftdata. 3.1.22 vco ---------- -- : y = vco (X, FC, FS) -- : y = vco (X, [FMIN, FMAX], FS) Creates a signal that oscillates at a frequency determined by input X with a sampling frequency FS. Inputs: • X - input data with a range of -1 to 1. A value of -1 means no output, 0 cuoreesponds to FC, and 1 corresponds to 2*FC. • FC - Carrier frequency • FS - Sampling rate • FMIN, FMAX - Frequency modulation range limits. Outputs: • Y - output signal  File: signal.info, Node: Signal Measurement, Next: Correlation and Convolution, Prev: Signals, Up: Function Reference 3.2 Signal Measurement ====================== 3.2.1 findpeaks --------------- -- Function File: [PKS, LOC, EXTRA] = findpeaks (DATA) -- Function File: ... = findpeaks (..., PROPERTY, VALUE) -- Function File: ... = findpeaks (..., "DoubleSided") Finds peaks on DATA. Peaks of a positive array of data are defined as local maxima. For double-sided data, they are maxima of the positive part and minima of the negative part. DATA is expected to be a single column vector. The function returns the value of DATA at the peaks in PKS. The index indicating their position is returned in LOC. The third output argument is a structure with additional information: "parabol" A structure containing the parabola fitted to each returned peak. The structure has two fields, "x" and "pp". The field "pp" contains the coefficients of the 2nd degree polynomial and "x" the extrema of the interval where it was fitted. "height" The estimated height of the returned peaks (in units of DATA). "baseline" The height at which the roots of the returned peaks were calculated (in units of DATA). "roots" The abscissa values (in index units) at which the parabola fitted to each of the returned peaks realizes its width as defined below. This function accepts property-value pair given in the list below: "MinPeakHeight" Minimum peak height (non-negative scalar). Only peaks that exceed this value will be returned. For data taking positive and negative values use the option "DoubleSided". Default value ‘eps’. "MinPeakDistance" Minimum separation between (positive integer). Peaks separated by less than this distance are considered a single peak. This distance is also used to fit a second order polynomial to the peaks to estimate their width, therefore it acts as a smoothing parameter. The neighborhood size is equal to the value of "MinPeakDistance". Default value 1. "MinPeakWidth" Minimum width of peaks (positive integer). The width of the peaks is estimated using a parabola fitted to the neighborhood of each peak. The width is caulculated with the formula a * (width - x0)^2 = 1 where a is the the concavity of the parabola and x0 its vertex. Default value 1. "MaxPeakWidth" Maximum width of peaks (positive integer). Default value ‘Inf’. "DoubleSided" Tells the function that data takes positive and negative values. The base-line for the peaks is taken as the mean value of the function. This is equivalent as passing the absolute value of the data after removing the mean. Run ‘demo findpeaks’ to see some examples. 3.2.2 peak2peak --------------- -- Function File: Y = peak2peak (X) -- Function File: Y = peak2peak (X, DIM) Compute the difference between the maximum and minimum values in the vector X. If X is a matrix, compute the difference for each column and return them in a row vector. If the optional argument DIM is given, operate along this dimension. See also: max, min, peak2rms, rms, rssq. 3.2.3 peak2rms -------------- -- Function File: Y = peak2rms (X) -- Function File: Y = peak2rms (X, DIM) Compute the ratio of the largest absolute value to the root-mean-square (RMS) value of the vector X. If X is a matrix, compute the peak-magnitude-to-RMS ratio for each column and return them in a row vector. If the optional argument DIM is given, operate along this dimension. See also: max, min, peak2peak, rms, rssq. 3.2.4 rms --------- -- Function File: Y = rms (X) -- Function File: Y = rms (X, DIM) Compute the root-mean-square (RMS) of the vector X. The root-mean-square is defined as rms (X) = SQRT (1/N SUM_i X(i)^2) If X is a matrix, compute the root-mean-square for each column and return them in a row vector. If the optional argument DIM is given, operate along this dimension. See also: mean, meansq, peak2rms, rssq, sumsq. 3.2.5 rssq ---------- -- Function File: Y = rssq (X) -- Function File: Y = rssq (X, DIM) Compute the root-sum-of-squares (RSS) of the vector X. The root-sum-of-squares is defined as rssq (X) = SQRT (SUM_i X(i)^2) If X is a matrix, compute the root-sum-of-squares for each column and return them in a row vector. If the optional argument DIM is given, operate along this dimension. See also: mean, meansq, sumsq, rms.  File: signal.info, Node: Correlation and Convolution, Next: Filtering, Prev: Signal Measurement, Up: Function Reference 3.3 Correlation and Convolution =============================== 3.3.1 cconv ----------- -- Function File: C = cconv (A, B, N) -- Function File: C = cconv (A, B) Compute the modulo-N circular convolution. A and B are input vectors and C is the modolo-N convolution of A and B. If N is not provided, its assumed default value is ‘length(A) + length(B) - 1’, which provides the same result as a linear convolution. Examples: cconv (1:2, 1:4) ⇒ 1 4 7 10 8 cconv (1:2, 1:4, 2) ⇒ 16 14 cconv (1:2, 1:4, 4) ⇒ 9 4 7 10 See also: conv, circshift. 3.3.2 convmtx ------------- -- Function File: convmtx (A, N) If A is a column vector and X is a column vector of length N, then ‘convmtx(A, N) * X’ gives the convolution of of A and X and is the same as ‘conv(A, X)’. The difference is if many vectors are to be convolved with the same vector, then this technique is possibly faster. Similarly, if A is a row vector and X is a row vector of length N, then ‘X * convmtx(A, N)’ is the same as ‘conv(X, A)’. See also: conv. 3.3.3 wconv ----------- -- Function File: Y = wconv (TYPE, X, F) -- Function File: Y = wconv (TYPE, X, F, SHAPE) 1-D or 2-D convolution. *Inputs* TYPE Type of convolution. X Signal vector or matrix. F Coefficients of FIR filter. SHAPE Shape. *Outputs* Y Convoluted signal. 3.3.4 xcorr ----------- -- Function File: [R, LAG] = xcorr ( X ) -- Function File: ... = xcorr ( X, Y ) -- Function File: ... = xcorr ( ..., MAXLAG) -- Function File: ... = xcorr ( ..., SCALE) Estimates the cross-correlation. Estimate the cross correlation R_xy(k) of vector arguments X and Y or, if Y is omitted, estimate autocorrelation R_xx(k) of vector X, for a range of lags k specified by argument "maxlag". If X is a matrix, each column of X is correlated with itself and every other column. The cross-correlation estimate between vectors "x" and "y" (of length N) for lag "k" is given by N R_xy(k) = sum x_{i+k} conj(y_i), i=1 where data not provided (for example x(-1), y(N+1)) is zero. Note the definition of cross-correlation given above. To compute a cross-correlation consistent with the field of statistics, see ‘xcov’. *ARGUMENTS* X [non-empty; real or complex; vector or matrix] data Y [real or complex vector] data If X is a matrix (not a vector), Y must be omitted. Y may be omitted if X is a vector; in this case xcorr estimates the autocorrelation of X. MAXLAG [integer scalar] maximum correlation lag If omitted, the default value is N-1, where N is the greater of the lengths of X and Y or, if X is a matrix, the number of rows in X. SCALE [character string] specifies the type of scaling applied to the correlation vector (or matrix). is one of: ‘none’ return the unscaled correlation, R, ‘biased’ return the biased average, R/N, ‘unbiased’ return the unbiased average, R(k)/(N-|k|), ‘coeff or normalized’ return the correlation coefficient, R/(rms(x).rms(y)), where "k" is the lag, and "N" is the length of X. If omitted, the default value is "none". If Y is supplied but does not have the same length as X, scale must be "none". *RETURNED VARIABLES* R array of correlation estimates LAG row vector of correlation lags [-maxlag:maxlag] The array of correlation estimates has one of the following forms: (1) Cross-correlation estimate if X and Y are vectors. (2) Autocorrelation estimate if is a vector and Y is omitted. (3) If X is a matrix, R is an matrix containing the cross-correlation estimate of each column with every other column. Lag varies with the first index so that R has 2*maxlag+1 rows and P^2 columns where P is the number of columns in X. If Rij(k) is the correlation between columns i and j of X ‘R(k+maxlag+1,P*(i-1)+j) == Rij(k)’ for lag k in [-maxlag:maxlag], or ‘R(:,P*(i-1)+j) == xcorr(X(:,i),X(:,j))’. ‘reshape(R(k,:),P,P)’ is the cross-correlation matrix for ‘X(k,:)’. See also: xcov. 3.3.5 xcorr2 ------------ -- Function File: xcorr2 (A) -- Function File: xcorr2 (A, B) -- Function File: xcorr2 (..., SCALE) Compute the 2D cross-correlation of matrices A and B. If B is not specified, computes autocorrelation of A, i.e., same as ‘xcorr (A, A)’. The optional argument SCALE, defines the type of scaling applied to the cross-correlation matrix. Possible values are: "none" (default) No scaling. "biased" Scales the raw cross-correlation by the maximum number of elements of A and B involved in the generation of any element of C. "unbiased" Scales the raw correlation by dividing each element in the cross-correlation matrix by the number of products A and B used to generate that element. "coeff" Scales the normalized cross-correlation on the range of [0 1] so that a value of 1 corresponds to a correlation coefficient of 1. See also: conv2, corr2, xcorr. 3.3.6 xcov ---------- -- Function File: [R, LAG] = xcov ( X ) -- Function File: ... = xcov ( X, Y ) -- Function File: ... = xcov ( ..., MAXLAG) -- Function File: ... = xcov ( ..., SCALE) Compute covariance at various lags [=correlation(x-mean(x),y-mean(y))]. X input vector Y if specified, compute cross-covariance between X and Y, otherwise compute autocovariance of X. MAXLAG is specified, use lag range [-maxlag:maxlag], otherwise use range [-n+1:n-1]. SCALE: ‘biased’ for covariance=raw/N, ‘unbiased’ for covariance=raw/(N-|lag|), ‘coeff’ for covariance=raw/(covariance at lag 0), ‘none’ for covariance=raw ‘none’ is the default. Returns the covariance for each lag in the range, plus an optional vector of lags. See also: xcorr.  File: signal.info, Node: Filtering, Next: Filter Analysis, Prev: Correlation and Convolution, Up: Function Reference 3.4 Filtering ============= 3.4.1 filtfilt -------------- -- Function File: Y = filtfilt (B, A, X) Forward and reverse filter the signal. This corrects for phase distortion introduced by a one-pass filter, though it does square the magnitude response in the process. That's the theory at least. In practice the phase correction is not perfect, and magnitude response is distorted, particularly in the stop band. Example [b, a]=butter(3, 0.1); # 5 Hz low-pass filter t = 0:0.01:1.0; # 1 second sample x=sin(2*pi*t*2.3)+0.25*randn(size(t)); # 2.3 Hz sinusoid+noise y = filtfilt(b,a,x); z = filter(b,a,x); # apply filter plot(t,x,';data;',t,y,';filtfilt;',t,z,';filter;') 3.4.2 filtic ------------ -- Function File: ZF = filtic (B, A, Y) -- Function File: ZF = filtic (B, A, Y, X) Set initial condition vector for filter function The vector zf has the same values that would be obtained from function filter given past inputs x and outputs y The vectors x and y contain the most recent inputs and outputs respectively, with the newest values first: x = [x(-1) x(-2) ... x(-nb)], nb = length(b)-1 y = [y(-1) y(-2) ... y(-na)], na = length(a)-a If length(x)<nb then it is zero padded If length(y)<na then it is zero padded zf = filtic(b, a, y) Initial conditions for filter with coefficients a and b and output vector y, assuming input vector x is zero zf = filtic(b, a, y, x) Initial conditions for filter with coefficients a and b input vector x and output vector y 3.4.3 medfilt1 -------------- -- : Y = medfilt1 (X, N) -- : Y = medfilt1 (X, N, [], DIM) -- : Y = medfilt1 (..., NAN_FLAG, PADDING) Apply a one dimensional median filter with a window size of N to the data X, which must be real, double and full. For N = 2m+1, Y(i) is the median of X(i-m:i+m). For N = 2m, Y(i) is the median of X(i-m:i+m-1). The calculation is performed over the first non-singleton dimension, or over dimension DIM if that is specified as the fourth argument. (The third argument is ignored; Matlab used to use it to tune its algorithm.) NAN_FLAG may be omitnan or includenan (the default). If it is omitnan then any NaN values are removed from the window before the median is taken. Otherwise, any window containing an NaN returns a median of NaN. PADDING determines how the partial windows at the start and end of X are treated. It may be truncate or zeropad (the default). If it is truncate then the window for Y(i) is the intersection of the window stated above with 1:length(X). If it is zeropad, then partial windows have additional zeros to bring them up to size N. See also: filter, medfilt2. 3.4.4 movingrms --------------- -- Function File: [RMSX,W] = movingrms (X,W,RC,FS=1) Calculate moving RMS value of the signal in X. The signal is convoluted against a sigmoid window of width W and risetime RC. The units of these parameters are relative to the value of the sampling frequency given in FS (Default value = 1). Run ‘demo movingrms’ to see an example. See also: sigmoid_train. 3.4.5 sgolayfilt ---------------- -- Function File: Y = sgolayfilt (X) -- Function File: Y = sgolayfilt (X, P) -- Function File: Y = sgolayfilt (X, P, N) -- Function File: Y = sgolayfilt (X, P, N, M) -- Function File: Y = sgolayfilt (X, P, N, M, TS) -- Function File: Y = sgolayfilt (X, P, N, M, TS) -- Function File: Y = sgolayfilt (X, F) Smooth the data in x with a Savitsky-Golay smoothing filter of polynomial order p and length n, n odd, n > p. By default, p=3 and n=p+2 or n=p+3 if p is even. If F is given as a matrix, it is expected to be a filter as computed by ‘sgolay’. These filters are particularly good at preserving lineshape while removing high frequency squiggles. Particularly, compare a 5 sample averager, an order 5 butterworth lowpass filter (cutoff 1/3) and sgolayfilt(x, 3, 5), the best cubic estimated from 5 points: [b, a] = butter (5, 1/3); x = [zeros(1,15), 10*ones(1,10), zeros(1,15)]; plot (sgolayfilt (x), "r;sgolayfilt;", ... filtfilt (ones (1,5)/5, 1, x), "g;5 sample average;", ... filtfilt (b, a, x), "c;order 5 butterworth;", ... x, "+b;original data;"); See also: sgolay. 3.4.6 sosfilt ------------- -- Loadable Function: Y = sosfilt (SOS, X) Second order section IIR filtering of X. The second order section filter is described by the matrix SOS with: [ B1 A1 ] SOS = [ ... ], [ BN AN ] where ‘B1 = [b0 b1 b2]’ and ‘A1 = [1 a1 a2]’ for section 1, etc. The b0 entry must be nonzero for each section.  File: signal.info, Node: Filter Analysis, Next: Filter Conversion, Prev: Filtering, Up: Function Reference 3.5 Filter Analysis =================== 3.5.1 filternorm ---------------- -- Function File: L = filternorm (B, A) -- Function File: L = filternorm (B, A, PNORM) -- Function File: L = filternorm (B, A, 2, TOL) Compute the 2-norm of a digital filter defined by the numerator coefficients, B, and the denominator coefficients, A. It is also possible to compute the infinity-norm by passing inf in the PNORM parameter. PNORM only accepts 2 or inf. Example: [b, a] = butter (8, 0.5); filternorm (b, a) 3.5.2 filtord ------------- -- Function File: N = filtord (B, A) -- Function File: N = filtord (SOS) Returns the filter order N for a filter defined by the numerator coefficients, B, and the denominator coefficients, A. It also accepts a filter defined by a matrix of second-order sections, SOS. Example: [b, a] = butter (8, 0.5); filtord (b, a) 3.5.3 freqs ----------- -- Function File: H = freqs (B, A, W) -- Function File: freqs (B, A, W) Compute the s-plane frequency response of the IIR filter B(s)/A(s) as H = polyval(B,j*W)./polyval(A,j*W). If called with no output argument, a plot of magnitude and phase are displayed. Example: b = [1 2]; a = [1 1]; w = linspace (0, 4, 128); freqs (b, a, w); 3.5.4 freqs_plot ---------------- -- Function File: freqs_plot (W, H) Plot the amplitude and phase of the vector H. 3.5.5 fwhm ---------- -- Function File: F = fwhm (Y) -- Function File: F = fwhm (X, Y) -- Function File: F = fwhm (..., "zero") -- Function File: F = fwhm (..., "min") -- Function File: F = fwhm (..., "alevel", LEVEL) -- Function File: F = fwhm (..., "rlevel", LEVEL) Compute peak full-width at half maximum (FWHM) or at another level of peak maximum for vector or matrix data Y, optionally sampled as y(x). If Y is a matrix, return FWHM for each column as a row vector. The default option "zero" computes fwhm at half maximum, i.e. 0.5*max(y). The option "min" computes fwhm at the middle curve, i.e. 0.5*(min(y)+max(y)). The option "rlevel" computes full-width at the given relative level of peak profile, i.e. at rlevel*max(y) or rlevel*(min(y)+max(y)), respectively. For example, ‘fwhm (..., "rlevel", 0.1)’ computes full width at 10 % of peak maximum with respect to zero or minimum; FWHM is equivalent to ‘fwhm(..., "rlevel", 0.5)’. The option "alevel" computes full-width at the given absolute level of Y. Return 0 if FWHM does not exist (e.g. monotonous function or the function does not cut horizontal line at rlevel*max(y) or rlevel*(max(y)+min(y)) or alevel, respectively). 3.5.6 grpdelay -------------- -- Function File: [G, W] = grpdelay (B) -- Function File: [G, W] = grpdelay (B, A) -- Function File: [G, W] = grpdelay (..., N) -- Function File: [G, W] = grpdelay (..., N, "whole") -- Function File: [G, F] = grpdelay (..., N, FS) -- Function File: [G, F] = grpdelay (..., N, "whole", FS) -- Function File: [G, W] = grpdelay (..., W) -- Function File: [G, F] = grpdelay (..., F, FS) -- Function File: grpdelay (...) Compute the group delay of a filter. [g, w] = grpdelay(b) returns the group delay g of the FIR filter with coefficients b. The response is evaluated at 512 angular frequencies between 0 and pi. w is a vector containing the 512 frequencies. The group delay is in units of samples. It can be converted to seconds by multiplying by the sampling period (or dividing by the sampling rate fs). [g, w] = grpdelay(b,a) returns the group delay of the rational IIR filter whose numerator has coefficients b and denominator coefficients a. [g, w] = grpdelay(b,a,n) returns the group delay evaluated at n angular frequencies. For fastest computation n should factor into a small number of small primes. [g, w] = grpdelay(b,a,n,'whole') evaluates the group delay at n frequencies between 0 and 2*pi. [g, f] = grpdelay(b,a,n,Fs) evaluates the group delay at n frequencies between 0 and Fs/2. [g, f] = grpdelay(b,a,n,'whole',Fs) evaluates the group delay at n frequencies between 0 and Fs. [g, w] = grpdelay(b,a,w) evaluates the group delay at frequencies w (radians per sample). [g, f] = grpdelay(b,a,f,Fs) evaluates the group delay at frequencies f (in Hz). grpdelay(...) plots the group delay vs. frequency. If the denominator of the computation becomes too small, the group delay is set to zero. (The group delay approaches infinity when there are poles or zeros very close to the unit circle in the z plane.) Theory: group delay, g(w) = -d/dw [arg{H(e^jw)}], is the rate of change of phase with respect to frequency. It can be computed as: d/dw H(e^-jw) g(w) = ------------- H(e^-jw) where H(z) = B(z)/A(z) = sum(b_k z^k)/sum(a_k z^k). By the quotient rule, A(z) d/dw B(z) - B(z) d/dw A(z) d/dw H(z) = ------------------------------- A(z) A(z) Substituting into the expression above yields: A dB - B dA g(w) = ----------- = dB/B - dA/A A B Note that, d/dw B(e^-jw) = sum(k b_k e^-jwk) d/dw A(e^-jw) = sum(k a_k e^-jwk) which is just the FFT of the coefficients multiplied by a ramp. As a further optimization when nfft>>length(a), the IIR filter (b,a) is converted to the FIR filter conv(b,fliplr(conj(a))). For further details, see http://ccrma.stanford.edu/~jos/filters/Numerical_Computation_Group_Delay.html 3.5.7 impz ---------- -- Function File: [X, T] = impz (B) -- Function File: [X, T] = impz (B, A) -- Function File: [X, T] = impz (B, A, N) -- Function File: [X, T] = impz (B, A, N, FS) -- Function File: impz (...) Generate impulse-response characteristics of the filter. The filter coefficients correspond to the the z-plane rational function with numerator b and denominator a. If a is not specified, it defaults to 1. If n is not specified, or specified as [], it will be chosen such that the signal has a chance to die down to -120dB, or to not explode beyond 120dB, or to show five periods if there is no significant damping. If no return arguments are requested, plot the results. See also: freqz, zplane. 3.5.8 isallpass --------------- -- Function File: L = isallpass (B, A) -- Function File: L = isallpass (SOS) Determine whether a digital filter is allpass. The filter might be defined by the numerator coefficients, B, and the denominator coefficients, A, or, alternatively, by a matrix of second-order sections, SOS. Example: a = [1 2 3]; b = [3 2 1]; isallpass (b, a) Ref [1] Shyu, Jong-Jy, & Pei, Soo-Chang, A new approach to the design of complex all-pass IIR digital filters, Signal Processing, 40(2–3), 207–215, 1994. https://doi.org/10.1016/0165-1684(94)90068-x Ref [2] Vaidyanathan, P. P. Multirate Systems and Filter Banks. 1st edition, Pearson College Div, 1992. 3.5.9 ismaxphase ---------------- -- Function File: L = ismaxphase (B, A) -- Function File: L = ismaxphase (SOS) -- Function File: L = ismaxphase (..., TOL) Determine whether a digital filter is maximum phase (maximum energy-delay). The filter might be defined by the numerator coefficients, B, and the denominator coefficients, A, or, alternatively, by a matrix of second-order sections, SOS. A tolerance TOL might be given to define when two numbers are close enough to be considered equal. Example: b = [1 2 4 4 2 1]; zplane (b); ismaxphase (b) Ref [1] Oppenheim, Alan, and Ronald Schafer. Discrete-Time Signal Processing. 3rd edition, Pearson, 2009. 3.5.10 isminphase ----------------- -- Function File: L = isminphase (B, A) -- Function File: L = isminphase (SOS) -- Function File: L = isminphase (..., TOL) Determine whether a digital filter is minimum phase. The filter might be defined by the numerator coefficients, B, and the denominator coefficients, A, or, alternatively, by a matrix of second-order sections, SOS. A toleranve TOL might be given to define when two numbers are close enough to be considered equal. Example: a = [1 0.5]; b = [3 1]; isminphase (b, a) Ref [1] Oppenheim, Alan, and Ronald Schafer. Discrete-Time Signal Processing. 3rd edition, Pearson, 2009. 3.5.11 isstable --------------- -- Function File: FLAG = isstable (B, A) Returns a logical output equal to TRUE, if the filter is stable. This can be done with coeffients of the filer B and A. Alternatively by using a second order sections matrix (SOS). Inputs: • B: Numerator coefficients of the filter • A: Denominator coeffients of the filter. Can be an empty vector. Output: • FLAG: Returns a logical output, equal to TRUE if the filter is stable. Examples: b = [1 2 3 4 5 5 1 2]; a = [4 5 6 7 9 10 4 6]; flag = isstable (b, a) flag = 0 Using SOS [z, p, k] = butter (6, 0.7, 'high'); sos = zp2sos (z, p, k); flag = isstable (sos) flag = 1 3.5.12 phasez ------------- -- Function File: [PHI, W] = phasez (B, A, N) -- Function File: [PHI, W] = phasez (B, A) -- Function File: [PHI, W] = phasez (SOS, N) -- Function File: [PHI, W] = phasez (SOS) -- Function File: [PHI, W] = phasez (..., N, "whole") -- Function File: [PHI, W] = phasez (..., N, Fs) -- Function File: phasez (...) Compute the phase response of digital filter defined either by its coefficients (B and A are the numerator and denominator coefficients respectively) or by its second-order sections representation, given by the matrix SOS. The output PHI is the phase response computed in a vector the vector of frequencies W. The phase response is evaluated at N angular frequencies between 0 and pi. If A is omitted, the denominator is assumed to be 1 (this corresponds to a simple FIR filter). If N is omitted, a value of 512 is assumed. If the third/forth argument, "whole", is given, the response is evaluated at N angular frequencies between 0 and 2*pi. It is possible also to pass the value "half", which will lead to the default behaviour. Example: [b, a] = butter (2, [.15,.3]); phasez (b, a); Ref [1] Oppenheim, Alan, and Ronald Schafer. Discrete-Time Signal Processing. 3rd edition, Pearson, 2009. See also: freqz, phasedelay. 3.5.13 zplane ------------- -- Function File: zplane (Z, P) -- Function File: zplane (B, A) Plot the poles and zeros on a complex plane. If the arguments are column vectors Z and P, the complex zeros Z and poles P are displayed. If the arguments are row vectors B and A, the zeros and poles of the transfer function represented by these filter coefficients are displayed. If Z and P are matrices, the columns are distinct sets of zeros and poles and are displayed together in distinct colors. Note that due to the nature of the ‘roots’ function, poles and zeros may be displayed as occurring around a circle rather than at a single point. The transfer function is B(z) b0 + b1 z^(-1) + b2 z^(-2) + ... + bM z^(-M) H(z) = ---- = -------------------------------------------- A(z) a0 + a1 z^(-1) + a2 z^(-2) + ... + aN z^(-N) b0 (z - z1) (z - z2) ... (z - zM) = -- z^(-M+N) ------------------------------ a0 (z - p1) (z - p2) ... (z - pN) If called with only one argument, the poles P defaults to an empty vector, and the denominator coefficient vector A defaults to 1.  File: signal.info, Node: Filter Conversion, Next: IIR Filter Design, Prev: Filter Analysis, Up: Function Reference 3.6 Filter Conversion ===================== 3.6.1 residued -------------- -- Function File: [R, P, F, M] = residued (B, A) Compute the partial fraction expansion (PFE) of filter H(z) = B(z)/A(z). In the usual PFE function ‘residuez’, the IIR part (poles P and residues R) is driven _in parallel_ with the FIR part (F). In this variant, the IIR part is driven by the _output_ of the FIR part. This structure can be more accurate in signal modeling applications. INPUTS: B and A are vectors specifying the digital filter H(z) = B(z)/A(z). See ‘help filter’ for documentation of the B and A filter coefficients. RETURNED: • R = column vector containing the filter-pole residues • P = column vector containing the filter poles • F = row vector containing the FIR part, if any • M = column vector of pole multiplicities EXAMPLES: See test residued verbose to see a number of examples. For the theory of operation, see ‘http://ccrma.stanford.edu/~jos/filters/residued.html’ See also: residue, residued. 3.6.2 residuez -------------- -- Function File: [R, P, F, M] = residuez (B, A) Compute the partial fraction expansion of filter H(z) = B(z)/A(z). INPUTS: B and A are vectors specifying the digital filter H(z) = B(z)/A(z). See ‘help filter’ for documentation of the B and A filter coefficients. RETURNED: • R = column vector containing the filter-pole residues • P = column vector containing the filter poles • F = row vector containing the FIR part, if any • M = column vector of pole multiplicities EXAMPLES: See test residuez verbose to see a number of examples. For the theory of operation, see ‘http://ccrma.stanford.edu/~jos/filters/residuez.html’ See also: residue, residued. 3.6.3 sos2ss ------------ -- Function File: [A, B, C, D] = sos2ss (SOS) Convert series second-order sections to state-space. See also: sos2ss, ss2tf. 3.6.4 sos2tf ------------ -- Function File: [B, A] = sos2tf (SOS) -- Function File: [B, A] = sos2tf (SOS, G) Convert series second-order sections to transfer function. INPUTS: • SOS = matrix of series second-order sections, one per row: SOS = [B1.' A1.'; ...; BN.' AN.'] where ‘B1.' = [b0 b1 b2] and A1.' = [a0 a1 a2]’ for section 1, etc. a0 is usually equal to 1 because all 2nd order transfer functions can be scaled so that a0 = 1. However, this is not mandatory for this implementation, which supports all kinds of transfer functions, including first order transfer functions. See ‘filter’ for documentation of the second-order direct-form filter coefficients Bi and Ai. • G is an overall gain factor that effectively scales the output B vector (or any one of the input Bi vectors). If not given the gain is assumed to be 1. RETURNED: B and A are vectors specifying the analog or digital filter H(s) = B(s)/A(s) or H(z) = B(z)/A(z). See ‘filter’ for further details. See also: tf2sos, zp2sos, sos2pz, zp2tf, tf2zp. 3.6.5 sos2zp ------------ -- Function File: [Z, P, K] = sos2zp (SOS) -- Function File: [Z, P, K] = sos2zp (SOS, G) Convert series second-order sections to zeros, poles, and gains (pole residues). INPUTS: • SOS = matrix of series second-order sections, one per row: SOS = [B1.' A1.'; ...; BN.' AN.'] where ‘B1.' = [b0 b1 b2] and A1.' = [a0 a1 a2]’ for section 1, etc. a0 is usually equal to 1 because all 2nd order transfer functions can be scaled so that a0 = 1. However, this is not mandatory for this implementation, which supports all kinds of transfer functions, including first order transfer functions. See ‘filter’ for documentation of the second-order direct-form filter coefficients Bi and Ai. • G is an overall gain factor that effectively scales any one of the input Bi vectors. If not given the gain is assumed to be 1. RETURNED: • Z = column-vector containing all zeros (roots of B(z)) • P = column-vector containing all poles (roots of A(z)) • K = overall gain = B(Inf) EXAMPLE: [z, p, k] = sos2zp ([1 0 1, 1 0 -0.81; 1 0 0, 1 0 0.49]) ⇒ z = 0 + 1i 0 - 1i 0 + 0i 0 + 0i ⇒ p = -0.9000 + 0i 0.9000 + 0i 0 + 0.7000i 0 - 0.7000i ⇒ k = 1 See also: zp2sos, sos2tf, tf2sos, zp2tf, tf2zp. 3.6.6 ss2tf ----------- -- Function File: [NUM, DEN] = ss2tf (A, B, C, D) Conversion from state-space to transfer function representation. The state space system: . x = Ax + Bu y = Cx + Du is converted to a transfer function: num(s) G(s)=------- den(s) 3.6.7 ss2zp ----------- -- Function File: [Z, P, K] = ss2zp (A, B, C, D) Converts a state space representation to a set of poles and zeros; K is a gain associated with the zeros. 3.6.8 tf2sos ------------ -- Function File: [SOS, G] = tf2sos (B, A) -- Function File: SOS = tf2sos (B, A) Convert direct-form filter coefficients to series second-order sections. INPUTS: B and A are vectors specifying the digital filter H(z) = B(z)/A(z). See ‘filter’ for documentation of the B and A filter coefficients. RETURNED: • SOS = matrix of series second-order sections, one per row: SOS = [B1.' A1.'; ...; BN.' AN.'] where ‘B1.' = [b0 b1 b2] and A1.' = [1 a1 a2]’ for section 1, etc. The b0 entry must be nonzero for each section (zeros at infinity not supported). • G is an overall gain factor that effectively scales any one of the Bi vectors. If called with only one output argument, the overall filter gain is applied to the first second-order section in the matrix SOS. EXAMPLE: B = [1 0 0 0 0 1]; A = [1 0 0 0 0 .9]; [sos, g] = tf2sos (B, A) sos = 1.00000 0.61803 1.00000 1.00000 0.60515 0.95873 1.00000 -1.61803 1.00000 1.00000 -1.58430 0.95873 1.00000 1.00000 -0.00000 1.00000 0.97915 -0.00000 g = 1 See also: sos2tf, zp2sos, sos2pz, zp2tf, tf2zp. 3.6.9 tf2ss ----------- -- Function File: [A, B, C, D] = tf2ss (NUM, DEN) Conversion from transfer function to state-space. The state space system: . x = Ax + Bu y = Cx + Du is obtained from a transfer function: num(s) G(s)=------- den(s) The state space system matrices obtained from this function will be in observable companion form as Wolovich's Observable Structure Theorem is used. 3.6.10 tf2zp ------------ -- Function File: [Z, P, K] = tf2zp (NUM, DEN) Convert transfer functions to poles-and-zero representations. Returns the zeros and poles of the system defined by NUM/DEN. K is a gain associated with the system zeros. 3.6.11 zp2sos ------------- -- Function File: [SOS, G] = zp2sos (Z) -- Function File: [SOS, G] = zp2sos (Z, P) -- Function File: [SOS, G] = zp2sos (Z, P, K) -- Function File: SOS = zp2sos (...) Convert filter poles and zeros to second-order sections. INPUTS: • Z = column-vector containing the filter zeros • P = column-vector containing the filter poles • K = overall filter gain factor. If not given the gain is assumed to be 1. RETURNED: • SOS = matrix of series second-order sections, one per row: SOS = [B1.' A1.'; ...; BN.' AN.'] where ‘B1.' = [b0 b1 b2] and A1.' = [a0 a1 a2]’ for section 1, etc. See ‘filter’ for documentation of the second-order direct-form filter coefficients Bi and %Ai, i=1:N. • G is the overall gain factor that effectively scales any one of the Bi vectors. If called with only one output argument, the overall filter gain is applied to the first second-order section in the matrix SOS. EXAMPLE: [z, p, k] = tf2zp ([1 0 0 0 0 1], [1 0 0 0 0 .9]); [sos, g] = zp2sos (z, p, k) sos = 1.0000 0.6180 1.0000 1.0000 0.6051 0.9587 1.0000 -1.6180 1.0000 1.0000 -1.5843 0.9587 1.0000 1.0000 0 1.0000 0.9791 0 g = 1 See also: sos2zp, sos2tf, tf2sos, zp2tf, tf2zp. 3.6.12 zp2ss ------------ -- Function File: [A, B, C, D] = zp2ss (Z, P, K) Conversion from zero / pole to state space. *Inputs* Z P Vectors of (possibly) complex poles and zeros of a transfer function. Complex values must come in conjugate pairs (i.e., x+jy in Z means that x-jy is also in Z). K Real scalar (leading coefficient). *Outputs* A B C D The state space system, in the form: . x = Ax + Bu y = Cx + Du 3.6.13 zp2tf ------------ -- Function File: [NUM, DEN] = zp2tf (Z, P, K) Converts zeros / poles to a transfer function. *Inputs* Z P Vectors of (possibly complex) poles and zeros of a transfer function. Complex values must appear in conjugate pairs. K Real scalar (leading coefficient).  File: signal.info, Node: IIR Filter Design, Next: FIR Filter Design, Prev: Filter Conversion, Up: Function Reference 3.7 IIR Filter Design ===================== 3.7.1 besselap -------------- -- Function File: [ZERO, POLE, GAIN] = besselap (N) Return bessel analog filter prototype. References: http://en.wikipedia.org/wiki/Bessel_polynomials 3.7.2 besself ------------- -- Function File: [B, A] = besself (N, W) -- Function File: [B, A] = besself (N, W, "high") -- Function File: [Z, P, G] = besself (...) -- Function File: [A, B, C, D] = besself (...) -- Function File: [...] = besself (..., "z") Generate a Bessel filter. Default is a Laplace space (s) filter. [b,a] = besself(n, Wc) low pass filter with cutoff pi*Wc radians [b,a] = besself(n, Wc, 'high') high pass filter with cutoff pi*Wc radians [z,p,g] = besself(...) return filter as zero-pole-gain rather than coefficients of the numerator and denominator polynomials. [...] = besself(...,'z') return a discrete space (Z) filter, W must be less than 1. [a,b,c,d] = besself(...) return state-space matrices References: Proakis & Manolakis (1992). Digital Signal Processing. New York: Macmillan Publishing Company. 3.7.3 bilinear -------------- -- Function File: [ZB, ZA] = bilinear (SB, SA, T) -- Function File: [ZB, ZA] = bilinear (SZ, SP, SG, T) -- Function File: [ZZ, ZP, ZG] = bilinear (...) Transform a s-plane filter specification into a z-plane specification. Filters can be specified in either zero-pole-gain or transfer function form. The input form does not have to match the output form. 1/T is the sampling frequency represented in the z plane. Note: this differs from the bilinear function in the signal processing toolbox, which uses 1/T rather than T. Theory: Given a piecewise flat filter design, you can transform it from the s-plane to the z-plane while maintaining the band edges by means of the bilinear transform. This maps the left hand side of the s-plane into the interior of the unit circle. The mapping is highly non-linear, so you must design your filter with band edges in the s-plane positioned at 2/T tan(w*T/2) so that they will be positioned at w after the bilinear transform is complete. The following table summarizes the transformation: +---------------+-----------------------+----------------------+ | Transform | Zero at x | Pole at x | | H(S) | H(S) = S-x | H(S)=1/(S-x) | +---------------+-----------------------+----------------------+ | 2 z-1 | zero: (2+xT)/(2-xT) | zero: -1 | | S -> - --- | pole: -1 | pole: (2+xT)/(2-xT) | | T z+1 | gain: (2-xT)/T | gain: (2-xT)/T | +---------------+-----------------------+----------------------+ With tedious algebra, you can derive the above formulae yourself by substituting the transform for S into H(S)=S-x for a zero at x or H(S)=1/(S-x) for a pole at x, and converting the result into the form: H(Z)=g prod(Z-Xi)/prod(Z-Xj) Please note that a pole and a zero at the same place exactly cancel. This is significant since the bilinear transform creates numerous extra poles and zeros, most of which cancel. Those which do not cancel have a "fill-in" effect, extending the shorter of the sets to have the same number of as the longer of the sets of poles and zeros (or at least split the difference in the case of the band pass filter). There may be other opportunistic cancellations but I will not check for them. Also note that any pole on the unit circle or beyond will result in an unstable filter. Because of cancellation, this will only happen if the number of poles is smaller than the number of zeros. The analytic design methods all yield more poles than zeros, so this will not be a problem. References: Proakis & Manolakis (1992). Digital Signal Processing. New York: Macmillan Publishing Company. 3.7.4 buttap ------------ -- Function File: [Z, P, G] = buttap (N) Design lowpass analog Butterworth filter. This function exists for MATLAB compatibility only, and is equivalent to ‘butter (N, 1, "s")’. See also: butter. 3.7.5 butter ------------ -- Function File: [B, A] = butter (N, WC) -- Function File: [B, A] = butter (N, WC, FILTER_TYPE) -- Function File: [Z, P, G] = butter (...) -- Function File: [A, B, C, D] = butter (...) -- Function File: [...] = butter (..., "s") Generate a Butterworth filter. Default is a discrete space (Z) filter. The cutoff frequency, WC should be specified in radians for analog filters. For digital filters, it must be a value between zero and one. For bandpass filters, WC is a two-element vector with ‘w(1) < w(2)’. The filter type must be one of "low", "high", "bandpass", or "stop". The default is "low" if WC is a scalar and "bandpass" if WC is a two-element vector. If the final input argument is "s" design an analog Laplace space filter. Low pass filter with cutoff ‘pi*Wc’ radians: [b, a] = butter (n, Wc) High pass filter with cutoff ‘pi*Wc’ radians: [b, a] = butter (n, Wc, "high") Band pass filter with edges ‘pi*Wl’ and ‘pi*Wh’ radians: [b, a] = butter (n, [Wl, Wh]) Band reject filter with edges ‘pi*Wl’ and ‘pi*Wh’ radians: [b, a] = butter (n, [Wl, Wh], "stop") Return filter as zero-pole-gain rather than coefficients of the numerator and denominator polynomials: [z, p, g] = butter (...) Return a Laplace space filter, WC can be larger than 1: [...] = butter (..., "s") Return state-space matrices: [a, b, c, d] = butter (...) References: Proakis & Manolakis (1992). Digital Signal Processing. New York: Macmillan Publishing Company. 3.7.6 buttord ------------- -- Function File: N = buttord (WP, WS, RP, RS) -- Function File: N = buttord ([WP1, WP2], [WS1, WS2], RP, RS) -- Function File: N = buttord ([WP1, WP2], [WS1, WS2], RP, RS, "s") -- Function File: [N, WC_P] = buttord (...) -- Function File: [N, WC_P, WC_S] = buttord (...) Compute the minimum filter order of a Butterworth filter with the desired response characteristics. The filter frequency band edges are specified by the passband frequency WP and stopband frequency WS. Frequencies are normalized to the Nyquist frequency in the range [0,1]. RP is the allowable passband ripple measured in decibels, and RS is the minimum attenuation in the stop band, also in decibels. The output arguments N and WC_P (or N and WC_N) can be given as inputs to ‘butter’. Using WC_P makes the filter characteristic touch at least one pass band corner and using WC_S makes the characteristic touch at least one stop band corner. If WP and WS are scalars, then WP is the passband cutoff frequency and WS is the stopband edge frequency. If WS is greater than WP, the filter is a low-pass filter. If WP is greater than WS, the filter is a high-pass filter. If WP and WS are vectors of length 2, then WP defines the passband interval and WS defines the stopband interval. If WP is contained within WS (WS1 < WP1 < WP2 < WS2), the filter is a band-pass filter. If WS is contained within WP (WP1 < WS1 < WS2 < WP2), the filter is a band-stop or band-reject filter. If the optional argument ‘"s"’ is given, the minimum order for an analog elliptic filter is computed. All frequencies WP and WS are specified in radians per second. Theory: For Low pass filters, |H(W)|^2 = 1/[1+(W/Wc)^(2N)] = 10^(-R/10). With some algebra, you can solve simultaneously for Wc and N given Ws,Rs and Wp,Rp. Rounding N to the next greater integer, one can recalculate the allowable range for Wc (filter caracteristic touching the pass band edge or the stop band edge). For other types of filter, before making the above calculation, the requirements must be transformed to LP requirements. After calculation, Wc must be transformed back to original filter type. See also: butter, cheb1ord, cheb2ord, ellipord. 3.7.7 cheb ---------- -- Function File: cheb (N, X) Returns the value of the nth-order Chebyshev polynomial calculated at the point x. The Chebyshev polynomials are defined by the equations: / cos(n acos(x), |x| <= 1 Tn(x) = | \ cosh(n acosh(x), |x| > 1 If x is a vector, the output is a vector of the same size, where each element is calculated as y(i) = Tn(x(i)). 3.7.8 cheb1ap ------------- -- Function File: [Z, P, G] = cheb1ap (N, RP) Design lowpass analog Chebyshev type I filter. This function exists for MATLAB compatibility only, and is equivalent to ‘cheby1 (N, RP, 1, "s")’. Input: • N Order of the filter must be a positive integer • RP Ripple in the passband in dB Output: • Z The zero vector • P The pole vectorAngle • G The gain factor Example [z, p, g] = cheb1ap (2, 1) z = [](0x1) p = -0.54887 - 0.89513i -0.54887 + 0.89513i g = 0.98261 See also: buttap, cheby1, cheb2ap, ellipap. 3.7.9 cheb1ord -------------- -- Function File: N = cheb1ord (WP, WS, RP, RS) -- Function File: N = cheb1ord ([WP1, WP2], [WS1, WS2], RP, RS) -- Function File: N = cheb1ord ([WP1, WP2], [WS1, WS2], RP, RS, "s") -- Function File: [N, WC] = cheb1ord (...) -- Function File: [N, WC_P, WC_S] = cheb1ord (...) Compute the minimum filter order of a Chebyshev type I filter with the desired response characteristics. The filter frequency band edges are specified by the passband frequency WP and stopband frequency WS. Frequencies are normalized to the Nyquist frequency in the range [0,1]. RP is the allowable passband ripple measured in decibels, and RS is the minimum attenuation in the stop band, also in decibels. The output arguments N and WC_P (or N and WC_S) can be given as inputs to ‘cheby1’. Using WC_P makes the filter characteristic touch at least one pass band corner and using WC_S makes the characteristic touch at least one stop band corner. If WP and WS are scalars, then WP is the passband cutoff frequency and WS is the stopband edge frequency. If WS is greater than WP, the filter is a low-pass filter. If WP is greater than WS, the filter is a high-pass filter. If WP and WS are vectors of length 2, then WP defines the passband interval and WS defines the stopband interval. If WP is contained within WS (WS1 < WP1 < WP2 < WS2), the filter is a band-pass filter. If WS is contained within WP (WP1 < WS1 < WS2 < WP2), the filter is a band-stop or band-reject filter. If the optional argument ‘"s"’ is given, the minimum order for an analog elliptic filter is computed. All frequencies WP and WS are specified in radians per second. See also: buttord, cheby1, cheb2ord, ellipord. 3.7.10 cheb2ap -------------- -- Function File: [Z, P, G] = cheb2ap (N, RS) Design lowpass analog Chebyshev type II filter. This function exists for MATLAB compatibility only, and is equivalent to ‘cheby2 (N, RS, 1, "s")’. Demo demo cheb2ap See also: cheby2. 3.7.11 cheb2ord --------------- -- Function File: N = cheb2ord (WP, WS, RP, RS) -- Function File: N = cheb2ord ([WP1, WP2], [WS1, WS2], RP, RS) -- Function File: N = cheb2ord ([WP1, WP2], [WS1, WS2], RP, RS, "s") -- Function File: [N, WC_S] = cheb2ord (...) -- Function File: [N, WC_S, WC_P] = cheb2ord (...) Compute the minimum filter order of a Chebyshev type II filter with the desired response characteristics. The filter frequency band edges are specified by the passband frequency WP and stopband frequency WS. Frequencies are normalized to the Nyquist frequency in the range [0,1]. RP is the allowable passband ripple measured in decibels, and RS is the minimum attenuation in the stop band, also in decibels. The output arguments N and WC_P (or N and WC_S) can be given as inputs to ‘cheby2’. Using WC_P makes the filter characteristic touch at least one pass band corner and using WC_S makes the characteristic touch at least one stop band corner. If WP and WS are scalars, then WP is the passband cutoff frequency and WS is the stopband edge frequency. If WS is greater than WP, the filter is a low-pass filter. If WP is greater than WS, the filter is a high-pass filter. If WP and WS are vectors of length 2, then WP defines the passband interval and WS defines the stopband interval. If WP is contained within WS (WS1 < WP1 < WP2 < WS2), the filter is a band-pass filter. If WS is contained within WP (WP1 < WS1 < WS2 < WP2), the filter is a band-stop or band-reject filter. If the optional argument ‘"s"’ is given, the minimum order for an analog elliptic filter is computed. All frequencies WP and WS are specified in radians per second. See also: buttord, cheb1ord, cheby2, ellipord. 3.7.12 cheby1 ------------- -- Function File: [B, A] = cheby1 (N, RP, W) -- Function File: [B, A] = cheby1 (N, RP, W, "high") -- Function File: [B, A] = cheby1 (N, RP, [WL, WH]) -- Function File: [B, A] = cheby1 (N, RP, [WL, WH], "stop") -- Function File: [Z, P, G] = cheby1 (...) -- Function File: [A, B, C, D] = cheby1 (...) -- Function File: [...] = cheby1 (..., "s") Generate a Chebyshev type I filter with RP dB of passband ripple. [b, a] = cheby1(n, Rp, Wc) low pass filter with cutoff pi*Wc radians [b, a] = cheby1(n, Rp, Wc, 'high') high pass filter with cutoff pi*Wc radians [b, a] = cheby1(n, Rp, [Wl, Wh]) band pass filter with edges pi*Wl and pi*Wh radians [b, a] = cheby1(n, Rp, [Wl, Wh], 'stop') band reject filter with edges pi*Wl and pi*Wh radians [z, p, g] = cheby1(...) return filter as zero-pole-gain rather than coefficients of the numerator and denominator polynomials. [...] = cheby1(...,'s') return a Laplace space filter, W can be larger than 1. [a,b,c,d] = cheby1(...) return state-space matrices References: Parks & Burrus (1987). Digital Filter Design. New York: John Wiley & Sons, Inc. 3.7.13 cheby2 ------------- -- Function File: [B, A] = cheby2 (N, RS, WC) -- Function File: [B, A] = cheby2 (N, RS, WC, "high") -- Function File: [B, A] = cheby2 (N, RS, [WL, WH]) -- Function File: [B, A] = cheby2 (N, RS, [WL, WH], "stop") -- Function File: [Z, P, G] = cheby2 (...) -- Function File: [A, B, C, D] = cheby2 (...) -- Function File: [...] = cheby2 (..., "s") Generate a Chebyshev type II filter with RS dB of stopband attenuation. [b, a] = cheby2(n, Rs, Wc) low pass filter with cutoff pi*Wc radians [b, a] = cheby2(n, Rs, Wc, 'high') high pass filter with cutoff pi*Wc radians [b, a] = cheby2(n, Rs, [Wl, Wh]) band pass filter with edges pi*Wl and pi*Wh radians [b, a] = cheby2(n, Rs, [Wl, Wh], 'stop') band reject filter with edges pi*Wl and pi*Wh radians [z, p, g] = cheby2(...) return filter as zero-pole-gain rather than coefficients of the numerator and denominator polynomials. [...] = cheby2(...,'s') return a Laplace space filter, W can be larger than 1. [a,b,c,d] = cheby2(...) return state-space matrices References: Parks & Burrus (1987). Digital Filter Design. New York: John Wiley & Sons, Inc. 3.7.14 ellip ------------ -- Function File: [B, A] = ellip (N, RP, RS, WP) -- Function File: [B, A] = ellip (N, RP, RS, WP, "high") -- Function File: [B, A] = ellip (N, RP, RS, [WL, WH]) -- Function File: [B, A] = ellip (N, RP, RS, [WL, WH], "stop") -- Function File: [Z, P, G] = ellip (...) -- Function File: [A, B, C, D] = ellip (...) -- Function File: [...] = ellip (..., "s") Generate an elliptic or Cauer filter with RP dB of passband ripple and RS dB of stopband attenuation. [b,a] = ellip(n, Rp, Rs, Wp) low pass filter with order n, cutoff pi*Wp radians, Rp decibels of ripple in the passband and a stopband Rs decibels down. [b,a] = ellip(n, Rp, Rs, Wp, 'high') high pass filter with cutoff pi*Wp... [b,a] = ellip(n, Rp, Rs, [Wl, Wh]) band pass filter with band pass edges pi*Wl and pi*Wh ... [b,a] = ellip(n, Rp, Rs, [Wl, Wh], 'stop') band reject filter with edges pi*Wl and pi*Wh, ... [z,p,g] = ellip(...) return filter as zero-pole-gain. [...] = ellip(...,'s') return a Laplace space filter, W can be larger than 1. [a,b,c,d] = ellip(...) return state-space matrices References: - Oppenheim, Alan V., Discrete Time Signal Processing, Hardcover, 1999. - Parente Ribeiro, E., Notas de aula da disciplina TE498 - Processamento Digital de Sinais, UFPR, 2001/2002. 3.7.15 ellipap -------------- -- Function File: [Z, P, G] = ellipap (N, RP, RS) Design lowpass analog elliptic filter. This function exists for MATLAB compatibility only, and is equivalent to ‘ellip (N, RP, RS, 1, "s")’. See also: ellip. 3.7.16 ellipord --------------- -- Function File: N = ellipord (WP, WS, RP, RS) -- Function File: N = ellipord ([WP1, WP2], [WS1, WS2], RP, RS) -- Function File: N = ellipord ([WP1, WP2], [WS1, WS2], RP, RS, "s") -- Function File: [N, WC] = ellipord (...) Compute the minimum filter order of an elliptic filter with the desired response characteristics. The filter frequency band edges are specified by the passband frequency WP and stopband frequency WS. Frequencies are normalized to the Nyquist frequency in the range [0,1]. RP is the allowable passband ripple measured in decibels, and RS is the minimum attenuation in the stop band, also in decibels. The output arguments N and WC can be given as inputs to ‘ellip’. If WP and WS are scalars, then WP is the passband cutoff frequency and WS is the stopband edge frequency. If WS is greater than WP, the filter is a low-pass filter. If WP is greater than WS, the filter is a high-pass filter. If WP and WS are vectors of length 2, then WP defines the passband interval and WS defines the stopband interval. If WP is contained within WS (WS1 < WP1 < WP2 < WS2), the filter is a band-pass filter. If WS is contained within WP (WP1 < WS1 < WS2 < WP2), the filter is a band-stop or band-reject filter. If the optional argument ‘"s"’ is given, the minimum order for an analog elliptic filter is computed. All frequencies WP and WS are specified in radians per second. Reference: Lamar, Marcus Vinicius, ‘Notas de aula da disciplina TE 456 - Circuitos Analogicos II’, UFPR, 2001/2002. See also: buttord, cheb1ord, cheb2ord, ellip. 3.7.17 firpm ------------ -- Loadable Function: B = firpm (N, F, A) -- Loadable Function: B = firpm (N, F, @RESPFN) -- Loadable Function: B = firpm (N, F, {@RESPFN, ...}) -- Loadable Function: B = firpm (..., W) -- Loadable Function: B = firpm (..., CLASS) -- Loadable Function: B = firpm (..., {ACCURACY, ...}) -- Loadable Function: [B, MINIMAX] = firpm (...) -- Loadable Function: [B, MINIMAX, RES] = firpm (...) Designs a linear-phase FIR filter according to given specifications and the 'minimax' criterion. The method (per McClellan et al.(1)) uses successive approximation to minimize the maximum weighted error between the desired and actual frequency response of the filter. Such filters are variably described as being 'minimax', 'equiripple', or 'optimal (in the Chebyshev sense)'. Arguments ========= ... Where shown as the first argument to ‘firpm’, indicates that any previously-indicated list of arguments may substitute for the ellipsis. N A positive integer giving the filter order. F A vector of real-numbers, increasing in the range [0,1], giving the frequencies of the left and right edges of each band for which a specific amplitude response is desired: [l1 r1 l2 r2 ...]. 1 represents the Nyquist-frequency. Transition-bands are defined implicitly as the regions between or outside the given bands. A A vector of real-numbers giving the desired amplitude response. An amplitude value is given either for each band edge: [a(l1) a(r1) a(l2) a(r2) ...], or for each band: [a1 a2 ...]. In the former case, in-band amplitude is determined by linear interpolation between the given band-edge values. 1 represents unity-gain, 0 represents infinite attenuation, and −1 represents a phase change of pi radians. Note that amplitude response is necessarily zero at F=0 for type III and IV filters, and at F=1 for type II and III filters. @RESPFN A handle to a 'response function' that supplies the desired amplitude response and error-weighting. This, unlike A above, allows the response to be arbitrary (subject to the note above). firpm invokes the response function according to the following syntax: AG = respFn (N,F,G,W, ...) [AG WG] = respFn (N,F,G,W, ...) SYMMETRY = respFn ("defaults", {N,F,G,W, ...}) where: • N and F are as given to firpm. • W is as given to firpm, or ones if not given. • AG and WG are the desired amplitude and weighting functions evaluated at each frequency in vector G (which are frequencies within the non-transition bands of F). Returning AG alone gives uniform weighting. • SYMMETRY is either "even" or "odd"; this provides an alternative to using the CLASS values "symmetric" and "antisymmetric". • Per the ellipses shown here and above, when @RESPFN is given contained in a cell-array, any additionally contained values are appended to the RESPFN invocation argument-list. W When used in conjunction with A, W is a vector of positive real-numbers giving error-weightings to be applied at each given band-edge [w(l1) w(r1) w(l2) w(r2) ...], or for each band [w1 w2 ...]. In the former case, in-band weighting is determined by linear interpolation between the given band-edge values. A higher relative error weighting yields a lower relative error. When used in conjunction with @RESPFN, W is a vector (constrained as above) that is passed through to RESPFN. CLASS A string, which may be abbreviated, giving the filter-class: • "symmetric" (the default) for type I or II filters, • "antisymmetric" (or "hilbert") for standard type III or IV filters, • "differentiator" for type III or IV filters with inverted phase and with error-weighting (further to W) of 2/f applied in the pass-band(s). ACCURACY, ... Up to three properties contained within a cell-array: ACCURACY, PERSISTENCE, ROBUSTNESS, that respectively control how close the computed filter will be to the ideal minimax solution, the number of computation iterations over which the required accuracy will be sought, and the precision of certain internal processing. Each can each be set to a small positive number (typically ≤3), to increase the relevant item; this may increase computation time, but the need to do so should be rare. A value of 0 can be used to leave an item unchanged. Alternatively, setting ACCURACY ≥16 emulates MATLAB's LGRID argument. Results ======= If a problem occurs during the computation, a diagnostic message will normally be displayed. If this happens, adjusting ACCURACY, PERSISTENCE, or ROBUSTNESS may provide the solution. Some filters however, may not be realizable due to machine-precision limitations. If a filter can be computed, returned values are as follows: B A length N+1 row-vector containing the computed filter coefficients. MINIMAX The absolute value of the minimized, maximum weighted error, or this number negated if the required accuracy could not be achieved. RES A structure of data relating to the filter computation and a partial response-analysis of the resultant filter; fields are vectors: ‘fgrid’ Analysis frequencies per F. ‘des’ Desired amplitude response. ‘wt’ Error weighting. ‘H’ Complex frequency response. ‘error’ Desired minus actual amplitude response. ‘iextr’ Indices of local peaks in ‘error’. ‘fextr’ Frequencies of local peaks in ‘error’. Using RES is not recommended because it can be slow to compute and, since the analysis excludes transition-bands, any 'anomalies'(2) therein are not easy to discern. In general, ‘freqz’ suffices to check that the response of the computed filter is satisfactory. Examples ======== # Low-pass with frequencies in Hz: Fs = 96000; Fn = Fs/2; # Sampling & Nyquist frequencies. b = firpm (50, [0 20000 28000 48000] / Fn, [1 0]); # Type IV high-pass: b = firpm (31, [0 0.5 0.7 1], [0 1], "antisym"); # Inverse-sinc (arbitrary response): b = firpm (20, [0 0.5 0.9 1], @(n,f,g) ... deal ((g<=f(2))./sinc (g), (g>=f(3))*9+1)); # Band-pass with filter-response check: freqz (firpm (40, [0 3 4 6 8 10]/10, [0 1 0])) Further examples can be found in the ‘firpm’ and ‘firpmord’ demonstration scripts. Compatibility ============= Given invalid filter specifications, Octave emits an error and does not produce a filter; MATLAB in such circumstances may still produce filter coefficients. Unlike with MATLAB, with Octave MINIMAX can be negative; for compatibility, take the absolute value. See also: firpmord. 3.7.18 firpmord --------------- -- Function File: [N, FOUT, A, W] = firpmord (F, A, D) -- Function File: [N, FOUT, A, W] = firpmord (F, A, D, FS) -- Function File: C = firpmord (F, A, D, "cell") -- Function File: C = firpmord (F, A, D, FS, "cell") Estimate the filter-order needed for ‘firpm’ to design a type-I or type-II linear-phase FIR filter according to the given specifications. Arguments ========= F A vector of real-numbers, increasing in the range (0, FS/2), giving the frequencies of the left and right edges of each band for which a specific amplitude response is desired (omitting 0 and FS/2, which are implied): [r1 l2 r2 ...]. Transition-bands are defined implicitly as the regions between the given bands. A A vector of real-numbers giving the ideal amplitude response. An amplitude value is given for each band specified by F: [a1 a2 ...]. 1 represents unity-gain, 0 represents infinite attenuation, and −1 represents a phase change of pi radians. D A vector of positive real-numbers giving the maximum allowable linear deviation from the amplitudes given in A, thus constraining the actual amplitude response (where defined by F) to be within A +/− D. Note that, though related, D does not equate to ‘firpm’'s W argument. FS The sampling-frequency, which defaults to 2. Usage ===== The function returns the estimated filter-order, together with the other design specification values, in one of two forms suitable for use with ‘firpm’. By default, multiple return values are used; alternatively, by giving "cell" (or "c") as the last argument to ‘firpmord’, the returned values are contained within a cell-array that can, if desired, be passed directly to ‘firpm’. The following examples illustrate the use of both mechanisms, as well as aspects of ‘firpmord’ usage in general: # Low-pass; frequencies in kHz: [n f a w] = firpmord ([2.5 3], [1 0], [0.01 db2mag(-60)], 8); b = firpm (n, f, a, w); # Band-pass: c = firpmord ([3 4 8 9], [0 1 0], [1e-3 1e-2 1e-3], 20, "cell"); b = firpm (c{:}); # High-pass: b = firpm (firpmord ([6.4 8]/16, [0 1], [1e-4 0.01], "c"){:}); In cases where elements of D follow a repeating pattern (e.g. all the elements are equal, or elements corresponding to pass-bands are equal and elements corresponding to stop-bands are equal), only as many elements as are needed to establish the pattern need be given. For example, the following ‘firpmord’ invocation pairs are equivalent: # Low-pass: firpmord ([0.4 0.5], [0 1], [db2mag(-72) db2mag(-72)]); firpmord ([0.4 0.5], [0 1], [db2mag(-72)]); # Multi-band-pass: ds = db2mag(-80); dp = 0.01; firpmord ([1 2 3 4 5 6 7 8]/10, [0 1 0 1 0], [ds dp ds dp ds]); firpmord ([1 2 3 4 5 6 7 8]/10, [0 1 0 1 0], [ds dp]); Notes ===== The estimation algorithm used is per Ichige et al.(3) Accuracy tends to decrease as the number of bands increases. Even with two bands (i.e. high-pass or low-pass), the algorithm may under- or over-estimate. See the ‘firpmord’ demonstrations for some examples. In order to precisely determine the minimum order needed for a particular design, ‘firpmord’ could be used to seed an algorithm iterating invocations of ‘firpm’ (as exemplified in demonstration number five). Related documentation ===================== See also: firpm, kaiserord. 3.7.19 impinvar --------------- -- Function File: [B_OUT, A_OUT] = impinvar (B, A, FS, TOL) -- Function File: [B_OUT, A_OUT] = impinvar (B, A, FS) -- Function File: [B_OUT, A_OUT] = impinvar (B, A) Converts analog filter with coefficients B and A to digital, conserving impulse response. If FS is not specified, or is an empty vector, it defaults to 1Hz. If TOL is not specified, it defaults to 0.0001 (0.1%) This function does the inverse of impinvar so that the following example should restore the original values of A and B. ‘invimpinvar’ implements the reverse of this function. [b, a] = impinvar (b, a); [b, a] = invimpinvar (b, a); Reference: Thomas J. Cavicchi (1996) "Impulse invariance and multiple-order poles". IEEE transactions on signal processing, Vol 44 (9): 2344-2347 See also: bilinear, invimpinvar. 3.7.20 invimpinvar ------------------ -- Function File: [B_OUT, A_OUT] = invimpinvar (B, A, FS, TOL) -- Function File: [B_OUT, A_OUT] = invimpinvar (B, A, FS) -- Function File: [B_OUT, A_OUT] = invimpinvar (B, A) Converts digital filter with coefficients B and A to analog, conserving impulse response. This function does the inverse of impinvar so that the following example should restore the original values of A and B. [b, a] = impinvar (b, a); [b, a] = invimpinvar (b, a); If FS is not specified, or is an empty vector, it defaults to 1Hz. If TOL is not specified, it defaults to 0.0001 (0.1%) Reference: Thomas J. Cavicchi (1996) "Impulse invariance and multiple-order poles". IEEE transactions on signal processing, Vol 40 (9): 2344-2347 See also: bilinear, impinvar. 3.7.21 ncauer ------------- -- Function File: [Z, P, G] = cauer(RP, RS, N) Analog prototype for Cauer filter. Rp Passband ripple Rs Stopband ripple n Desired order z complex vector of zeros for the model. p complex vector of poles for the model. g gain value. References: - Serra, Celso Penteado, Teoria e Projeto de Filtros, Campinas: CARTGRAF, 1983. - Lamar, Marcus Vinicius, Notas de aula da disciplina TE 456 - Circuitos Analogicos II, UFPR, 2001/2002. 3.7.22 pei_tseng_notch ---------------------- -- Function File: [B, A] = pei_tseng_notch (FREQUENCIES, BANDWIDTHS) Return coefficients for an IIR notch-filter with one or more filter frequencies and according (very narrow) bandwidths to be used with ‘filter’ or ‘filtfilt’. The filter construction is based on an allpass which performs a reversal of phase at the filter frequencies. Thus, the mean of the phase-distorted and the original signal has the respective frequencies removed. See the demo for an illustration. Original source: Pei, Soo-Chang, and Chien-Cheng Tseng "IIR Multiple Notch Filter Design Based on Allpass Filter" 1996 IEEE Tencon doi: 10.1109/TENCON.1996.608814) 3.7.23 sftrans -------------- -- Function File: [SZ, SP, SG] = sftrans (SZ, SP, SG, W, STOP) Transform band edges of a generic lowpass filter (cutoff at W=1) represented in splane zero-pole-gain form. W is the edge of the target filter (or edges if band pass or band stop). Stop is true for high pass and band stop filters or false for low pass and band pass filters. Filter edges are specified in radians, from 0 to pi (the nyquist frequency). Theory: Given a low pass filter represented by poles and zeros in the splane, you can convert it to a low pass, high pass, band pass or band stop by transforming each of the poles and zeros individually. The following table summarizes the transformation: Transform Zero at x Pole at x ---------------- ------------------------- ------------------------ Low Pass zero: Fc x/C pole: Fc x/C S -> C S/Fc gain: C/Fc gain: Fc/C ---------------- ------------------------- ------------------------ High Pass zero: Fc C/x pole: Fc C/x S -> C Fc/S pole: 0 zero: 0 gain: -x gain: -1/x ---------------- ------------------------- ------------------------ Band Pass zero: b +- sqrt(b^2-FhFl) pole: b +- sqrt(b^2-FhFl) S^2+FhFl pole: 0 zero: 0 S -> C -------- gain: C/(Fh-Fl) gain: (Fh-Fl)/C S(Fh-Fl) b=x/C (Fh-Fl)/2 b=x/C (Fh-Fl)/2 ---------------- ------------------------- ------------------------ Band Stop zero: b +- sqrt(b^2-FhFl) pole: b +- sqrt(b^2-FhFl) S(Fh-Fl) pole: +-sqrt(-FhFl) zero: +-sqrt(-FhFl) S -> C -------- gain: -x gain: -1/x S^2+FhFl b=C/x (Fh-Fl)/2 b=C/x (Fh-Fl)/2 ---------------- ------------------------- ------------------------ Bilinear zero: (2+xT)/(2-xT) pole: (2+xT)/(2-xT) 2 z-1 pole: -1 zero: -1 S -> - --- gain: (2-xT)/T gain: (2-xT)/T T z+1 ---------------- ------------------------- ------------------------ where C is the cutoff frequency of the initial lowpass filter, Fc is the edge of the target low/high pass filter and [Fl,Fh] are the edges of the target band pass/stop filter. With abundant tedious algebra, you can derive the above formulae yourself by substituting the transform for S into H(S)=S-x for a zero at x or H(S)=1/(S-x) for a pole at x, and converting the result into the form: H(S)=g prod(S-Xi)/prod(S-Xj) The transforms are from the references. The actual pole-zero-gain changes I derived myself. Please note that a pole and a zero at the same place exactly cancel. This is significant for High Pass, Band Pass and Band Stop filters which create numerous extra poles and zeros, most of which cancel. Those which do not cancel have a "fill-in" effect, extending the shorter of the sets to have the same number of as the longer of the sets of poles and zeros (or at least split the difference in the case of the band pass filter). There may be other opportunistic cancellations but I will not check for them. Also note that any pole on the unit circle or beyond will result in an unstable filter. Because of cancellation, this will only happen if the number of poles is smaller than the number of zeros and the filter is high pass or band pass. The analytic design methods all yield more poles than zeros, so this will not be a problem. References: Proakis & Manolakis (1992). Digital Signal Processing. New York: Macmillan Publishing Company. ---------- Footnotes ---------- (1) J. H. McClellan, T. W. Parks and L. R. Rabiner, 'A Computer Program for Designing Optimum FIR Linear Phase Digital Filters', IEEE Trans. Audio Electroacoust., vol. AU-21, 1973, pp. 506-525. (2) Tapio Saramäki, 'Finite impulse response filter design', Chapter 4 in 'Handbook for Digital Signal Processing', edited by S. K. Mitra and J. F. Kaiser, John Wiley and Sons, New York, 1993, pp. 155-277. (<https://homepages.tuni.fi/tapio.saramaki/Mitra_Kaiser.pdf>) (3) K. Ichige, M. Iwaki, algorithm and R. Ishii, 'Accurate Estimation of Minimum Filter Length for Optimum FIR Digital Filters', IEEE Transactions on Circuits and Systems, Vol. 47, No. 10, 2000, pp. 1008-1017  File: signal.info, Node: FIR Filter Design, Next: Transforms, Prev: IIR Filter Design, Up: Function Reference 3.8 FIR Filter Design ===================== 3.8.1 cl2bp ----------- -- Loadable Function: H = cl2bp (M, W1, W2, UP, LO) -- Loadable Function: H = cl2bp (M, W1, W2, UP, LO, GRIDSIZE) Constrained L2 bandpass FIR filter design. This is a fast implementation of the algorithm cited below. Compared to “remezâ€, it offers implicit specification of transition bands, a higher likelihood of convergence, and an error criterion combining features of both L2 and Chebyshev approaches. Inputs: M degree of cosine polynomial, i.e. the number of output coefficients will be M*2+1 W1 W2 bandpass filter cutoffs in the range 0 <= W1 < W2 <= pi, where pi is the Nyquist frequency UP vector of 3 upper bounds for [stopband1, passband, stopband2] LO vector of 3 lower bounds for [stopband1, passband, stopband2] GRIDSIZE search grid size; larger values may improve accuracy, but greatly increase calculation time. Default value is 2048, max value is 1e6. Output: A vector of M*2+1 FIR coefficients, or an empty value if the solver failed to converge. Example: h = cl2bp(30, 0.3*pi, 0.6*pi, [0.02, 1.02, 0.02], [-0.02, 0.98, -0.02], 2^11); Original Paper: I. W. Selesnick, M. Lang, and C. S. Burrus. A modified algorithm for constrained least square design of multiband FIR filters without specified transition bands. IEEE Trans. on Signal Processing, 46(2):497-501, February 1998. See also: remez. 3.8.2 fir1 ---------- -- Function File: B = fir1 (N, W) -- Function File: B = fir1 (N, W, TYPE) -- Function File: B = fir1 (N, W, TYPE, WINDOW) -- Function File: B = fir1 (N, W, TYPE, WINDOW, NOSCALE) Produce an order N FIR filter with the given frequency cutoff W, returning the N+1 filter coefficients in B. If W is a scalar, it specifies the frequency cutoff for a lowpass or highpass filter. If W is a two-element vector, the two values specify the edges of a bandpass or bandstop filter. If W is an N-element vector, each value specifies a band edge of a multiband pass/stop filter. The filter TYPE can be specified with one of the following strings: "low", "high", "stop", "pass", "bandpass", "DC-0", or "DC-1". The default is "low" is W is a scalar, "pass" if W is a pair, or "DC-0" if W is a vector with more than 2 elements. An optional shaping WINDOW can be given as a vector with length N+1. If not specified, a Hamming window of length N+1 is used. With the option "noscale", the filter coefficients are not normalized. The default is to normalize the filter such that the magnitude response of the center of the first passband is 1. To apply the filter, use the return vector B with the ‘filter’ function, for example ‘y = filter (b, 1, x)’. Examples: freqz (fir1 (40, 0.3)); freqz (fir1 (15, [0.2, 0.5], "stop")); # note the zero-crossing at 0.1 freqz (fir1 (15, [0.2, 0.5], "stop", "noscale")); See also: filter, fir2. 3.8.3 fir2 ---------- -- Function File: B = fir2 (N, F, M) -- Function File: B = fir2 (N, F, M, GRID_N) -- Function File: B = fir2 (N, F, M, GRID_N, RAMP_N) -- Function File: B = fir2 (N, F, M, GRID_N, RAMP_N, WINDOW) Produce an order N FIR filter with arbitrary frequency response M over frequency bands F, returning the N+1 filter coefficients in B. The vector F specifies the frequency band edges of the filter response and M specifies the magnitude response at each frequency. The vector F must be nondecreasing over the range [0,1], and the first and last elements must be 0 and 1, respectively. A discontinuous jump in the frequency response can be specified by duplicating a band edge in F with different values in M. The resolution over which the frequency response is evaluated can be controlled with the GRID_N argument. The default is 512 or the next larger power of 2 greater than the filter length. The band transition width for discontinuities can be controlled with the RAMP_N argument. The default is GRID_N/25. Larger values will result in wider band transitions but better stopband rejection. An optional shaping WINDOW can be given as a vector with length N+1. If not specified, a Hamming window of length N+1 is used. To apply the filter, use the return vector B with the ‘filter’ function, for example ‘y = filter (b, 1, x)’. Example: f = [0, 0.3, 0.3, 0.6, 0.6, 1]; m = [0, 0, 1, 1/2, 0, 0]; [h, w] = freqz (fir2 (100, f, m)); plot (f, m, ";target response;", w/pi, abs (h), ";filter response;"); See also: filter, fir1. 3.8.4 firls ----------- -- Function File: B = firls (N, F, A) -- Function File: B = firls (N, F, A, W) FIR filter design using least squares method. Returns a length N+1 linear phase filter such that the integral of the weighted mean squared error in the specified bands is minimized. The vector F specifies the frequencies of the band edges, normalized so that half the sample frequency is equal to 1. Each band is specified by two frequencies, to the vector must have an even length. The vector A specifies the amplitude of the desired response at each band edge. The optional argument W is a weighting function that contains one value for each band that weights the mean squared error in that band. A must be the same length as F, and W must be half the length of F. N must be even. If given an odd value, ‘firls’ increments it by 1. The least squares optimization algorithm for computing FIR filter coefficients is derived in detail in: I. Selesnick, "Linear-Phase FIR Filter Design by Least Squares," http://cnx.org/content/m10577 3.8.5 kaiserord --------------- -- Function File: [N, WN, BETA, FTYPE] = kaiserord (F, M, DEV) -- Function File: [...] = kaiserord (F, M, DEV, FS) Return the parameters needed to produce a filter of the desired specification from a Kaiser window. The vector F contains pairs of frequency band edges in the range [0,1]. The vector M specifies the magnitude response for each band. The values of M must be zero for all stop bands and must have the same magnitude for all pass bands. The deviation of the filter DEV can be specified as a scalar or a vector of the same length as M. The optional sampling rate FS can be used to indicate that F is in Hz in the range [0,FS/2]. The returned value N is the required order of the filter (the length of the filter minus 1). The vector WN contains the band edges of the filter suitable for passing to ‘fir1’. The value BETA is the parameter of the Kaiser window of length N+1 to shape the filter. The string FTYPE contains the type of filter to specify to ‘fir1’. The Kaiser window parameters n and beta are computed from the relation between ripple (A=-20*log10(dev)) and transition width (dw in radians) discovered empirically by Kaiser: / 0.1102(A-8.7) A > 50 beta = | 0.5842(A-21)^0.4 + 0.07886(A-21) 21 <= A <= 50 \ 0.0 A < 21 n = (A-8)/(2.285 dw) Example: [n, w, beta, ftype] = kaiserord ([1000, 1200], [1, 0], [0.05, 0.05], 11025); b = fir1 (n, w, kaiser (n+1, beta), ftype, "noscale"); freqz (b, 1, [], 11025); See also: fir1, kaiser. 3.8.6 qp_kaiser --------------- -- Function File: qp_kaiser (NB, AT) -- Function File: qp_kaiser (NB, AT, LINEAR) Computes a finite impulse response (FIR) filter for use with a quasi-perfect reconstruction polyphase-network filter bank. This version utilizes a Kaiser window to shape the frequency response of the designed filter. Tha number nb of bands and the desired attenuation at in the stop-band are given as parameters. The Kaiser window is multiplied by the ideal impulse response h(n)=a.sinc(a.n) and converted to its minimum-phase version by means of a Hilbert transform. By using a third non-null argument, the minimum-phase calculation is omitted at all. 3.8.7 remez ----------- -- Loadable Function: B = remez (N, F, A) -- Loadable Function: B = remez (N, F, A, W) -- Loadable Function: B = remez (N, F, A, W, FTYPE) -- Loadable Function: B = remez (N, F, A, W, FTYPE, GRIDDENSITY) Parks-McClellan optimal FIR filter design. N gives the filter order, where the generated filter length taps is n+1 F gives frequency at the band edges [b1 e1 b2 e2 b3 e3 ...] A gives amplitude at the band edges [a(b1) a(e1) a(b2) a(e2) ...] W gives weighting applied to each band FTYPE is "bandpass", "hilbert" or "differentiator" GRIDDENSITY determines how accurately the filter will be constructed. The minimum value is 16, but higher numbers are slower to compute. Frequency is in the range (0, 1), with 1 being the Nyquist frequency. 3.8.8 sgolay ------------ -- Function File: F = sgolay (P, N) -- Function File: F = sgolay (P, N, M) -- Function File: F = sgolay (P, N, M, TS) Computes the filter coefficients for all Savitzsky-Golay smoothing filters of order p for length n (odd). m can be used in order to get directly the mth derivative. In this case, ts is a scaling factor. The early rows of F smooth based on future values and later rows smooth based on past values, with the middle row using half future and half past. In particular, you can use row i to estimate x(k) based on the i-1 preceding values and the n-i following values of x values as y(k) = F(i,:) * x(k-i+1:k+n-i). Normally, you would apply the first (n-1)/2 rows to the first k points of the vector, the last k rows to the last k points of the vector and middle row to the remainder, but for example if you were running on a realtime system where you wanted to smooth based on the all the data collected up to the current time, with a lag of five samples, you could apply just the filter on row n-5 to your window of length n each time you added a new sample. Reference: Numerical recipes in C. p 650 See also: sgolayfilt.  File: signal.info, Node: Transforms, Next: Power Spectrum Analysis, Prev: FIR Filter Design, Up: Function Reference 3.9 Transforms ============== 3.9.1 bitrevorder ----------------- -- Function File: Y = bitrevorder (X) -- Function File: [Y I] = bitrevorder (X) Reorder the elements of the vector X in bit-reversed order. Equivalent to calling ‘digitrevorder (X, 2)’. See also: digitrevorder, fft, ifft. 3.9.2 cceps ----------- -- Function File: cceps (X) -- Function File: cceps (X, CORRECT) Return the complex cepstrum of the vector X. If the optional argument CORRECT has the value 1, a correction method is applied. The default is not to do this. 3.9.3 cplxreal -------------- -- Function File: [ZC, ZR] = cplxreal (Z) -- Function File: [ZC, ZR] = cplxreal (Z, TOL) -- Function File: [ZC, ZR] = cplxreal (Z, TOL, DIM) Sort the numbers Z into complex-conjugate-valued and real-valued elements. The positive imaginary complex numbers of each complex conjugate pair are returned in ZC and the real numbers are returned in ZR. TOL is a weighting factor in the range [0, 1) which determines the tolerance of the matching. The default value is ‘100 * eps’ and the resulting tolerance for a given complex pair is ‘TOL * abs (Z(i)))’. By default the complex pairs are sorted along the first non-singleton dimension of Z. If DIM is specified, then the complex pairs are sorted along this dimension. Signal an error if some complex numbers could not be paired. Signal an error if all complex numbers are not exact conjugates (to within TOL). Note that there is no defined order for pairs with identical real parts but differing imaginary parts. See also: cplxpair. 3.9.4 czt --------- -- Function File: czt (X) -- Function File: czt (X, M) -- Function File: czt (X, M, W) -- Function File: czt (X, M, W, A) Chirp z-transform. Compute the frequency response starting at a and stepping by w for m steps. a is a point in the complex plane, and w is the ratio between points in each step (i.e., radius increases exponentially, and angle increases linearly). To evaluate the frequency response for the range f1 to f2 in a signal with sampling frequency Fs, use the following: m = 32; ## number of points desired w = exp(-j*2*pi*(f2-f1)/((m-1)*Fs)); ## freq. step of f2-f1/m a = exp(j*2*pi*f1/Fs); ## starting at frequency f1 y = czt(x, m, w, a); If you don't specify them, then the parameters default to a Fourier transform: m=length(x), w=exp(-j*2*pi/m), a=1 If x is a matrix, the transform will be performed column-by-column. 3.9.5 dct --------- -- Function File: dct (X) -- Function File: dct (X, N) Compute the discrete cosine transform of X. If N is given, then X is padded or trimmed to length N before computing the transform. If X is a matrix, compute the transform along the columns of the the matrix. The transform is faster if X is real-valued and has even length. The discrete cosine transform X can be defined as follows: N-1 X[k] = w(k) sum x[n] cos (pi (2n+1) k / 2N ), k = 0, ..., N-1 n=0 with w(0) = sqrt(1/N) and w(k) = sqrt(2/N), k = 1, ..., N-1. There are other definitions with different scaling of X[k], but this form is common in image processing. See also: idct, dct2, idct2, dctmtx. 3.9.6 dct2 ---------- -- Function File: dct2 (X) -- Function File: dct2 (X, M, N) -- Function File: dct2 (X, [M, N]) Compute the 2-D discrete cosine transform of matrix X. If M and N are specified, the input is padded or trimmed to the desired size. See also: dct, idct, idct2. 3.9.7 dctmtx ------------ -- Function File: dctmtx (N) Return the DCT transformation matrix of size N-by-N. If A is an N-by-N matrix, then the following are true: T*A == dct(A), T'*A == idct(A) T*A*T' == dct2(A), T'*A*T == idct2(A) A DCT transformation matrix is useful for doing things like jpeg image compression, in which an 8x8 DCT matrix is applied to non-overlapping blocks throughout an image and only a subblock on the top left of each block is kept. During restoration, the remainder of the block is filled with zeros and the inverse transform is applied to the block. See also: dct, idct, dct2, idct2. 3.9.8 dftmtx ------------ -- Function File: D = dftmtx (N) Compute the N-by-N Fourier transformation matrix. This is the matrix D such that the Fourier transform of a column vector of length N is given by ‘dftmtx(N) * X’ and the inverse Fourier transform is given by ‘inv(dftmtx(N)) * X’. In general this is less efficient than calling the ‘fft’ and ‘ifft’ functions directly. See also: fft, ifft. 3.9.9 digitrevorder ------------------- -- Function File: Y = digitrevorder (X, R) -- Function File: [Y, I] = digitrevorder (X, R) Reorder the elements of the vector X in digit-reversed order. The elements of X are converted to radix R and reversed. The reordered indices of the elements of X are returned in I. See also: bitrevorder, fft, ifft. 3.9.10 dst ---------- -- Function File: Y = dst (X) -- Function File: Y = dst (X, N) Computes the type I discrete sine transform of X. If N is given, then X is padded or trimmed to length N before computing the transform. If X is a matrix, compute the transform along the columns of the the matrix. The discrete sine transform X of x can be defined as follows: N X[k] = sum x[n] sin (pi n k / (N+1) ), k = 1, ..., N n=1 See also: idst. 3.9.11 dwt ---------- -- Function File: [U, V] = dwt (X, WNAME) -- Function File: [U, V] = dwt (X, HP, GP) -- Function File: [U, V] = dwt (X, HP, GP, ...) Discrete wavelet transform (1D). *Inputs* X Signal vector. WNAME Wavelet name. HP Coefficients of low-pass decomposition FIR filter. GP Coefficients of high-pass decomposition FIR filter. *Outputs* U Signal vector of average, approximation. V Signal vector of difference, detail. 3.9.12 fht ---------- -- Function File: M = fht (D) -- Function File: M = fht (D, N) -- Function File: M = fht (D, N, DIM) Calculate the Fast Hartley Transform of real input D. If D is a matrix, the Hartley transform is calculated along the columns by default. The options N and DIM are similar to the options of FFT function. The forward and inverse Hartley transforms are the same (except for a scale factor of 1/N for the inverse Hartley transform), but implemented using different functions. The definition of the forward hartley transform for vector d, m[K] = \sum_{i=0}^{N-1} d[i]*(cos[K*2*pi*i/N] + sin[K*2*pi*i/N]), for 0 <= K < N. m[K] = \sum_{i=0}^{N-1} d[i]*CAS[K*i], for 0 <= K < N. fht(1:4) See also: ifht, fft. 3.9.13 fwht ----------- -- Function File: fwht (X) -- Function File: fwht (X, N) -- Function File: fwht (X, N, ORDER) Compute the Walsh-Hadamard transform of X using the Fast Walsh-Hadamard Transform (FWHT) algorithm. If the input is a matrix, the FWHT is calculated along the columns of X. The number of elements of X must be a power of 2; if not, the input will be extended and filled with zeros. If a second argument is given, the input is truncated or extended to have length N. The third argument specifies the ORDER in which the returned Walsh-Hadamard transform coefficients should be arranged. The ORDER may be any of the following strings: "sequency" The coefficients are returned in sequency order. This is the default if ORDER is not given. "hadamard" The coefficients are returned in Hadamard order. "dyadic" The coefficients are returned in Gray code order. See also: ifwht. 3.9.14 hilbert -------------- -- Function File: H = hilbert (F, N, DIM) Analytic extension of real valued signal. ‘H = hilbert (F)’ computes the extension of the real valued signal F to an analytic signal. If F is a matrix, the transformation is applied to each column. For N-D arrays, the transformation is applied to the first non-singleton dimension. ‘real (H)’ contains the original signal F. ‘imag (H)’ contains the Hilbert transform of F. ‘hilbert (F, N)’ does the same using a length N Hilbert transform. The result will also have length N. ‘hilbert (F, [], DIM)’ or ‘hilbert (F, N, DIM)’ does the same along dimension DIM. 3.9.15 idct ----------- -- Function File: Y = idct (X) -- Function File: Y = idct (X, N) Compute the inverse discrete cosine transform of X. If N is given, then X is padded or trimmed to length N before computing the transform. If X is a matrix, compute the transform along the columns of the the matrix. The transform is faster if X is real-valued and even length. The inverse discrete cosine transform X can be defined as follows: N-1 x[n] = sum w(k) X[k] cos (pi (2n+1) k / 2N ), n = 0, ..., N-1 k=0 with w(0) = sqrt(1/N) and w(k) = sqrt(2/N), k = 1, ..., N-1 See also: dct, dct2, idct2, dctmtx. 3.9.16 idct2 ------------ -- Function File: Y = idct2 (X) -- Function File: Y = idct2 (X, M, N) -- Function File: Y = idct2 (X, [M, N]) Compute the inverse 2-D discrete cosine transform of matrix X. If M and N are specified, the input is either padded or truncated to have M rows and N columns. 3.9.17 idst ----------- -- Function File: Y = idst (X) -- Function File: Y = idst (X, N) Computes the inverse type I discrete sine transform of Y. If N is given, then Y is padded or trimmed to length N before computing the transform. If Y is a matrix, compute the transform along the columns of the the matrix. See also: dst. 3.9.18 ifht ----------- -- Function File: M = ifht (D, N, DIM) Calculate the inverse Fast Hartley Transform of real input D. If D is a matrix, the inverse Hartley transform is calculated along the columns by default. The options N and DIM are similar to the options of FFT function. The forward and inverse Hartley transforms are the same (except for a scale factor of 1/N for the inverse hartley transform), but implemented using different functions. The definition of the forward hartley transform for vector d, m[K] = 1/N \sum_{i=0}^{N-1} d[i]*(cos[K*2*pi*i/N] + sin[K*2*pi*i/N]), for 0 <= K < N. m[K] = 1/N \sum_{i=0}^{N-1} d[i]*CAS[K*i], for 0 <= K < N. ifht(1:4) See also: fht, fft. 3.9.19 ifwht ------------ -- Function File: ifwht (X) -- Function File: ifwht (X, N) -- Function File: ifwht (X, N, ORDER) Compute the inverse Walsh-Hadamard transform of X using the Fast Walsh-Hadamard Transform (FWHT) algorithm. If the input is a matrix, the inverse FWHT is calculated along the columns of X. The number of elements of X must be a power of 2; if not, the input will be extended and filled with zeros. If a second argument is given, the input is truncated or extended to have length N. The third argument specifies the ORDER in which the returned inverse Walsh-Hadamard transform coefficients should be arranged. The ORDER may be any of the following strings: "sequency" The coefficients are returned in sequency order. This is the default if ORDER is not given. "hadamard" The coefficients are returned in Hadamard order. "dyadic" The coefficients are returned in Gray code order. See also: fwht. 3.9.20 rceps ------------ -- Function File: [Y, YM] = rceps (X) Return the cepstrum of the signal X. If X is a matrix, return the cepstrum of each column. If called with two output arguments, the minimum phase reconstruction of the signal X is returned in YM. For example: f0 = 70; Fs = 10000; # 100 Hz fundamental, 10kHz sampling rate a = poly (0.985 * exp (1i * pi * [0.1, -0.1, 0.3, -0.3])); # two formants s = 0.005 * randn (1024, 1); # Noise excitation signal s(1:Fs/f0:length(s)) = 1; # Impulse glottal wave x = filter (1, a, s); # Speech signal [y, ym] = rceps (x .* hanning (1024)); Reference: ‘Programs for Digital Signal Processing’, IEEE Press, John Wiley & Sons, New York, 1979.  File: signal.info, Node: Power Spectrum Analysis, Next: Window Functions, Prev: Transforms, Up: Function Reference 3.10 Power Spectrum Analysis ============================ 3.10.1 __power -------------- -- Function File: [P, W] = __power (B, A) -- Function File: [...] = __power (B, A, NFFT) -- Function File: [...] = __power (B, A, NFFT, FS) -- Function File: [...] = __power (B, A, NFFT, FS, RANGE) -- Function File: [...] = __power (B, A, NFFT, FS, RANGE, UNITS) -- Function File: __power (...) Plot the power spectrum of the given ARMA model. b, a: filter coefficients (b=numerator, a=denominator) nfft is number of points at which to sample the power spectrum Fs is the sampling frequency of x range is 'half' (default) or 'whole' units is 'squared' or 'db' (default) range and units may be specified any time after the filter, in either order Returns P, the magnitude vector, and w, the frequencies at which it is sampled. If there are no return values requested, then plot the power spectrum and don't return anything. 3.10.2 ar_psd ------------- -- Function File: ar_psd (A, V) -- Function File: ar_psd (A, V, FREQ) -- Function File: ar_psd (A, V, FREQ, FS) -- Function File: ar_psd (..., RANGE) -- Function File: ar_psd (..., METHOD) -- Function File: ar_psd (..., PLOTTYPE) -- Function File: [PSD, F_OUT] = ar_psd (...) Calculate the power spectrum of the autoregressive model M x(n) = sqrt(v).e(n) + SUM a(k).x(n-k) k=1 where x(n) is the output of the model and e(n) is white noise. This function is intended for use with ‘[a, v, k] = arburg (x, poles, criterion)’ which use the Burg (1968) method to calculate a "maximum entropy" autoregressive model of X. If the FREQ argument is a vector (of frequencies) the spectrum is calculated using the polynomial method and the METHOD argument is ignored. For scalar FREQ, an integer power of 2, or METHOD = "FFT", causes the spectrum to be calculated by FFT. Otherwise, the spectrum is calculated as a polynomial. It may be computationally more efficient to use the FFT method if length of the model is not much smaller than the number of frequency values. The spectrum is scaled so that spectral energy (area under spectrum) is the same as the time-domain energy (mean square of the signal). ARGUMENTS: All but the first two arguments are optional and may be empty. • A list of M=(order+1) autoregressive model coefficients. The first element of "ar_coeffs" is the zero-lag coefficient, which always has a value of 1. • V square of the moving-average coefficient of the AR model. • FREQ frequencies at which power spectral density is calculated, or a scalar indicating the number of uniformly distributed frequency values at which spectral density is calculated. (default = 256) • FS sampling frequency (Hertz) (default=1) CONTROL-STRING ARGUMENTS - each of these arguments is a character string. Control-string arguments can be in any order after the other arguments. Range: 'half', 'onesided' : frequency range of the spectrum is from zero up to but not including sample_f/2. Power from negative frequencies is added to the positive side of the spectrum. 'whole', 'twosided' : frequency range of the spectrum is -sample_f/2 to sample_f/2, with negative frequencies stored in "wrap around" order after the positive frequencies; e.g. frequencies for a 10-point 'twosided' spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 'shift', 'centerdc' : same as 'whole' but with the first half of the spectrum swapped with second half to put the zero-frequency value in the middle. (See "help fftshift". If "freq" is vector, 'shift' is ignored. If model coefficients "ar_coeffs" are real, the default range is 'half', otherwise default range is 'whole'. Method: 'fft': use FFT to calculate power spectrum. 'poly': calculate power spectrum as a polynomial of 1/z N.B. this argument is ignored if the "freq" argument is a vector. The default is 'poly' unless the "freq" argument is an integer power of 2. Plot type: 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': specifies the type of plot. The default is 'plot', which means linear-linear axes. 'squared' is the same as 'plot'. 'dB' plots "10*log10(psd)". This argument is ignored and a spectrum is not plotted if the caller requires a returned value. RETURNED VALUES: If returned values are not required by the caller, the spectrum is plotted and nothing is returned. • PSD estimate of power-spectral density • F_OUT frequency values REFERENCE [1] Equation 2.28 from Steven M. Kay and Stanley Lawrence Marple Jr.: "Spectrum analysis - a modern perspective", Proceedings of the IEEE, Vol 69, pp 1380-1419, Nov., 1981 3.10.3 cohere ------------- -- Function File: [PXX, FREQ] = cohere(X,Y,NFFT,FS,WINDOW,OVERLAP,RANGE,PLOT_TYPE,DETREND) Estimate (mean square) coherence of signals "x" and "y". Use the Welch (1967) periodogram/FFT method. Compatible with Matlab R11 cohere and earlier. See "help pwelch" for description of arguments, hints and references -- especially hint (7) for Matlab R11 defaults. 3.10.4 cpsd ----------- -- Function File: [PXX, FREQ] = cpsd (X, Y) -- Function File: [...] = cpsd (X, Y, WINDOW) -- Function File: [...] = cpsd (X, Y, WINDOW, OVERLAP) -- Function File: [...] = cpsd (X, Y, WINDOW, OVERLAP, NFFT) -- Function File: [...] = cpsd (X, Y, WINDOW, OVERLAP, NFFT, FS) -- Function File: [...] = cpsd (X, Y, WINDOW, OVERLAP, NFFT, FS, RANGE) -- Function File: cpsd (...) Estimate cross power spectrum of data X and Y by the Welch (1967) periodogram/FFT method. See also: pwelch. 3.10.5 csd ---------- -- Function File: [PXX,FREQ] = csd(X, Y, NFFT, FS, WINDOW, OVERLAP, RANGE, PLOT_TYPE, DETREND) Estimate cross power spectrum of data "x" and "y" by the Welch (1967) periodogram/FFT method. Compatible with Matlab R11 csd and earlier. See "help pwelch" for description of arguments, hints and references -- especially hint (7) for Matlab R11 defaults. 3.10.6 db2pow ------------- -- Function File: db2pow (X) Convert decibels (dB) to power. The power of X is defined as P = ‘10 ^ (x/10)’. If X is a vector, matrix, or N-dimensional array, the power is computed over the elements of X. Example: db2pow ([-10, 0, 10]) ⇒ 0.1000 1.0000 10.0000 See also: pow2db. 3.10.7 mscohere --------------- -- Function File: [PXX, FREQ] = mscohere (X, Y) -- Function File: [...] = mscohere (X, Y, WINDOW) -- Function File: [...] = mscohere (X, Y, WINDOW, OVERLAP) -- Function File: [...] = mscohere (X, Y, WINDOW, OVERLAP, NFFT) -- Function File: [...] = mscohere (X, Y, WINDOW, OVERLAP, NFFT, FS) -- Function File: [...] = mscohere (X, Y, WINDOW, OVERLAP, NFFT, FS, RANGE) -- Function File: mscohere (...) Estimate (mean square) coherence of signals X and Y. Use the Welch (1967) periodogram/FFT method. See also: pwelch. 3.10.8 pburg ------------ -- Function File: [PSD,F_OUT] = pburg(X, POLES, FREQ, FS, RANGE, METHOD, PLOT_TYPE, CRITERION) Calculate Burg maximum-entropy power spectral density. The functions "arburg" and "ar_psd" do all the work. See "help arburg" and "help ar_psd" for further details. ARGUMENTS: All but the first two arguments are optional and may be empty. x [vector] sampled data poles [integer scalar] required number of poles of the AR model freq [real vector] frequencies at which power spectral density is calculated. [integer scalar] number of uniformly distributed frequency values at which spectral density is calculated. [default=256] Fs [real scalar] sampling frequency (Hertz) [default=1] CONTROL-STRING ARGUMENTS - each of these arguments is a character string. Control-string arguments can be in any order after the other arguments. range 'half', 'onesided' : frequency range of the spectrum is from zero up to but not including sample_f/2. Power from negative frequencies is added to the positive side of the spectrum. 'whole', 'twosided' : frequency range of the spectrum is -sample_f/2 to sample_f/2, with negative frequencies stored in "wrap around" order after the positive frequencies; e.g. frequencies for a 10-point 'twosided' spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 'shift', 'centerdc' : same as 'whole' but with the first half of the spectrum swapped with second half to put the zero-frequency value in the middle. (See "help fftshift". If "freq" is vector, 'shift' is ignored. If model coefficients "ar_coeffs" are real, the default range is 'half', otherwise default range is 'whole'. method 'fft': use FFT to calculate power spectral density. 'poly': calculate spectral density as a polynomial of 1/z N.B. this argument is ignored if the "freq" argument is a vector. The default is 'poly' unless the "freq" argument is an integer power of 2. plot_type 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': specifies the type of plot. The default is 'plot', which means linear-linear axes. 'squared' is the same as 'plot'. 'dB' plots "10*log10(psd)". This argument is ignored and a spectrum is not plotted if the caller requires a returned value. criterion [optional string arg] model-selection criterion. Limits the number of poles so that spurious poles are not added when the whitened data has no more information in it (see Kay & Marple, 1981). Recognized values are 'AKICc' - approximate corrected Kullback information criterion (recommended), 'KIC' - Kullback information criterion 'AICc' - corrected Akaike information criterion 'AIC' - Akaike information criterion 'FPE' - final prediction error" criterion The default is to NOT use a model-selection criterion RETURNED VALUES: If return values are not required by the caller, the spectrum is plotted and nothing is returned. psd [real vector] power-spectral density estimate f_out [real vector] frequency values HINTS This function is a wrapper for arburg and ar_psd. See "help arburg", "help ar_psd". 3.10.9 pow2db ------------- -- Function File: pow2db (X) Convert power to decibels (dB). The decibel value of X is defined as D = ‘10 * log10 (x)’. If X is a vector, matrix, or N-dimensional array, the decibel value is computed over the elements of X. Examples: pow2db ([0, 10, 100]) ⇒ -Inf 10 20 See also: db2pow. 3.10.10 pwelch -------------- -- Function File: [SPECTRA,FREQ] = pwelch(X, WINDOW, OVERLAP, NFFT, FS, RANGE, PLOT_TYPE, DETREND, SLOPPY) Estimate power spectral density of data "x" by the Welch (1967) periodogram/FFT method. All arguments except "x" are optional. The data is divided into segments. If "window" is a vector, each segment has the same length as "window" and is multiplied by "window" before (optional) zero-padding and calculation of its periodogram. If "window" is a scalar, each segment has a length of "window" and a Hamming window is used. The spectral density is the mean of the periodograms, scaled so that area under the spectrum is the same as the mean square of the data. This equivalence is supposed to be exact, but in practice there is a mismatch of up to 0.5% when comparing area under a periodogram with the mean square of the data. [spectra,freq] = pwelch(x,y,window,overlap,Nfft,Fs, range,plot_type,detrend,sloppy,results) Two-channel spectrum analyser. Estimate power spectral density, cross- spectral density, transfer function and/or coherence functions of time- series input data "x" and output data "y" by the Welch (1967) periodogram/FFT method. pwelch treats the second argument as "y" if there is a control-string argument "cross", "trans", "coher" or "ypower"; "power" does not force the 2nd argument to be treated as "y". All other arguments are optional. All spectra are returned in matrix "spectra". [spectra,Pxx_ci,freq] = pwelch(x,window,overlap,Nfft,Fs,conf, range,plot_type,detrend,sloppy) [spectra,Pxx_ci,freq] = pwelch(x,y,window,overlap,Nfft,Fs,conf, range,plot_type,detrend,sloppy,results) Estimates confidence intervals for the spectral density. See Hint (7) below for compatibility options. Confidence level "conf" is the 6th or 7th numeric argument. If "results" control-string arguments are used, one of them must be "power" when the "conf" argument is present; pwelch can estimate confidence intervals only for the power spectrum of the "x" data. It does not know how to estimate confidence intervals of the cross-power spectrum, transfer function or coherence; if you can suggest a good method, please send a bug report. ARGUMENTS All but the first argument are optional and may be empty, except that the "results" argument may require the second argument to be "y". x [non-empty vector] system-input time-series data y [non-empty vector] system-output time-series data window [real vector] of window-function values; the data segment has the same length as the window. Default window shape is Hamming. [integer scalar] length of each data segment. The default value is window=sqrt(length(x)) rounded up to the nearest integer power of 2; see 'sloppy' argument. overlap [real scalar] segment overlap expressed as a multiple of window or segment length. 0 <= overlap < 1, The default is overlap=0.5 . Nfft [integer scalar] Length of FFT. The default is the length of the "window" vector or has the same value as the scalar "window" argument. If Nfft is larger than the segment length, "seg_len", the data segment is padded with "Nfft-seg_len" zeros. The default is no padding. Nfft values smaller than the length of the data segment (or window) are ignored silently. Fs [real scalar] sampling frequency (Hertz); default=1.0 conf [real scalar] confidence level between 0 and 1. Confidence intervals of the spectral density are estimated from scatter in the periodograms and are returned as Pxx_ci. Pxx_ci(:,1) is the lower bound of the confidence interval and Pxx_ci(:,2) is the upper bound. If there are three return values, or conf is an empty matrix, confidence intervals are calculated for conf=0.95 . If conf is zero or is not given, confidence intervals are not calculated. Confidence intervals can be obtained only for the power spectral density of x; nothing else. CONTROL-STRING ARGUMENTS - each of these arguments is a character string. Control-string arguments must be after the other arguments but can be in any order. range 'half', 'onesided' : frequency range of the spectrum is zero up to but not including Fs/2. Power from negative frequencies is added to the positive side of the spectrum, but not at zero or Nyquist (Fs/2) frequencies. This keeps power equal in time and spectral domains. See reference [2]. 'whole', 'twosided' : frequency range of the spectrum is -Fs/2 to Fs/2, with negative frequencies stored in "wrap around" order after the positive frequencies; e.g. frequencies for a 10-point 'twosided' spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 'shift', 'centerdc' : same as 'whole' but with the first half of the spectrum swapped with second half to put the zero-frequency value in the middle. (See "help fftshift". If data (x and y) are real, the default range is 'half', otherwise default range is 'whole'. plot_type 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': specifies the type of plot. The default is 'plot', which means linear-linear axes. 'squared' is the same as 'plot'. 'dB' plots "10*log10(psd)". This argument is ignored and a spectrum is not plotted if the caller requires a returned value. detrend 'no-strip', 'none' - do NOT remove mean value from the data 'short', 'mean' - remove the mean value of each segment from each segment of the data. 'linear', - remove linear trend from each segment of the data. 'long-mean' - remove the mean value from the data before splitting it into segments. This is the default. sloppy 'sloppy': FFT length is rounded up to the nearest integer power of 2 by zero padding. FFT length is adjusted after addition of padding by explicit Nfft argument. The default is to use exactly the FFT and window/ segment lengths specified in argument list. results specifies what results to return (in the order specified and as many as desired). 'power' calculate power spectral density of "x" 'cross' calculate cross spectral density of "x" and "y" 'trans' calculate transfer function of a system with input "x" and output "y" 'coher' calculate coherence function of "x" and "y" 'ypower' calculate power spectral density of "y" The default is 'power', with argument "y" omitted. RETURNED VALUES: If return values are not required by the caller, the results are plotted and nothing is returned. spectra [real-or-complex matrix] columns of the matrix contain results in the same order as specified by "results" arguments. Each column contains one of the result vectors. Pxx_ci [real matrix] estimate of confidence interval for power spectral density of x. First column is the lower bound. Second column is the upper bound. freq [real column vector] frequency values HINTS 1. EMPTY ARGS: if you don't want to use an optional argument you can leave it empty by writing its value as []. 2. FOR BEGINNERS: The profusion of arguments may make pwelch difficult to use, and an unskilled user can easily produce a meaningless result or can easily mis-interpret the result. With real data "x" and sampling frequency "Fs", the easiest and best way for a beginner to use pwelch is probably "pwelch(x,[],[],[],Fs)". Use the "window" argument to control the length of the spectrum vector. For real data and integer scalar M, "pwelch(x,2*M,[],[],Fs)" gives an M+1 point spectrum. Run "demo pwelch" (octave only). 3. WINDOWING FUNCTIONS: Without a window function, sharp spectral peaks can have strong sidelobes because the FFT of a data in a segment is in effect convolved with a rectangular window. A window function which tapers off (gradually) at the ends produces much weaker sidelobes in the FFT. Hann (hanning), hamming, bartlett, blackman, flattopwin etc are available as separate Matlab/sigproc or Octave functions. The sidelobes of the Hann window have a roll-off rate of 60dB/decade of frequency. The first sidelobe of the Hamming window is suppressed and is about 12dB lower than the first Hann sidelobe, but the roll-off rate is only 20dB/decade. You can inspect the FFT of a Hann window by plotting "abs(fft(postpad(hanning(256),4096,0)))". The default window is Hamming. 4. ZERO PADDING: Zero-padding reduces the frequency step in the spectrum, and produces an artificially smoothed spectrum. For example, "Nfft=2*length(window)" gives twice as many frequency values, but adjacent PSD (power spectral density) values are not independent; adjacent PSD values are independent if "Nfft=length(window)", which is the default value of Nfft. 5. REMOVING MEAN FROM SIGNAL: If the mean is not removed from the signal there is a large spectral peak at zero frequency and the sidelobes of this peak are likely to swamp the rest of the spectrum. For this reason, the default behavior is to remove the mean. However, the matlab pwelch does not do this. 6. WARNING ON CONFIDENCE INTERVALS Confidence intervals are obtained by measuring the sample variance of the periodograms and assuming that the periodograms have a Gaussian probability distribution. This assumption is not accurate. If, for example, the data (x) is Gaussian, the periodogram has a Rayleigh distribution. However, the confidence intervals may still be useful. 7. COMPATIBILITY WITH Matlab R11, R12, etc When used without the second data (y) argument, arguments are compatible with the pwelch of Matlab R12, R13, R14, 2006a and 2006b except that 1) overlap is expressed as a multiple of window length -- effect of overlap scales with window length 2) default values of length(window), Nfft and Fs are more sensible, and 3) Goertzel algorithm is not available so Nfft cannot be an array of frequencies as in Matlab 2006b. Pwelch has four persistent Matlab-compatibility levels. Calling pwelch with an empty first argument sets the order of arguments and defaults specified above in the USAGE and ARGUMENTS section of this documentation. prev_compat=pwelch([]); [Pxx,f]=pwelch(x,window,overlap,Nfft,Fs,conf,...); Calling pwelch with a single string argument (as described below) gives compatibility with Matlab R11 or R12, or the R14 spectrum.welch defaults. The returned value is the PREVIOUS compatibility string. Matlab R11: For compatibility with the Matlab R11 pwelch: prev_compat=pwelch('R11-'); [Pxx,f]=pwelch(x,Nfft,Fs,window,overlap,conf,range,units); %% units of overlap are "number of samples" %% defaults: Nfft=min(length(x),256), Fs=2*pi, length(window)=Nfft, %% window=Hanning, do not detrend, %% N.B. "Sloppy" is not available. Matlab R12: For compatibility with Matlab R12 to 2006a pwelch: prev_compat=pwelch('R12+'); [Pxx,f]=pwelch(x,window,overlap,nfft,Fs,...); %% units of overlap are "number of samples" %% defaults: length(window)==length(x)/8, window=Hamming, %% Nfft=max(256,NextPow2), Fs=2*pi, do not detrend %% NextPow2 is the next power of 2 greater than or equal to the %% window length. "Sloppy", "conf" are not available. Default %% window length gives very poor amplitude resolution. To adopt defaults of the Matlab R14 "spectrum.welch" spectrum object associated "psd" method. prev_compat=pwelch('psd'); [Pxx,f] = pwelch(x,window,overlap,Nfft,Fs,conf,...); %% overlap is expressed as a percentage of window length, %% defaults: length(window)==64, Nfft=max(256,NextPow2), Fs=2*pi %% do not detrend %% NextPow2 is the next power of 2 greater than or equal to the %% window length. "Sloppy" is not available. %% Default window length gives coarse frequency resolution. REFERENCES [1] Peter D. Welch (June 1967): "The use of fast Fourier transform for the estimation of power spectra: a method based on time averaging over short, modified periodograms." IEEE Transactions on Audio Electroacoustics, Vol AU-15(6), pp 70-73 [2] William H. Press and Saul A. Teukolsky and William T. Vetterling and Brian P. Flannery", "Numerical recipes in C, The art of scientific computing", 2nd edition, Cambridge University Press, 2002 -- Section 13.7. 3.10.11 pyulear --------------- -- Function File: [psd,f_out] = pyulear(x,poles,freq,Fs,range,method,plot_type) Calculates a Yule-Walker autoregressive (all-pole) model of the data "x" and computes the power spectrum of the model. This is a wrapper for functions "aryule" and "ar_psd" which perform the argument checking. See "help aryule" and "help ar_psd" for further details. ARGUMENTS: All but the first two arguments are optional and may be empty. x [vector] sampled data poles [integer scalar] required number of poles of the AR model freq [real vector] frequencies at which power spectral density is calculated [integer scalar] number of uniformly distributed frequency values at which spectral density is calculated. [default=256] Fs [real scalar] sampling frequency (Hertz) [default=1] CONTROL-STRING ARGUMENTS - each of these arguments is a character string. Control-string arguments can be in any order after the other arguments. range 'half', 'onesided' : frequency range of the spectrum is from zero up to but not including sample_f/2. Power from negative frequencies is added to the positive side of the spectrum. 'whole', 'twosided' : frequency range of the spectrum is -sample_f/2 to sample_f/2, with negative frequencies stored in "wrap around" order after the positive frequencies; e.g. frequencies for a 10-point 'twosided' spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 'shift', 'centerdc' : same as 'whole' but with the first half of the spectrum swapped with second half to put the zero-frequency value in the middle. (See "help fftshift". If "freq" is vector, 'shift' is ignored. If model coefficients "ar_coeffs" are real, the default range is 'half', otherwise default range is 'whole'. method 'fft': use FFT to calculate power spectrum. 'poly': calculate power spectrum as a polynomial of 1/z N.B. this argument is ignored if the "freq" argument is a vector. The default is 'poly' unless the "freq" argument is an integer power of 2. plot_type 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': specifies the type of plot. The default is 'plot', which means linear-linear axes. 'squared' is the same as 'plot'. 'dB' plots "10*log10(psd)". This argument is ignored and a spectrum is not plotted if the caller requires a returned value. RETURNED VALUES: If return values are not required by the caller, the spectrum is plotted and nothing is returned. psd [real vector] power-spectrum estimate f_out [real vector] frequency values HINTS This function is a wrapper for aryule and ar_psd. See "help aryule", "help ar_psd". 3.10.12 tfe ----------- -- Function File: [Pxx,freq] = tfe(x,y,Nfft,Fs,window,overlap,range,plot_type,detrend) Estimate transfer function of system with input "x" and output "y". Use the Welch (1967) periodogram/FFT method. Compatible with Matlab R11 tfe and earlier. See "help pwelch" for description of arguments, hints and references -- especially hint (7) for Matlab R11 defaults. 3.10.13 tfestimate ------------------ -- Function File: tfestimate (X, Y) -- Function File: tfestimate (X, Y, WINDOW) -- Function File: tfestimate (X, Y, WINDOW, OVERLAP) -- Function File: tfestimate (X, Y, WINDOW, OVERLAP, NFFT) -- Function File: tfestimate (X, Y, WINDOW, OVERLAP, NFFT, FS) -- Function File: tfestimate (X, Y, WINDOW, OVERLAP, NFFT, FS, RANGE) -- Function File: [PXX, FREQ] = tfestimate (...) Estimate transfer function of system with input X and output Y. Use the Welch (1967) periodogram/FFT method. See also: pwelch.  File: signal.info, Node: Window Functions, Next: System Identification, Prev: Power Spectrum Analysis, Up: Function Reference 3.11 Window Functions ===================== 3.11.1 barthannwin ------------------ -- Function File: barthannwin (M) Return the filter coefficients of a modified Bartlett-Hann window of length M. See also: rectwin, bartlett. 3.11.2 blackmanharris --------------------- -- Function File: blackmanharris (M) -- Function File: blackmanharris (M, "periodic") -- Function File: blackmanharris (M, "symmetric") Return the filter coefficients of a Blackman-Harris window of length M. If the optional argument ‘"periodic"’ is given, the periodic form of the window is returned. This is equivalent to the window of length M+1 with the last coefficient removed. The optional argument ‘"symmetric"’ is equivalent to not specifying a second argument. See also: rectwin, bartlett. 3.11.3 blackmannuttall ---------------------- -- Function File: blackmannuttall (M) -- Function File: blackmannuttall (M, "periodic") -- Function File: blackmannuttall (M, "symmetric") Return the filter coefficients of a Blackman-Nuttall window of length M. If the optional argument ‘"periodic"’ is given, the periodic form of the window is returned. This is equivalent to the window of length M+1 with the last coefficient removed. The optional argument ‘"symmetric"’ is equivalent to not specifying a second argument. See also: nuttallwin, kaiser. 3.11.4 bohmanwin ---------------- -- Function File: bohmanwin (M) Return the filter coefficients of a Bohman window of length M. See also: rectwin, bartlett. 3.11.5 boxcar ------------- -- Function File: boxcar (M) Return the filter coefficients of a rectangular window of length M. 3.11.6 chebwin -------------- -- Function File: chebwin (M) -- Function File: chebwin (M, AT) Return the filter coefficients of a Dolph-Chebyshev window of length M. The Fourier transform of the window has a stop-band attenuation of AT dB. The default attenuation value is 100 dB. For the definition of the Chebyshev window, see * Peter Lynch, "The Dolph-Chebyshev Window: A Simple Optimal Filter", Monthly Weather Review, Vol. 125, pp. 655-660, April 1997. (http://www.maths.tcd.ie/~plynch/Publications/Dolph.pdf) * C. Dolph, "A current distribution for broadside arrays which optimizes the relationship between beam width and side-lobe level", Proc. IEEE, 34, pp. 335-348. The window is described in frequency domain by the expression: Cheb(m-1, beta * cos(pi * k/m)) W(k) = ------------------------------- Cheb(m-1, beta) with beta = cosh(1/(m-1) * acosh(10^(at/20)) and Cheb(m,x) denoting the m-th order Chebyshev polynomial calculated at the point x. Note that the denominator in W(k) above is not computed, and after the inverse Fourier transform the window is scaled by making its maximum value unitary. See also: kaiser. 3.11.7 expwin ------------- -- Function File: expwin (M, ALPHA) -- Function File: expwin (M, SLL) -- Function File: expwin (..., "canonical") Return the coefficients of an exponential window(1) of length M. The window's adjustable parameter can be set directly as ALPHA (≥0) or indirectly with SLL (<0), the latter being the desired side-lobe level in dBc. By default, the returned window is both symmetric and periodic. With the optional argument "canonical", the canonical form of the window is returned, which is symmetric but not periodic. See also: kaiser, poisswin. 3.11.8 flattopwin ----------------- -- Function File: flattopwin (M) -- Function File: flattopwin (M, "periodic") -- Function File: flattopwin (M, "symmetric") Return the filter coefficients of a Flat Top window of length M. The Flat Top window is defined by the function f(w): f(w) = 1 - 1.93 cos(2 pi w) + 1.29 cos(4 pi w) - 0.388 cos(6 pi w) + 0.0322cos(8 pi w) where w = i/(m-1) for i=0:m-1 for a symmetric window, or w = i/m for i=0:m-1 for a periodic window. The default is symmetric. The returned window is normalized to a peak of 1 at w = 0.5. This window has low pass-band ripple, but high bandwidth. According to [1]: The main use for the Flat Top window is for calibration, due to its negligible amplitude errors. [1] Gade, S; Herlufsen, H; (1987) "Use of weighting functions in DFT/FFT analysis (Part I)", Bruel & Kjaer Technical Review No.3. 3.11.9 gaussian --------------- -- Function File: gaussian (M) -- Function File: gaussian (M, A) Return a Gaussian convolution window of length M. The width of the window is inversely proportional to the parameter A. Use larger A for a narrower window. Use larger M for longer tails. w = exp ( -(a*x)^2/2 ) for x = linspace ( -(m-1)/2, (m-1)/2, m ). Width a is measured in frequency units (sample rate/num samples). It should be f when multiplying in the time domain, but 1/f when multiplying in the frequency domain (for use in convolutions). 3.11.10 gausswin ---------------- -- Function File: gausswin (M) -- Function File: gausswin (M, A) Return the filter coefficients of a Gaussian window of length M. The width of the window is inversely proportional to the parameter A. Use larger A for a narrow window. Use larger M for a smoother curve. w = exp ( -(a*x)^2/2 ) for x = linspace(-(m-1)/m, (m-1)/m, m) 3.11.11 hann ------------ -- Function File: hann (M) -- Function File: hann (M, "periodic") -- Function File: hann (M, "symmetric") Return the filter coefficients of a Hanning window of length M. If the optional argument ‘"periodic"’ is given, the periodic form of the window is returned. This is equivalent to the window of length M+1 with the last coefficient removed. The optional argument ‘"symmetric"’ is equivalent to not specifying a second argument. This function exists for MATLAB compatibility only, and is equivalent to ‘hanning (M)’. See also: hanning. 3.11.12 kaiser -------------- -- Function File: kaiser (M) -- Function File: kaiser (M, BETA) Return the filter coefficients of a Kaiser window of length M. The Fourier transform of the window has a stop-band attenuation that is derived from the parameter BETA. For the definition of the Kaiser window, see A. V. Oppenheim & R. W. Schafer, "Discrete-Time Signal Processing". The continuous version of width m centered about x=0 is: besseli(0, beta * sqrt(1-(2*x/m).^2)) k(x) = -------------------------------------, m/2 <= x <= m/2 besseli(0, beta) See also: kaiserord. 3.11.13 nuttallwin ------------------ -- Function File: nuttallwin (M) -- Function File: nuttallwin (M, "periodic") -- Function File: nuttallwin (M, "symmetric") Return the filter coefficients of a Blackman-Harris window defined by Nuttall of length M. If the optional argument ‘"periodic"’ is given, the periodic form of the window is returned. This is equivalent to the window of length M+1 with the last coefficient removed. The optional argument ‘"symmetric"’ is equivalent to not specifying a second argument. See also: blackman, blackmanharris. 3.11.14 parzenwin ----------------- -- Function File: parzenwin (M) Return the filter coefficients of a Parzen window of length M. See also: rectwin, bartlett. 3.11.15 poisswin ---------------- -- Function File: poisswin (M, ALPHA) Return the coefficients of a Poisson (a.k.a. exponential) window(2) of length M and adjustable parameter ALPHA. 3.11.16 rectwin --------------- -- Function File: rectwin (M) Return the filter coefficients of a rectangular window of length M. See also: boxcar, hamming, hanning. 3.11.17 taylorwin ----------------- -- Function File: taylorwin (M) -- Function File: taylorwin (M, NBAR) -- Function File: taylorwin (M, NBAR, SLL) -- Function File: taylorwin (M, NBAR, SLL, PLOTS) Return the coefficients of a Taylor window of length M, whose Fourier transform has NBAR (default 4) quasi-equiripple side-lobes adjacent to the main-lobe, at a nominal level of SLL (default −30) dBc. If PLOTS is non-zero then time and frequency domains plots of the resultant window are shown. Reference: Doerry, 'Catalog of Window Taper Functions for Sidelobe Control', 2017. See also: chebwin. 3.11.18 triang -------------- -- Function File: triang (M) Return the filter coefficients of a triangular window of length M. Unlike the Bartlett window, ‘triang’ does not go to zero at the edges of the window. For odd M, ‘triang (M)’ is equal to ‘bartlett (M + 2)’ except for the zeros at the edges of the window. See also: bartlett. 3.11.19 tukeywin ---------------- -- Function File: tukeywin (M) -- Function File: tukeywin (M, R) Return the filter coefficients of a Tukey window (also known as the cosine-tapered window) of length M. R defines the ratio between the constant section and and the cosine section. It has to be between 0 and 1. The function returns a Hanning window for R equal to 1 and a rectangular window for R equal to 0. The default value of R is 1/2. For a definition of the Tukey window, see e.g. Fredric J. Harris, "On the Use of Windows for Harmonic Analysis with the Discrete Fourier Transform, Proceedings of the IEEE", Vol. 66, No. 1, January 1978, Page 67, Equation 38. See also: hanning. 3.11.20 ultrwin --------------- -- Function File: [W, XMU] = ultrwin (M, MU, BETA) -- Function File: [W, XMU] = ultrwin (M, MU, ATT, "att") -- Function File: [W, XMU] = ultrwin (M, MU, LATT, "latt") -- Function File: W = ultrwin (M, MU, XMU, "xmu") Return the coefficients of an Ultraspherical window of length M. The parameter MU controls the window's Fourier transform's side-lobe to side-lobe ratio, and the third given parameter controls the transform's main-lobe width/side-lobe-ratio; normalize W such that the central coefficient(s) value is unitary. By default, the third parameter is BETA, which sets the main lobe width to BETA times that of a rectangular window. Alternatively, giving ATT or LATT sets the ripple ratio at the first or last side-lobe respectively, or giving XMU sets the (un-normalized) window's Fourier transform according to its canonical definition: (MU) W(k) = C [ XMU cos(pi k/M) ], k = 0, 1, ..., M-1, M-1 where C is the Ultraspherical (a.k.a. Gegenbauer) polynomial, which can be defined using the recurrence relationship: (l) 1 (l) (l) C (x) = - [ 2x(m + l - 1) C (x) - (m + 2l - 2) C (x) ] m m m-1 m-2 (l) (l) for m an integer > 1, and C (x) = 1, C (x) = 2lx. 0 1 For given BETA, ATT, or LATT, the corresponding (determined) value of XMU is also returned. The Dolph-Chebyshev and Saramaki windows are special cases of the Ultraspherical window, with MU set to 0 and 1 respectively. Note that when not giving XMU, stability issues may occur with MU <= -1.5. For further information about the window, see • Kabal, P., 2009: Time Windows for Linear Prediction of Speech. Technical Report, Dept. Elec. & Comp. Eng., McGill University. • Bergen, S., Antoniou, A., 2004: Design of Ultraspherical Window Functions with Prescribed Spectral Characteristics. Proc. JASP, 13/13, pp. 2053-2065. • Streit, R., 1984: A two-parameter family of weights for nonrecursive digital filters and antennas. Trans. ASSP, 32, pp. 108-118. See also: chebwin, kaiser. 3.11.21 welchwin ---------------- -- Function File: welchwin (M) -- Function File: welchwin (M, "periodic") -- Function File: welchwin (M, "symmetric") Return the filter coefficients of a Welch window of length M. The Welch window is given by W(n)=1-(n/N-1)^2, n=[0,1, ... M-1]. The optional argument specifies a "symmetric" window (the default) or a "periodic" window. A symmetric window has zero at each end and maximum in the middle, and the length must be an integer greater than 2. The variable N in the formula above is ‘(M-1)/2’. A periodic window wraps around the cyclic interval [0,1, ... M-1], and is intended for use with the DFT. The length must be an integer greater than 1. The variable N in the formula above is ‘M/2’. See also: blackman, kaiser. 3.11.22 window -------------- -- Function File: W = window (F, M) -- Function File: W = window (F, M, OPTS) Create an M-point window from the function F. The function F can be for example ‘@blackman’. Any additional arguments OPT are passed to the windowing function. ---------- Footnotes ---------- (1) K. Avci & A. Nacaroglu, 'Exponential Window Family', SIPIJ Vol. 4 No. 4, August 2013. (2) S. Gade & H. Herlufsen, 'Windows to FFT analysis (Part I)', Technical Review 3, Bruel & Kjaer, 1987  File: signal.info, Node: System Identification, Next: Sample Rate Change, Prev: Window Functions, Up: Function Reference 3.12 System Identification ========================== 3.12.1 arburg ------------- -- Function File: [A, V, K] = arburg (X, POLES) -- Function File: [A, V, K] = arburg (X, POLES, CRITERION) Calculate coefficients of an autoregressive (AR) model of complex data X using the whitening lattice-filter method of Burg (1968). The inverse of the model is a moving-average filter which reduces X to white noise. The power spectrum of the AR model is an estimate of the maximum entropy power spectrum of the data. The function ‘ar_psd’ calculates the power spectrum of the AR model. ARGUMENTS: • X sampled data • POLES number of poles in the AR model or limit to the number of poles if a valid CRITERION is provided. • CRITERION model-selection criterion. Limits the number of poles so that spurious poles are not added when the whitened data has no more information in it (see Kay & Marple, 1981). Recognized values are 'AKICc' - approximate corrected Kullback information criterion (recommended), 'KIC' - Kullback information criterion 'AICc' - corrected Akaike information criterion 'AIC' - Akaike information criterion 'FPE' - final prediction error" criterion The default is to NOT use a model-selection criterion RETURNED VALUES: • A list of (P+1) autoregression coefficients; for data input x(n) and white noise e(n), the model is P+1 x(n) = sqrt(v).e(n) + SUM a(k).x(n-k) k=1 V mean square of residual noise from the whitening operation of the Burg lattice filter. • K reflection coefficients defining the lattice-filter embodiment of the model HINTS: (1) arburg does not remove the mean from the data. You should remove the mean from the data if you want a power spectrum. A non-zero mean can produce large errors in a power-spectrum estimate. See "help detrend". (2) If you don't know what the value of "poles" should be, choose the largest (reasonable) value you could want and use the recommended value, criterion='AKICc', so that arburg can find it. E.g. arburg(x,64,'AKICc') The AKICc has the least bias and best resolution of the available model-selection criteria. (3) Autoregressive and moving-average filters are stored as polynomials which, in matlab, are row vectors. NOTE ON SELECTION CRITERION: AIC, AICc, KIC and AKICc are based on information theory. They attempt to balance the complexity (or length) of the model against how well the model fits the data. AIC and KIC are biased estimates of the asymmetric and the symmetric Kullback-Leibler divergence respectively. AICc and AKICc attempt to correct the bias. See reference [4]. REFERENCES: [1] John Parker Burg (1968) "A new analysis technique for time series data", NATO advanced study Institute on Signal Processing with Emphasis on Underwater Acoustics, Enschede, Netherlands, Aug. 12-23, 1968. [2] Steven M. Kay and Stanley Lawrence Marple Jr.: "Spectrum analysis - a modern perspective", Proceedings of the IEEE, Vol 69, pp 1380-1419, Nov., 1981 [3] William H. Press and Saul A. Teukolsky and William T. Vetterling and Brian P. Flannery "Numerical recipes in C, The art of scientific computing", 2nd edition, Cambridge University Press, 2002 -- Section 13.7. [4] Abd-Krim Seghouane and Maiza Bekara "A small sample model selection criterion based on Kullback's symmetric divergence", IEEE Transactions on Signal Processing, Vol. 52(12), pp 3314-3323, Dec. 2004 See also: ar_psd. 3.12.2 aryule ------------- -- Function File: A = aryule (X, P) -- Function File: [A, V, K] = aryule (X, P) Fit an AR (P)-model with Yule-Walker estimates. X data vector to estimate A AR coefficients V variance of white noise K reflection coefficients for use in lattice filter The power spectrum of the resulting filter can be plotted with pyulear(x, p), or you can plot it directly with ar_psd(a,v,...). See also: pyulear, power, freqz, impz - for observing characteristics of the model arburg - for alternative spectral estimators Example: Use example from arburg, but substitute aryule for arburg. Note: Orphanidis '85 claims lattice filters are more tolerant of truncation errors, which is why you might want to use them. However, lacking a lattice filter processor, I haven't tested that the lattice filter coefficients are reasonable. 3.12.3 invfreq -------------- -- Function File: [B,A] = invfreq(H,F,nB,nA) -- : [B,A] = invfreq(H,F,nB,nA,W) -- : [B,A] = invfreq(H,F,nB,nA,W,[],[],plane) -- : [B,A] = invfreq(H,F,nB,nA,W,iter,tol,plane) Fit filter B(z)/A(z) or B(s)/A(s) to complex frequency response at frequency points F. A and B are real polynomial coefficients of order nA and nB respectively. Optionally, the fit-errors can be weighted vs frequency according to the weights W. Also, the transform plane can be specified as either 's' for continuous time or 'z' for discrete time. 'z' is chosen by default. Eventually, Steiglitz-McBride iterations will be specified by iter and tol. H: desired complex frequency response It is assumed that A and B are real polynomials, hence H is one-sided. F: vector of frequency samples in radians nA: order of denominator polynomial A nB: order of numerator polynomial B plane='z': F on unit circle (discrete-time spectra, z-plane design) plane='s': F on jw axis (continuous-time spectra, s-plane design) H(k) = spectral samples of filter frequency response at points zk, where zk=exp(sqrt(-1)*F(k)) when plane='z' (F(k) in [0,.5]) and zk=(sqrt(-1)*F(k)) when plane='s' (F(k) nonnegative) Example: [B,A] = butter(12,1/4); [H,w] = freqz(B,A,128); [Bh,Ah] = invfreq(H,F,4,4); Hh = freqz(Bh,Ah); disp(sprintf('||frequency response error|| = %f',norm(H-Hh))); References: J. O. Smith, "Techniques for Digital Filter Design and System Identification with Application to the Violin, Ph.D. Dissertation, Elec. Eng. Dept., Stanford University, June 1983, page 50; or, http://ccrma.stanford.edu/~jos/filters/FFT_Based_Equation_Error_Method.html 3.12.4 invfreqs --------------- -- Function File: [B,A] = invfreqs(H,F,nB,nA) -- : [B,A] = invfreqs(H,F,nB,nA,W) -- : [B,A] = invfreqs(H,F,nB,nA,W,iter,tol,'trace') Fit filter B(s)/A(s)to the complex frequency response H at frequency points F. A and B are real polynomial coefficients of order nA and nB. Optionally, the fit-errors can be weighted vs frequency according to the weights W. Note: all the guts are in invfreq.m H: desired complex frequency response F: frequency (must be same length as H) nA: order of the denominator polynomial A nB: order of the numerator polynomial B W: vector of weights (must be same length as F) Example: B = [1/2 1]; A = [1 1]; w = linspace(0,4,128); H = freqs(B,A,w); [Bh,Ah] = invfreqs(H,w,1,1); Hh = freqs(Bh,Ah,w); plot(w,[abs(H);abs(Hh)]) legend('Original','Measured'); err = norm(H-Hh); disp(sprintf('L2 norm of frequency response error = %f',err)); 3.12.5 invfreqz --------------- -- Function File: [B,A] = invfreqz(H,F,nB,nA) -- : [B,A] = invfreqz(H,F,nB,nA,W) -- : [B,A] = invfreqz(H,F,nB,nA,W,iter,tol,'trace') Fit filter B(z)/A(z)to the complex frequency response H at frequency points F. A and B are real polynomial coefficients of order nA and nB. Optionally, the fit-errors can be weighted vs frequency according to the weights W. Note: all the guts are in invfreq.m H: desired complex frequency response F: normalized frequency (0 to pi) (must be same length as H) nA: order of the denominator polynomial A nB: order of the numerator polynomial B W: vector of weights (must be same length as F) Example: [B,A] = butter(4,1/4); [H,F] = freqz(B,A); [Bh,Ah] = invfreq(H,F,4,4); Hh = freqz(Bh,Ah); disp(sprintf('||frequency response error|| = %f',norm(H-Hh))); 3.12.6 levinson --------------- -- Function File: [A, V, REF] = levinson (ACF) -- Function File: [...] = levinson (ACF, P) Use the Durbin-Levinson algorithm to solve: toeplitz(acf(1:p)) * x = -acf(2:p+1). The solution [1, x'] is the denominator of an all pole filter approximation to the signal x which generated the autocorrelation function acf. acf is the autocorrelation function for lags 0 to p. p defaults to length(acf)-1. Returns a=[1, x'] the denominator filter coefficients. v= variance of the white noise = square of the numerator constant ref = reflection coefficients = coefficients of the lattice implementation of the filter Use freqz(sqrt(v),a) to plot the power spectrum. REFERENCE [1] Steven M. Kay and Stanley Lawrence Marple Jr.: "Spectrum analysis - a modern perspective", Proceedings of the IEEE, Vol 69, pp 1380-1419, Nov., 1981 3.12.7 lpc ---------- -- Function File: A = lpc (X) -- Function File: A = lpc (X, P) -- Function File: [A, G] = lpc (...) -- Function File: [A, G] = lpc (X, P) Determines the forward linear predictor by minimizing the prediction error in the least squares sense. Use the Durbin-Levinson algorithm to solve the Yule-Walker equations obtained by the autocorrelation of the input signal. X is a data vector used to estimate the lpc model of P-th order, given by the prediction polynomial ‘A = [1 A(2) ... A(P+1)]’. If P is not provided, ‘length(P) - 1’ is used as default. X might also be a matrix, in which case each column is regarded as a separate signal. ‘lpc’ will return a model estimate for each column of X. G is the variance (power) of the prediction error for each signal in X. See also: aryule,levinson.  File: signal.info, Node: Sample Rate Change, Next: Pulse Metrics, Prev: System Identification, Up: Function Reference 3.13 Sample Rate Change ======================= 3.13.1 data2fun --------------- -- Function File: [FHANDLE, FULLNAME] = data2fun (TI, YI) -- Function File: [...] = data2fun (..., PROPERTY, VALUE) Create a vectorized function based on data samples using interpolation. The values given in YI (N-by-k matrix) correspond to evaluations of the function y(t) at the points TI (N-by-1 matrix). The data is interpolated and the function handle to the generated interpolant is returned. The function accepts PROPERTY-VALUE pairs described below. ‘file’ Code is generated and .m file is created. The VALUE contains the name of the function. The returned function handle is a handle to that file. If VALUE is empty, then a name is automatically generated using ‘tempname’ and the file is created in the current directory. VALUE must not have an extension, since .m will be appended. Numerical values used in the function are stored in a .mat file with the same name as the function. ‘interp’ Type of interpolation. See ‘interp1’. See also: interp1. 3.13.2 decimate --------------- -- Function File: Y = decimate (X, Q) -- Function File: Y = decimate (X, Q, N) -- Function File: Y = decimate (..., "fir") Downsample the signal X by a reduction factor of Q. A lowpass antialiasing filter is applied to the signal prior to reducing the input sequence. By default, an order N Chebyshev type I filter is used. If N is not specified, the default is 8. If the optional argument ‘"fir"’ is given, an order N FIR filter is used, with a default order of 30 if N is not given. Note that Q must be an integer for this rate change method. Example: ## Generate a signal that starts away from zero, is slowly varying ## at the start and quickly varying at the end, decimate and plot. ## Since it starts away from zero, you will see the boundary ## effects of the antialiasing filter clearly. Next you will see ## how it follows the curve nicely in the slowly varying early ## part of the signal, but averages the curve in the quickly ## varying late part of the signal. t = 0:0.01:2; x = chirp (t, 2, .5, 10, "quadratic") + sin (2*pi*t*0.4); y = decimate (x, 4); stem (t(1:121) * 1000, x(1:121), "-g;Original;"); hold on; # original stem (t(1:4:121) * 1000, y(1:31), "-r;Decimated;"); hold off; # decimated 3.13.3 downsample ----------------- -- Function File: Y = downsample (X, N) -- Function File: Y = downsample (X, N, OFFSET) Downsample the signal, selecting every Nth element. If X is a matrix, downsample every column. For most signals you will want to use ‘decimate’ instead since it prefilters the high frequency components of the signal and avoids aliasing effects. If OFFSET is defined, select every Nth element starting at sample OFFSET. See also: decimate, interp, resample, upfirdn, upsample. 3.13.4 interp ------------- -- Function File: Y = interp (X, Q) -- Function File: Y = interp (X, Q, N) -- Function File: Y = interp (X, Q, N, WC) Upsample the signal x by a factor of q, using an order 2*q*n+1 FIR filter. Note that q must be an integer for this rate change method. n defaults to 4 and Wc defaults to 0.5. Example # Generate a signal. t=0:0.01:2; x=chirp(t,2,.5,10,'quadratic')+sin(2*pi*t*0.4); y = interp(x(1:4:length(x)),4,4,1); # interpolate a sub-sample stem(t(1:121)*1000,x(1:121),"-g;Original;"); hold on; stem(t(1:121)*1000,y(1:121),"-r;Interpolated;"); stem(t(1:4:121)*1000,x(1:4:121),"-b;Subsampled;"); hold off; See also: decimate, resample. 3.13.5 resample --------------- -- Function File: [Y, H] = resample (X, P, Q) -- Function File: Y = resample (X, P, Q, H) Change the sample rate of X by a factor of P/Q. This is performed using a polyphase algorithm. The impulse response H of the antialiasing filter is either specified or either designed with a Kaiser-windowed sinecard. Ref [1] J. G. Proakis and D. G. Manolakis, Digital Signal Processing: Principles, Algorithms, and Applications, 4th ed., Prentice Hall, 2007. Chap. 6 Ref [2] A. V. Oppenheim, R. W. Schafer and J. R. Buck, Discrete-time signal processing, Signal processing series, Prentice-Hall, 1999 3.13.6 upfirdn -------------- -- Loadable Function: Y = upfirdn (X, H, P, Q) Upsample, FIR filtering, and downsample. 3.13.7 upsample --------------- -- Function File: Y = upsample (X, N) -- Function File: Y = upsample (X, N, OFFSET) Upsample the signal, inserting N-1 zeros between every element. If X is a matrix, upsample every column. If OFFSET is specified, control the position of the inserted sample in the block of N zeros. See also: decimate, downsample, interp, resample, upfirdn.  File: signal.info, Node: Pulse Metrics, Next: Utility, Prev: Sample Rate Change, Up: Function Reference 3.14 Pulse Metrics ================== 3.14.1 statelevels ------------------ -- Function File: LEVELS = statelevels (A) -- Function File: LEVELS = statelevels (A, NBINS) -- Function File: LEVELS = statelevels (A, NBINS, METHOD) -- Function File: LEVELS = statelevels (A, NBINS, METHOD, BOUNDS) -- Function File: [LEVELS, HISTOGRAMS] = statelevels (...) -- Function File: [LEVELS, HISTOGRAMS, BINLEVELS] = statelevels (...) -- Function File: statelevels (...) Estimate state-level for bilevel waveform A using histogram method INPUTS: A Bylevel waveform NBINS Number of histogram bins (100 default) METHOD State-level estimation method 'mode' (default) or 'mean'. BOUNDS 2 element vector for histogram lower and upper bounds. Values outside of this will be ignored. OUTPUTS: LEVELS Levels of high and low states HISTOGRAMS Histogram counts BINLEVELS Histogram bincenters If no outputs are provided, the signal and histogram will be plotted, and display the levels.  File: signal.info, Node: Utility, Prev: Pulse Metrics, Up: Function Reference 3.15 Utility ============ 3.15.1 buffer ------------- -- Function File: Y = buffer (X, N, P, OPT) -- Function File: [Y, Z, OPT] = buffer (...) Buffer a signal into a data frame. The arguments to ‘buffer’ are X The data to be buffered. N The number of rows in the produced data buffer. This is an positive integer value and must be supplied. P An integer less than N that specifies the under- or overlap between column in the data frame. The default value of P is 0. OPT In the case of an overlap, OPT can be either a vector of length P or the string 'nodelay'. If OPT is a vector, then the first P entries in Y will be filled with these values. If OPT is the string 'nodelay', then the first value of Y corresponds to the first value of X. In the can of an underlap, OPT must be an integer between 0 and ‘-P’. The represents the initial underlap of the first column of Y. The default value for OPT the vector ‘zeros (1, P)’ in the case of an overlap, or 0 otherwise. In the case of a single output argument, Y will be padded with zeros to fill the missing values in the data frame. With two output arguments Z is the remaining data that has not been used in the current data frame. Likewise, the output OPT is the overlap, or underlap that might be used for a future call to ‘code’ to allow continuous buffering. 3.15.2 clustersegment --------------------- -- Function File: CLUSTERIDX = clustersegment (UNOS) Calculate boundary indexes of clusters of 1's. The function calculates the initial index and end index of the sequences of 1's in the rows of UNOS. The clusters are sought in the rows of the array UNOS. The result is returned in a cell array of size 1-by-NP, where NP is the number of rows in UNOS. Each element of the cell has two rows. The first row is the initial index of a sequence of 1's and the second row is the end index of that sequence. If NP == 1 the output is a matrix with two rows. The function works by finding the indexes of jumps between consecutive values in the rows of UNOS. 3.15.3 fracshift ---------------- -- Function File: [Y, H] = fracshift (X, D) -- Function File: Y = fracshift (X, D, H) Shift the series X by a (possibly fractional) number of samples D. The interpolator H is either specified or either designed with a Kaiser-windowed sinecard. See also: circshift. 3.15.4 marcumq -------------- -- Function File: Q = marcumq (A, B) -- Function File: Q = marcumq (A, B, M) -- Function File: Q = marcumq (A, B, M, TOL) Compute the generalized Marcum Q function of order M with noncentrality parameter A and argument B. If the order M is omitted it defaults to 1. An optional relative tolerance TOL may be included, the default is ‘eps’. If the input arguments are commensurate vectors, this function will produce a table of values. This function computes Marcum's Q function using the infinite Bessel series, truncated when the relative error is less than the specified tolerance. The accuracy is limited by that of the Bessel functions, so reducing the tolerance is probably not useful. Reference: Marcum, "Tables of Q Functions", Rand Corporation. Reference: R.T. Short, "Computation of Noncentral Chi-squared and Rice Random Variables", www.phaselockedsystems.com/publications 3.15.5 primitive ---------------- -- Function File: F = primitive (F, T, F0) Calculate the primitive of a function. The function approximates the primitive (indefinite integral) of the univariate function handle F with constant of integration F0. The output is the primitive evaluated at the points T. The vector T must be ordered and ascending. This function is a fancy way of calculating the cumulative sum, ‘F = cumsum (f(t).*diff (t)([1 1:end]))’. Example: f = @(t) sin (2 * pi * 3 * t); t = [0; sort(rand (100, 1))]; F = primitive (f, t, 0); t_true = linspace (0, 1, 1e3).'; F_true = (1 - cos (2 * pi * 3 * t_true)) / (2 * pi * 3); plot (t, F, 'o', t_true, F_true); See also: quadgk, cumsum. 3.15.6 sampled2continuous ------------------------- -- Function File: XT = sampled2continuous (XN, T, T) Calculate the x(t) reconstructed from samples x[n] sampled at a rate 1/T samples per unit time. t is all the instants of time when you need x(t) from x[n]; this time is relative to x[0] and not an absolute time. This function can be used to calculate sampling rate effects on aliasing, actual signal reconstruction from discrete samples. 3.15.7 schtrig -------------- -- V =: schtrig (X,LVL,RST=1) -- [V,RNG] =: schtrig (...) Implements a multisignal Schmitt trigger with levels LVL. The triger works along the first dimension of the 2-dimensional array X. It compares each column in X to the levels in LVL, when the value is higher ‘max (LVL)’ the output V is high (i.e. 1); when the value is below ‘min (LVL)’ the output is low (i.e. 0); and when the value is between the two levels the output retains its value. The threshold levels are passed in the array LVL. If this is a scalar, the thresholds are symmetric around 0, i.e. ‘[-lvl lvl]’. The second output argument stores the ranges in which the output is high, so the indexes RNG(1,I):RNG(2,I) point to the i-th segment of 1s in V. See ‘clustersegment’ for a detailed explanation. The function conserves the state of the trigger across calls (persistent variable). If the reset flag is active, i.e. ‘RST== true’, then the state of the trigger for all signals is set to the low state (i.e. 0). Example: x = [0 0.5 1 1.5 2 1.5 1.5 1.2 1 0 0].'; y = schtrig (x, [1.3 1.6]); disp ([x y]); 0.0 0 0.5 0 1.0 0 1.5 0 2.0 1 1.5 1 1.5 1 1.2 0 1.0 0 0.0 0 0.0 0 Run ‘demo schtrig’ to see further examples. See also: clustersegment. 3.15.8 upsamplefill ------------------- -- Function File: Y = upsamplefill (X, V) -- Function File: Y = upsamplefill (..., COPY) Upsamples a vector interleaving given values or copies of the vector elements. The values in the vector V are placed between the elements of X. If the optional argument COPY is TRUE then V should be a scalar and each value in X are repeat V times. Example: upsamplefill (eye (2), 2, true) ⇒ 1 0 1 0 1 0 0 1 0 1 0 1 upsamplefill (eye (2), [-1 -1 -1]) ⇒ 1 0 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 See also: upsample. 3.15.9 wkeep ------------ -- Function File: Y = wkeep (X, L) -- Function File: Y = wkeep (X, L, OPT) Extract the elements of X of size L from the center, the right or the left. 3.15.10 wrev ------------ -- Function File: Y = wrev (X) Reverse the order of the element of the vector X. See also: flipud, fliplr. 3.15.11 zerocrossing -------------------- -- Function File: X0 = zerocrossing (X, Y) Estimates the points at which a given waveform y=y(x) crosses the x-axis using linear interpolation. See also: fzero, roots.  Tag Table: Node: Top198 Node: Overview1343 Node: Installing and loading1565 Node: Function Reference2675 Node: Signals3127 Node: Signal Measurement18710 Node: Correlation and Convolution23655 Node: Filtering30507 Node: Filter Analysis35625 Node: Filter Conversion48210 Node: IIR Filter Design58420 Ref: IIR Filter Design-Footnote-196862 Ref: IIR Filter Design-Footnote-297060 Ref: IIR Filter Design-Footnote-397333 Node: FIR Filter Design97546 Node: Transforms108381 Node: Power Spectrum Analysis121433 Node: Window Functions151274 Ref: Window Functions-Footnote-1164939 Ref: Window Functions-Footnote-2165033 Node: System Identification165141 Node: Sample Rate Change175906 Node: Pulse Metrics181211 Node: Utility182441  End Tag Table  Local Variables: coding: utf-8 End: ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/doc/signal.qch�������������������������������������������������������������������������0000644�0000000�0000000�00000430000�14673270174�012454� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������SQLite format 3���@ ������#�������������������������������������������������������������.v‰ ��� o�–«A $ § › 3 ½ ? É o�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������X''qtableMetaDataTableMetaDataTableCREATE TABLE MetaDataTable(Name Text, Value BLOB )t ##/tableFolderTableFolderTableCREATE TABLE FolderTable(Id INTEGER PRIMARY KEY, Name Text, NamespaceID INTEGER )| ''7tableFileNameTableFileNameTable CREATE TABLE FileNameTable (FolderId INTEGER, Name TEXT, FileId INTEGER, Title TEXT )t ++tableFileFilterTableFileFilterTable CREATE TABLE FileFilterTable (FilterAttributeId INTEGER, FileId INTEGER )f '' tableFileDataTableFileDataTable CREATE TABLE FileDataTable (Id INTEGER PRIMARY KEY, Data BLOB ) 77#tableFileAttributeSetTableFileAttributeSetTable CREATE TABLE FileAttributeSetTable (Id INTEGER, FilterAttributeId INTEGER )33/tableContentsFilterTableContentsFilterTable CREATE TABLE ContentsFilterTable (FilterAttributeId INTEGER, ContentsId INTEGER ){''5tableContentsTableContentsTableCREATE TABLE ContentsTable (Id INTEGER PRIMARY KEY, NamespaceId INTEGER, Data BLOB )x--#tableIndexFilterTableIndexFilterTableCREATE TABLE IndexFilterTable (FilterAttributeId INTEGER, IndexId INTEGER ) !!‚ tableIndexTableIndexTableCREATE TABLE IndexTable (Id INTEGER PRIMARY KEY, Name TEXT, Identifier TEXT, NamespaceId INTEGER, FileId INTEGER, Anchor TEXT )h##tableFilterTableFilterTableCREATE TABLE FilterTable (NameId INTEGER, FilterAttributeId INTEGER )l++tableFilterNameTableFilterNameTableCREATE TABLE FilterNameTable (Id INTEGER PRIMARY KEY, Name TEXT ){55tableFilterAttributeTableFilterAttributeTableCREATE TABLE FilterAttributeTable (Id INTEGER PRIMARY KEY, Name TEXT )h)) tableNamespaceTableNamespaceTableCREATE TABLE NamespaceTable (Id INTEGER PRIMARY KEY,Name TEXT ) ���ä�ä���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;octave.community.signal �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ú����#ú�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ����ç��ç�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������₫� ü ��������s�i�g�n�a�l�.�h�t�m�l���h�O�c�t�a�v�e� �S�i�g�n�a�l� �-� �S�i�g�n�a�l� �T�o�o�l�k�i�t� �f�o�r� �G�N�U� �o�c�t�a�v�e� �M�a�n�u�a�l������(�s�i�g�n�a�l�.�h�t�m�l�#�O�v�e�r�v�i�e�w����1� �O�v�e�r�v�i�e�w������D�s�i�g�n�a�l�.�h�t�m�l�#�I�n�s�t�a�l�l�i�n�g�-�a�n�d�-�l�o�a�d�i�n�g���0�2� �I�n�s�t�a�l�l�i�n�g� �a�n�d� �l�o�a�d�i�n�g������6�s�i�g�n�a�l�.�h�t�m�l�#�W�i�n�d�o�w�s�-�i�n�s�t�a�l�l���&�2�.�1� �W�i�n�d�o�w�s� �i�n�s�t�a�l�l������,�s�i�g�n�a�l�.�h�t�m�l�#�I�n�s�t�a�l�l�i�n�g����2�.�2� �I�n�s�t�a�l�l�i�n�g������&�s�i�g�n�a�l�.�h�t�m�l�#�L�o�a�d�i�n�g����2�.�3� �L�o�a�d�i�n�g������<�s�i�g�n�a�l�.�h�t�m�l�#�F�u�n�c�t�i�o�n�-�R�e�f�e�r�e�n�c�e���(�3� �F�u�n�c�t�i�o�n� �R�e�f�e�r�e�n�c�e������&�s�i�g�n�a�l�.�h�t�m�l�#�S�i�g�n�a�l�s����3�.�1� �S�i�g�n�a�l�s������$�s�i�g�n�a�l�.�h�t�m�l�#�b�u�f�f�e�r����3�.�1�.�1� �b�u�f�f�e�r������"�s�i�g�n�a�l�.�h�t�m�l�#�c�h�i�r�p����3�.�1�.�2� �c�h�i�r�p������(�s�i�g�n�a�l�.�h�t�m�l�#�c�m�o�r�w�a�v�f����3�.�1�.�3� �c�m�o�r�w�a�v�f������"�s�i�g�n�a�l�.�h�t�m�l�#�d�i�r�i�c����3�.�1�.�4� �d�i�r�i�c������(�s�i�g�n�a�l�.�h�t�m�l�#�g�a�u�s�p�u�l�s����3�.�1�.�5� �g�a�u�s�p�u�l�s������*�s�i�g�n�a�l�.�h�t�m�l�#�g�m�o�n�o�p�u�l�s����3�.�1�.�6� �g�m�o�n�o�p�u�l�s������&�s�i�g�n�a�l�.�h�t�m�l�#�m�e�x�i�h�a�t����3�.�1�.�7� �m�e�x�i�h�a�t������(�s�i�g�n�a�l�.�h�t�m�l�#�m�e�y�e�r�a�u�x����3�.�1�.�8� �m�e�y�e�r�a�u�x������$�s�i�g�n�a�l�.�h�t�m�l�#�m�o�r�l�e�t����3�.�1�.�9� �m�o�r�l�e�t������(�s�i�g�n�a�l�.�h�t�m�l�#�p�u�l�s�t�r�a�n����3�.�1�.�1�0� �p�u�l�s�t�r�a�n������(�s�i�g�n�a�l�.�h�t�m�l�#�r�e�c�t�p�u�l�s����3�.�1�.�1�1� �r�e�c�t�p�u�l�s������(�s�i�g�n�a�l�.�h�t�m�l�#�s�a�w�t�o�o�t�h����3�.�1�.�1�2� �s�a�w�t�o�o�t�h������(�s�i�g�n�a�l�.�h�t�m�l�#�s�h�a�n�w�a�v�f����3�.�1�.�1�3� �s�h�a�n�w�a�v�f������*�s�i�g�n�a�l�.�h�t�m�l�#�s�h�i�f�t�d�a�t�a��� �3�.�1�.�1�4� �s�h�i�f�t�d�a�t�a������:�s�i�g�n�a�l�.�h�t�m�l�#�s�i�g�m�o�i�d�_�0�0�5�f�t�r�a�i�n���(�3�.�1�.�1�5� �s�i�g�m�o�i�d�_�t�r�a�i�n������(�s�i�g�n�a�l�.�h�t�m�l�#�s�p�e�c�g�r�a�m����3�.�1�.�1�6� �s�p�e�c�g�r�a�m������$�s�i�g�n�a�l�.�h�t�m�l�#�s�q�u�a�r�e����3�.�1�.�1�7� �s�q�u�a�r�e������&�s�i�g�n�a�l�.�h�t�m�l�#�t�r�i�p�u�l�s����3�.�1�.�1�8� �t�r�i�p�u�l�s������&�s�i�g�n�a�l�.�h�t�m�l�#�u�d�e�c�o�d�e����3�.�1�.�1�9� �u�d�e�c�o�d�e������&�s�i�g�n�a�l�.�h�t�m�l�#�u�e�n�c�o�d�e����3�.�1�.�2�0� �u�e�n�c�o�d�e������.�s�i�g�n�a�l�.�h�t�m�l�#�u�n�s�h�i�f�t�d�a�t�a���$�3�.�1�.�2�1� �u�n�s�h�i�f�t�d�a�t�a�������s�i�g�n�a�l�.�h�t�m�l�#�v�c�o����3�.�1�.�2�2� �v�c�o������<�s�i�g�n�a�l�.�h�t�m�l�#�S�i�g�n�a�l�-�M�e�a�s�u�r�e�m�e�n�t���,�3�.�2� �S�i�g�n�a�l� �M�e�a�s�u�r�e�m�e�n�t������*�s�i�g�n�a�l�.�h�t�m�l�#�f�i�n�d�p�e�a�k�s����3�.�2�.�1� �f�i�n�d�p�e�a�k�s������*�s�i�g�n�a�l�.�h�t�m�l�#�p�e�a�k�2�p�e�a�k����3�.�2�.�2� �p�e�a�k�2�p�e�a�k������(�s�i�g�n�a�l�.�h�t�m�l�#�p�e�a�k�2�r�m�s����3�.�2�.�3� �p�e�a�k�2�r�m�s�������s�i�g�n�a�l�.�h�t�m�l�#�r�m�s����3�.�2�.�4� �r�m�s������ �s�i�g�n�a�l�.�h�t�m�l�#�r�s�s�q����3�.�2�.�5� �r�s�s�q������N�s�i�g�n�a�l�.�h�t�m�l�#�C�o�r�r�e�l�a�t�i�o�n�-�a�n�d�-�C�o�n�v�o�l�u�t�i�o�n���>�3�.�3� �C�o�r�r�e�l�a�t�i�o�n� �a�n�d� �C�o�n�v�o�l�u�t�i�o�n������"�s�i�g�n�a�l�.�h�t�m�l�#�c�c�o�n�v����3�.�3�.�1� �c�c�o�n�v������&�s�i�g�n�a�l�.�h�t�m�l�#�c�o�n�v�m�t�x����3�.�3�.�2� �c�o�n�v�m�t�x������"�s�i�g�n�a�l�.�h�t�m�l�#�w�c�o�n�v����3�.�3�.�3� �w�c�o�n�v������"�s�i�g�n�a�l�.�h�t�m�l�#�x�c�o�r�r����3�.�3�.�4� �x�c�o�r�r������$�s�i�g�n�a�l�.�h�t�m�l�#�x�c�o�r�r�2����3�.�3�.�5� �x�c�o�r�r�2������ �s�i�g�n�a�l�.�h�t�m�l�#�x�c�o�v����3�.�3�.�6� �x�c�o�v������*�s�i�g�n�a�l�.�h�t�m�l�#�F�i�l�t�e�r�i�n�g����3�.�4� �F�i�l�t�e�r�i�n�g������(�s�i�g�n�a�l�.�h�t�m�l�#�f�i�l�t�f�i�l�t����3�.�4�.�1� �f�i�l�t�f�i�l�t������$�s�i�g�n�a�l�.�h�t�m�l�#�f�i�l�t�i�c����3�.�4�.�2� �f�i�l�t�i�c������(�s�i�g�n�a�l�.�h�t�m�l�#��� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���è�û è����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������‚%�„N��ßxœ½‘MnÂ0…÷>Å“P7($Aü6,«r'ÄVÛrL ­à,=KOV™HP•J́X̀ffô¾7󜧔z̃:M RI\OÖỤ́0©¸ Ểă“Ù%ï(ÏqBiÅú�e U#:«¹W$$µ„qÆ€Êjë Œ–‹U¹mPZ/ÈO₫ pd̀]ÍüæÍpú₫*yơÖx»3b¼ƒ½®_@µ¨—tvà¸Ê4̣tAíx©)­¸vWÉ?-0u}„(Ñó|=_ WܶÛ×ÙË2÷JY`çOv¼"ÁMÕg^|Ï]+j³l C{̣1 ej‹† yƒCºø¡̃ÿ{í#¢œ8Oµơ-ăsư'́;ƒë'�‡ÖP�Úăxœ́½ívÛF–(úOQÇY“&c"i˱­ue'J<+q|,÷¤»}¬"P$+Q0 IuÏ]çÎSÜ׸r䮽ë� €¤ÚTÚéX"]U»ªö÷Çéÿøî——ï₫₫æ{2I¦Á¹sªÿùy30Ÿ ä‡×%ïØœ‡#A¾íö]2I’H>?:ÍfƯq˜vE<>’b”̀h̀ơäét�"£₫¹s:e Å×:́cÊoμa¤ón±ÄS=HØ<9‚YœoBcÉ’³4u>8wŃü/¡7Œ\ñqH̉1¿¼"¸æ ‰ç+đ±Ó#ơ’£g̉);{à3éÅ<J¸sCoøÁyâ5[̀D́ˆÀÅL4öX')bÇ^:ea²ô¸Ïeóaº´ q †4Xzö²˜&"Î=8¥× ¶léÑÎf‘ˆ“Ü“3î'“3ŸƯpuđ—‡<á4èH́¬ÿ�pđđLb6:{đƠ;= 1 ÎÈ„0Ü‘³đùyñÑ_nX ƒêçC6Ï·ß;§2YŒ�nôñ¤| ­ăó›.›Ói0̣Ï)Ç<́l”<'º6ưoG&±Ç]Ÿ:°ḶÏ‘“ΈNy°xN¦"2¢;!øùŒññ$yN†"đơG’ß²ç$ ñ˜Åÿí¤AwJăëÎ0 –\&œ ñsâséư·ƒwá?7‹Ö8YLNƒ•¤±"ñÜtƠçôHƯ(çt(ü h8>{ÀBü.÷sêóâTʳ‰ˆ:»aA‡Íaî[üOú¹ÇÔ7êävÔíèû`éâéO&ưsç4:)¢E ¸"ÿßÿK̃MÑ¿‰Å̀KÈw0±Xçô(Âw̃°xÊ¥ä"$\’qLC 8‰ p }bO6#7,̉„O‰'"Î$#’L¸$S¦4 Q,n¸¯O<¢'„{̀Xøt” ©¾"4f$™dñ ó‰ =Fwƒ©ÂPËS Ÿ8óaÎđÊÊdÓĐg±ièóŸ‰ØÉ/rÁñ›_Mđ&<f$f2 ‰ÏbsŸ‰øf—ÍÄÏ”°x¡Î*¸P=À’p¦"dw]~ÓP4)[9Ah(’ ‹ñđ¦t̀Ül›e´¬"TOítŸº7¡QÂâ’ă§“Á̉óÅG:ưç}b₫:= ÎSj^á¡Ïæ&ñ¢Ă}ơ¦ú,âôˆÂ Îá",~ ¥”‡’¨‹ ́1)a#!ézAêĂ#$,Æs0ă¡/fđ¡ÆvĐ¥¡‡hêê­B„ùüfS¼¼ eBƒ€‡ă ưN (Œ\ƒ¥̣�g’}‡³ÔßmÁªÉÔásÊ„ áê]æuÙYˆă«c:d$•̀ïÚư*! ‹ïñœ̉á06ó¤^,ÂÅôÁù¯ÿzzßœªæó˜yI° £XL5ïŒD<f®"‡|ÉpJÿ+nª́è9 Ö-½öà|Đíư¤™íéÑäÑf(]q ‘8 CØ+ø.’ˆz×t̀È”. bFưES.̃ü ó®ÄóƠk ë‰b¶ôi'ÙHÄS$̀p] 0M}�X̀Îơ.;ËƠè̀O%&ógts$æüưÊ“ ¡!P4‡ /v¨"ô†̣€¦đ©O¬AëÊÁƒCääI=˜02A î½'¦S8Ú3L6?ª ́(Ñs+ß'u70™€hè̀èµâ ÜÙ@/f¡¾¤°2‹‘́₫ŒbÆ%s 爌L῭Pæ!̣Ơ+îñ:y¼~œ*dvúƯÇƯ'Ư„ÆƯñí.7à§ù.;₫ÈO–&oxö*áÓèü-ÓØ˜”f[§,™₫âÈí7°4"bdñ1á‰̀x—ëäφ¡çz³CB!¨o����� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ����ù¹����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� !!signal.csssignal.css> #gsignal.htmlOctave Signal - Signal Toolkit for GNU octave ���÷�÷���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� doc ���î�î������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������!qchVersion1.0���6¬ ºàêÎsŤDHơ&³ ÉPv*c̉ÛđêK±Î[6b1 =VçWưˆ˜Ï‰ư|s₫\6Í›—%±ê3ª¨¡,?£ù'p¾Ư¾&Ÿró#kGPG6?«tX=±a:±çơxơœK·OÔS§G“Ç›MÆ@Ơs ̀#ˤă³¨}#PàNưÄ|™}¼©3xp~*#Ú]§ ‹x°œÛí½ä{NNàÑóSOø,\ÎOo¨=¾74~p¾8=º¡ñ99;=‚7ÎÉ©R—ó¯‚ÖüàÜ A}NVF€¿;4£ÁB>8o­ 6Wƒ¹då›°̣›¨̣%ê»¶û鑟”#uNp‚S¿S‡çGÍáù}¢KÖq»~…ö²?_OXđèd₫ùit₫Áj´¥ÇŸ&”Œb:e]Tú-< ô…!á÷lVj̣4f††Ûk‘€Ø¤.ĂêñÔ'¦03§¡Ä|5B&Bù~°°X˜N‡,n+‰[qŸXø©Ç|5–Ö̀%hÄ4$‘<á7̀A‰p̀brCƒT™1 ûi|“ÉE%“»-hä¾É„†•wGÙ dÄ<Đœ%®µ́17,hä!Kf 7y"H§¡Ỵ́¶úlDÓ Ñ+£Ê{ ¸è­_=É…ơ½Rƒ{Tâ44Ó¬» FÆcM ”Ü0/¸} ÇÉÄ©œ«P†°[„c̣u,?¦â$> èBÿƠ%¯J› [¯Gt•Î 6 ‚´½IÀ&`OxÉö lDäG„~€-™Ú 3[]Zafë—ÍXO¸z{ơ¬â‰8f2¡/•©hư»ú̉æto³Ï¡̃f<—ëöÙÜ!Ưsx{pÉœrÓ©¾WHÔéÚÿjM@[@ƒ¶•‘rq¹)5XÊVºzwÀU³HGà’åܲXH̉êWóEC»s“Ë.“ˆI£X©ÙêËzäJø]¾‹Äđ€‘&QX:_2“åQßר!j‰Àc­t®l_êT— T´“™Đc;9&SÅ<ÍéÙ”r4q($TÆP$J]£Ó!^Ç,ḶƒÛü‰_3¥†\…ơ×/s{pS0O;Æ0…ç‚’Q¤ ·€fXÎ@ῆ}ă�y˜TjÆÄĂqn[Ơ®–é‘ủ°7áqT/ >´¹,¬aî. # ж—Đª&½”äÙ¦äOµ¸;‰ù{_\É…ơ]÷ÄîϹ’~£(yü'BIÙ[Íbëøß[%_É X£¸|̣—åfˆ •˜öQ^øä0B4z3øpù”•̀RË„\ß@c³) ½…CäŒEàl<ddFo¬²¡]¦ye:L4f€b`nByq± ¾Ù‰Â�v₫ÉY¼'=̣ă-ù°¤ÙÁH¥Õ“>‘̀[eT¥lb ho³¹åÎI0~ÍF3Æ"‡bÔ±€‡ŒÆú‚?£V̉&g¤5êwF½ö7­ä(é·ÉC2êå_ü˜R?¦ ÷²wK_üm°̣j Æ4æÉd½œ½z4êµÓc~/®Y|îŸ9á£ñzÖ+U2.EL´q¾̃˜Ÿût‹Dȵö}´}Œc:%-u|[ï{Ï{Ư^¯ÿüøC»}BÈWV7S¡¹‘^§ßëưx .§Xg ¡ơ?¸äq¯ç’>₫¯ç’¯?¦"Éí₫ÙnŸ8D4ô¥—ŸSÿèi¯×{Pđ̣À%Çü~)0.çÛ'EÎoñjD"%3&`¡ăh uüˆ:—°å.zb >F³ 9䈔çdA΀îÖ€|C"N¾QxL̉€pNqçós»³ú1ñŒ̃Œê5GÄ<·…b!7 ‡hXwSE65G’Wr¢ùæ&á U;°à`X9•´ú«jƒ₫¨ú¥‘WÅa1̃l¥=ÁŸE 1xÀ–́¬û<æ^ưù{Lđ¡ÍŸ†¹ûÉC@M»|A ¸‚ªÎÚ#€S˜Àî·rf»Y·úëÁùc„R<Ïf.yè¹dLS¥‰%é,"™́|” ÈúÓtl‡̃ü@ew?SÖ« `”±¸9 ÷k“¸Ù‚ỗm zSm%_ g5”L僶øM¥ä4„˜×4À ÉĂT îCY€`̣®oT–;¸Ñ&ï@aˆàu „8*:˜Ä~Ù Bxưz:ø„Ø· „́(¡v(¤0ĂGw;Ië-K̉X¹eÆÙáTÓa;‰)›ó MêÄ·D?¶ùq°pw? Ô½ñ->—ˆ¿VRû™Í9¸~Á Ö”¤>e Ót^óÜ6ÇÈ@nâ)XBS2d́.¸o°ë ›ư&4ó€Óx±$­ïrP÷«?�ψzj‹í×PØ|„t?hˆF̉á’fơ|#ñ¬‰ǘYÑhóó“̃ưXB>2d́E”ö«…́4´bvÙâÖzEîa¨wŸ ¹QCzŸÅçaè}ŸŸ%ß\ʦQ}§0'T—|¥RWê<¹V7ÇpJå“]œÉtÚBÔJún·Ûm·1„ ³Bü.°Q]·™̉$æst®Î„Ô‰v*t̉Ä̃ª1ŒĐ$6‹ÜO"ô¥§ÀÀ“Ôg„ºø¨ưÆLª0!—ṿ2`4.Ê\Y8¥ÁÈl½ ¡Ç¢D"iÑÊĐuÈE¸ lÄ4ƒ2æë�6\’fHèx¬RfṬr.¹ëû¼ïï®y<d$Éé÷{ƒcôéÑxÈ“dKe&!°yơà©^ư¬_iCJSŸ›‘3‚~½“ÜsXé�Ñ'SǗ M£@$¤eÎ<i;o$Ÿ÷ J₫̃S¿+ß±¨¨¿\2k»d$—\yƉ¹TŒú*ü̉¢k€cÉ„›úơ2Ë“s<_J̉2®Î>ùñ¶í›¹ edZÊÔC ` ߤ‰>Jêtv FÎfàU™Đ…4鉘̉Q•èTi8f6Â`¾£’N(Ós–$(­K†i’Kí£á¢ü]uŒUư“m0¨ïïơªC¶ÉQÜà8ÅÜ£q«ßSNëº# ûÔï‘ëo·9œ3t[÷z¥§qÁÚ÷5‚ußZ7¬3Đ» ÖÖÖ2Àíaqsrq“¸)‘6´ÑĂ, tE@c}!Î['$,¾¡y¿{ ¡ V °ö«¶ëlã'6)•l”6M$£v%1䙄¦s€wỢ°t‘,Ö%Vpyr;Zy§h}pñGG£̃ É|tÔïi$AÍz̀&’¨Ơ:¤‚p>>ơ,åTTñơđœí\1™#:sÊ4å1®í5´y`}à›Óæ ôî´ÙÀ:Úœ!ă�h³ÅÍaĐæ&qSF›áön@ŸAs1SA!’1sá—CËf‡ô3àS¨OP̣đĂ₫Q§oɦƠyXÀ”.T–¶ê­Y™ö Lª!M%³éÙ<Ú°ti}»*T́l.¨£$|ÁĂdđK˜›°XéÈS:çÓtJ¸Äôº‚äíÅPDjãÔÏ)Ëܳ“/σ²_ó”}ÿ)É7S¬Cù‡ ’bƯJŸöÙÆsÍMµ4 1?ׂŒP6o7g\‰¸™{.·²ä.¯^÷Ø-ÊăüƠIhèÓØFcdœ|”ùFC@~9n¾ êZB¯¼Mµ%ÏêdW·1ÏœĐp}$iÿ1nÁé,è8†u/\Dª₫¤¡¤W†`kÈÇ„±đXºæ>&öÉm¡̃Ä9ÔÀö{E`1Fµ^¹ÍѳøÙá́ñ _ăöB˜EWƒRØÁ¢«̀ ϧ5wë s@0£º(°xX[Ë;e!#«+P¶ñ»D»¥¡EĐîwœ§‚û¿÷zÇ#ÔI×Üơcb̃À§·¸ï«5pï—î÷₫½b5¡j‹³]Dß^Ô´\WûâJƲ”¨Œbdö<+vơZC®2 §i¬̀Ưb¤ ó,ÔeP땇º²`ưºù̃ŬT}É?›¯”¡µ”LhfƯqjô鉔IÂVYÀJĐjá«O%g½n?¯{0(6Rứ±~V•3)·vQ-î>‡ô·÷½ndăL¦Ö‰̉JfßuñÇt¡ ;ølÄC]p'æ̉ÔB™²x| ¥&ÊÓ*c~ÿÀu˜@mØ[¦<h́#”ÍU¾ÇỤ̂+Åí̀úü†û�AĂ—Xï8ÆN]̣´âªÚ(˜ñ$™ó…çCy ùº%U7ƯVä1k•Ç^©`2ơ&ˆÓ²=ư;9M“´®Ú+JĐÛ´T¡ơÙT,“\«cJ1e&Ñ6L%³Œ—óJvà:—p {xb“·à t AĂj¶̀F¶¦æ£·̃̀-¶Ñä7’»ûâ­¸ñi¿Ïx‹—FËn|v¼”T¡èsÓhk´₫Æ¡£­¬d™ªùÔ4ZïTcSiüªÚrRùÍÅ(ﲋƠå(¢7€'±À́|c‘×qZU'Ad6¼‰ˆ"eᘪ]Èk’­m_‹/Ơ§¥U”æÔ[�ZUáÚQ½Àï©SJ¬Ôñ,Ë=¾¼|§'kx4hGɃ\’Áñp¶ºw2RÇü†…h-Ö„D·)Œ†ØTr£¥^Ưz„J{Ö߇t‹¡}A€Ơ3`!'ă–bơ±†e’[¸«¢Xă`’«w{‰.M¶¤Bb₫v.á"«ü)¨¶n™zجÊ|æOFb5…Î́¢4.ËDY}¬V×V ÏGƒ2c(–Ḳ) _o7îpî~¨î Æ_u ɪ«¯"ê*;;ªQ‰2ŒêÑô//ß¹Đ*ƠLjÅDÜcƠdDC˧â1™«,©Za( *°–é<Wù+WÉhƒV;ˬëABæPdjƒdåJÜ;p{:� p×Ơå<PÁïu{=ƒ2€xÑ.|¹”gƠe£̀²Ÿ¯lˆ »añBÅ;b)à’ôU!D&,:óZƒ̃7—̣¨ßS3@°÷ê€ ›¯azd*ñuu€~/á+¬²3•Ê>¨S#j~Ñ»dđôÄlĐRO´]r)MCóo&Ù>qđơ¯¾"WcÚç©Ï>~ó~/ g„¦P˽]~çáïđGD“IK…p(ütgôÆÖn ”ÔçXº’Y¼32âóÖq/uˆ9.âEx\À́Wäq)^F£$$g%(ÙÁgdÂÇèÀ‰™¢dµî+—Œ\’ÀÊóÈ€uè„w¯�[CÙºj Ăóß<îơzG—̉}®°2¥ăP…"óPzö¾’“üç &?̃v-¨«£���)·®Zøv₫L†p4|XˆRèj™t®Kâ¿È !]ü­ƠyÜ;ê÷įˆp ÙP³óxéÚwÙẀ;ªùPç‘}…Oé˜A¹ñˆqëʾbđpè43&Ø�M –ÖØ£&<háóØ„©ƠZơÙ:Á%ƠÜé/‹¿èæ2Êa®‰S Ÿd_T•₫A‹ÍDÀa#sẠ̀) „ŒöBŸ¹�ÛÆb™#¸6£¬0“Kàú–ƒË 䩈¡ùF<!÷ÀàHy�₫Ü€AÄ{Hcàú zĂbÀb$·ü"{,\ŒG›Bơ"™Ä©Q•-Ê–Ô¸q6 âÅ\u°’‚";„JwÆ‚aÇ*°‚  ÷P„6‹n»‚rUË:§ơ@IO!ßđó6V^E Ù̀DÄüÚ;ê0˜¹æ¨P—|§ Đ+.`,ñ&P!Ö±ú;à¹1“PëY}©#VØ”%×fÅl?Uœ´bÀ?ºë `‹O¡«2Û-„Ê6pLđ ŸFBÚèi»ùˆˆ>÷ƒ¤JIÀ“$`dÈ×!>‹˜â«¿vÏ"-‘¡ê4FŒ^÷ÓR雳ßÛ’ÀZX¹¼hkK‘›~ˆ*óPÎÂWê,g›{yùÎ́b~Û ̣]س.!W,€k††[’½å1¶Ä̀ ­Å³áĂIüRß×é¹ĂUVr†£ÏB:µ́ÿ�³&3Ç3–oåÎ\ư?ŒÛ‘:x¢à±Y,8Y’pçÏ[îp_Œ`î°yˆ2A~îˆV¥̉SbƠfr1l°Ç¥í˦) VV¦]B.ч›‹5ạ̀(à̉Ánˆ4ö³.]zC3êoûºDç–ó´OVXG̃έ5ˆEH§Ü+æT<É€Î]qù,L,£|páYhN€Jà’‘Q  Ä;ÜŒd‘,„ÈSA\Tqh¸p–&¡;ö E’ˆ)æ¾d»>Hp½èµQö€Ë’Ơï†"uëô”‡X¥1†æq*áăïÏ:{₫‹.¹âS`–£wPH¼çÅ5›Ă‡Î9Çy»D 9b¤Edj£º–§óïÏ:üy¼w0Ǧaªé.1c€£¾)80r¬*¿«p)Á$¯á_/>¦ĐG,{p XĐ`´ª́*¥9wH°QÂbŸ¸$CTØ‘B“¦z€LHy‚Q�ëʸ4án%W ™¬R%´<ÑÛUÂƯC îT*JbN£ºÅëL][| ÓBVp*ÿ–zÇÂÀ&°z`"È5(" 9oûẵ8ö¼hMU[ס+åñêÈÔ6”&€Ô³"̉œ•ư}?åᥠGæ̣ƒB¹'̉À_­Tˆ 'ZÈ²ĂÆư9–±$_“<]—äk:NȈ ,pKH‡BqR<À]‰° 뛉†Đtă†Æ Ơ5L}ïØ«à )†JïC8t +v¤™ Qi¹?FëˆÁp[È.¹pÈ$e+°-è?Xp'̣FƒǺ-Ÿ{Ö¬xKÂXæsIè¸*5¯q8dUÖ�-Å:ö‚£�³.€_̃À!–χ3jvóÂ<™3 eçÜî(QZK̉£€G©ßBºÅư9(æ̣ïâZû˜̉˜­q¬}KÔc[¸Ơ4Øœji¯Ñ́Æè·YV£a?‰ºi²hÊ®¶Ï0÷Ï´uiFj¤åö„çăÔ1(½><7Û ¸óÅÈ\ndñØcaB5“ÅJÈ@Ap—Z}¡úרÑså0!m‡§`‡ˆs$ áÚ©–™]ưêÓù¬E¨_Ărˆ·đFÎHgåÇ©ñˆ‘ZœÖ ·LÈñD®(¤ …ÙKÈÑpÖĐ®§f¼Í‰—¼;ở $Çbâ�rq f#§Àl%ygœF‰O‚³²F×lĂ´Ó\FÆ¿YÖi ̉t 6L+1Ö’N×¾k…d­`Ç Ü0ÔcÊj €-*W»�3Zº`i hBƠ=>-'¨› ™H«Ă¼Îz@¥¡ Œâ¶ÎRG±|ǽ/ù¹åù¹ún‚ô\“ ¼³8úLƯ›ZqàÑÏm.XÀ»‹Ô^Å‘&“p‹‹ưd:4xgжOYáđĐṾÍMĂƯ§ qŸZ”6 Ĭ"HR÷_Wˆê[±,¿�̀<ÂgwJ¯É¿º 5TpÖ´#́™ñ¶ †pÔP:jhpqàÔP£í`¨á'AÛ>©¡FèÁPĂÏŒĐ2‹CVYơï4:ÿŸ) pvk×QL°ôæúTg3ªàÍÁoU3%pE_‘ÖÉ;ÑVÅev§­á†ÉɃ~>]r 6 œ·÷åÍCœ ˜ÙÏI‡Ùê#Ë ®(ă%₫™ê™ó?/å¿nÙ0§±äÙO¬9}ră‰ÍOÜư´ƯxbÍ)[w°œ\Ù^2jZ’ŒÊ˜Ơ³ïƒÂÑêMMk®ƯhJMeŒ-¨*K`À8Q.~´ûéñ P_$ùæù̀Ưá¢*ơTOFYƯhæÏÏÀTN2ç%ØR›‰R{?x¦*3¾î Ó@—Ôøª`¦ÑÑóÔ±ª8'¬ÑéƒÛ»ß%Yå—NŸL e»î’ñR3–-KSCíAv´5-‹ăÆßT¾̉uœÓ#XCÙ:̀C¤C^̉8†ø©,Úªî=i߻ʇTÔ¾³Ù9#ri7S÷6¦ĐªÜ~]=̀Qª›i₫‚¨ÜiKvxåo;¾Ú‘̣~gd¾„ÚW’ú+„Úù™Q™Æh…EÊÿhéͪ‡?êˆú†ä¾9=<ÚŒ9”MAó ùƠˆ‡>Æ'Öq­A·Óƒ›³®́Ư˜¶çÂB×Ơ s¨fBXNzs1+‡ÍX’̉á}zT`MîÛ¾bà— ™1Ø~L¸@™Vt¼qä5¨¬~:ä)Âw"́û̀×ưe¢À%>¥"K+ÛØ#™1é7êi¨ÿ ÉÑs¥´O1RüÂ.T|¿O00 â˜1T“vÉ%„”û8»„éá;Ú»À7ƠƒÖf†ˆhœ Å€SjºB6¦önƯ@¿`sˆ4S’XgÔâÀdZ9º\D±^…ơªPBŸm‡ºsî4ˆ_Mg³ô©«Ëzøl¾ä䱯Æ*çë[¬‚³$­¸€dÂc9#Ï”¸ÓÉ ZḤ} k¨Ø°\Û»´—»:^éPèä‘Â»È !Æó©_¢dĽ)˜¨j ˜Óơ3 ́M Fœ¾4~®₫Á#¢§™x hÈß)~cæc’ ÙhÄ=OŸ`ÑÅq̀à$‹PL9 œÜ fX4É̀“˜eG×ú¿UJÈu R/5_¯#‡Å ƒÎ$ ˜LøcăƠc+®êœµ U7ä…?sL¦bC*T—¬˜…ú¤a°¿·ÉjÀ­Î ÖîÑÀS}#燃UL¥Ç¥Ô®w… u©pÄvqÚ«ÇÏQç¯|%PZˆß2Èß‘Ú-L¥%t$38ä:Ê¿ËWj±­, Oë(RQ«YṕUˆÙ&đge₫±êư¬ăôÑ·¯7±°c (×̉¸Ư%¿@dµZ3ª†lîalùr%Ôl1{˜¡麢₫:u ă ¡Ÿiµ/ ⤂gA^R>ª $€ƒEr)yé¸h¼|§½ö5˜‘ ÎǸö[vØTvÿÓ£Ń�›u_V!TÑ<às10CĂn ]Ë=«ÚZR�nx‚ñ'ØBAÄ>äYd·ơ6ÁÉƠäA3 < :cf$ư¡$b#ƯŸB° îé4|]Z*„£1ñcÄu6¿­T`}5î:K[ׯß_a¶5{cKhW²/ï&¹₫9¶+åTfpZÆy’åÅ›"X¸YN>æ%¤†¢åD<Mªh@y )%ß–‚̉!ó^û·„¦˜°è\± jâ_[ =zĂ“…]—™;ܬyÉøHÙ|s¬Óy-ÖuZÍz¬/XrC_…£úºrí‹d:%ÎRPUÑLÓ&kI–€©u€«Ùbæt ŒĐ$ÿ (;àùQñ¨�3ö1å74�!JQi cĐ!¦:²"%C¢¤ËLÅM­b4,g%ŦSúº^XNEđl­0ÆơÂvoAÈèơ�₫SoMûà=3Ø 4!4À$8‡¨'–aç0â€ÅÎÖµ_óu•}>±˜åƒụ̀µâ­¶™N@Y¨*¸ª€ÍW,Ú%"î<SG©îĂæbVuÉ´l·4Ưh ¦¤d.Ô~§³!ílYsƠY„JÀ¢AM¥œ¬|mV‘G…Ú€gM ­BAEÀ½‹KnJç.à̉U´"J—¨ÿHù±BO×X=Ù±·$S¹!*O%Q!CÆ¡Đ(ÀÍ‘¨†p³…B}ÄÈǼ$eتD"é€DÑ1éQ­·?_µ‹¢HU9Ôf2›#̃IDçíÏWz †’9«¤́>S2øO“¤l-{L¶"` Ñ®Ă![‡B±‡XZ">ölKũ•â2çMP:wnˆOeIM;s( œÇÿ|û´úG¯ÉƠ_₫WNºÅÛ¿ Ú¥=R·'œ+k.‘ûœ{I-äŸ`dÅÇ‚́'áo™N› ™R~¬§™Ç8̃D!6@5¥üx(dptpr „³!œ́N9e:툑¾ü’´̃^íB<— 5K?¥ü¸ ưÔÄsiÍNú‰ô¥ÍU¢y׸§—°¦B¹:4ô;/Ex£ËµƠ@Ơ¼¥"¡‘Ü#(ëçÙ<$ªvvÛÅFyP/¦O<êö >´9£Đ0wçh¯¬ÂÛ˜,j́@i%]\ÛAmg₫¢0¹OsP˜\Ë_0RSt^Ǧé{ÙªIf·1,e¥Œ‡æËØT˜VdT–?kK£§$±®€“ŸaiÀ&së–³™@Í4¨8 ~'×A/•2…è+¹́•ơ±+w¬M’ªG̀Ö‘1-…\GÇ%èÙ2èàb—0tÛª®Ÿå;¨“́¥ h.ÍÏ1iơŸ\̉₫¸µl¾/âø„>!ä1!ä[B ¶!OË Áîo>.,Mé ̀åñ§ŸÇjPÓ@r?ŒçâMÆ—U'€7Mæơ\q@ôc[đE·Ψ@5ÛïÇ.h/¤¹‚•©tær†®XµÔ_Jáæ•Ï;5„PÉ á_%m;wYrY‹`=]SbÅ ¬jê‡<¹ßâÏs_âúH:i)å†á¶YÛ’æ«"Mr>: 9d Åu-Œ™1U‹»ÉljàÜÔ“z3”¦0ọåDBJ>„ÏTbt­^j«©Bc»���úĂ”)8œ¤*ë§›8F•£}Cv8aËLjçXå6û]­»/á¯ÙíI¶±q­WX‘Ùv ˬ)…e¶w…es;Îlg1¦°î₫W÷ÙYg™í]g¹?È,Í"¦QEṛÔ~ç;(D;è|W¡Û”_V•mh—ª‹S•†ØÖ¬±¬¶ˆt̃¥id1oỚ1ß Xe‘bk»×ZX£X/—ÂÚOéphߢ^,ÂÅôÁùå«·§GđÍ9´± §f¬Ü®,5W¦+j«Ø$x·X”.Y¡_u…ÎG+ÓÙAhCg=]~Lđ¡Í鲆¹;]F@ûMª{[RGÇ›'Íi mNhVÇû›¦j;`…µÏ“+×JväïÍbèó$Äm¡TÂ)ÛcÚVîÔ’ó°°‚…ƠkX́÷:‚^+l±²ăe¶ùœ*—… #¹çÈÛßç‹Ö5ú¶Œ^b;ÄU^ïRƠåïÆXˆ0J¡¿gº˜b”¿›åHĐ4KóçUyÉƯºÀ–èX’묀5TIÈÜF*¤]:[Ÿº̀ đ·œ.æXGW̃‰U¦ç̃2ë1ª&O$ Fªư#vÔ bâ¯~Ă•ÍPe"cj[•n·ĐŸ´ 3S+¯Ûˆ¬€ơC×ú!ă1ƒ́™ÆÍ•¹Ÿ×=rgà>#óßÿÉ^ÿ7Hh´¿s(2›ưđ³~¹ÑĐdf`(̃rLZ¹d̃êôÛ.Y´^?́·Û°JhëÔ%¯…º̣ÄrcêXE»Â 6zé’wÂ::©Ṣ0¦ILrI(çˆƯ"p™pªƒ³•Ô N0÷ÄÍJ Ç 9íâíưùû×ï®î&©ư­DR{hl%‹̀¯YW7u<Y? ú—“Hª.~qœ%àvb¹q.-ơ< oR³Œv Û¦˜ÂgPw5bÜ>I¹K Za&j́n¥ KÈ̉±^&u5Td%A§–{¬S‚táDŸ: chŸ¥Çù«ÖỤ̀ºÓwuÎ́kkÏ3]®L(,̉—̣̉MØF%×(ÙnW'Û>¬Ø^†—¤ËoŒÆ»-bÑ›Đ˜z°P™Ä<Xj›h�`&[²jmÇĐ Ûúú´́ưiw‘†�áyƯƠư:Sqr U|, ÓèÁy(B¨™G§Ñù×±z(?ÿ,²Á"ưü”\̣Ö]R+«‡r*¡̃&ƒ©gMS?—¼=z½ù@i¸ÍPæéÜ`­ëöQëuç_×ÿjo>*f›EÊzŒm6"°º=,ºOek̃îÂ?‹vpVx¯&»9öưzé[ÅÀk‰Åú«lúJ†YZh͉j2U'Zu 4½ë°7œ5óê¹Ñj‘*Çc« C€W'RjXo«xûư»¿¾}ưưwä¿.̃¾ºxñÓ÷wd†oKn¿­¢Q&‡Éuö˜rºœó�,F±ơ}GQôçêŸùë¹ ¥sĂ °,uĹL>wH«ß&/«…̀:R\KÇÁÑ¢%ÓL~i Úäb‰íå‡ÊqĐzè™î₫¨½V~·âû[ü34‚ĂRư‹‰.—Åm²µ̣́]NŒ7R<ù‰¡E0ˆœ ËÄÑ•L·Ú·¸IƒoÔN?́+6ËóÛÀ¶Vă!¹&‹æ‰ JRoù vÛNƯÙVÂBÄYüQGlêüLo[×Í¢Ü7ß´x§ß~øG›œé9,»ŒŒJr kY¾Øó´v´çKƒ ÔƠú[ë¹ËÛ.üóG»½*R¯BP[o[×îó¶ûÆ}c^³H[¹0úÁ J ₫ !Ç̃Î[êÀÎQˆA½…ôX¡m°¥‰tĐ˜tĐlDYÍîÍ¥w³fîy›‡²Ưuáw2R6·đ¬lù¸½Áw%×_ŒđÊ:álW«ë3†ư«³–lÚ !7̉&íNó.뺵±ˆ̃’x̣êĂRê7RÊQÛ¹=p‹]ÈËU+Û#¹wɪaJN€L²IÅL%--9· Çáµ0“©*Ơ„HIÑŒ+X¤Ô¤³’©ëÚFIÏt[°©ơVà̃© å&àE'Ë›vJê´@”Œ¤t ¯B‡V«4Ú×k.®Öç7[€£Pe&`ZÙ¯ÊaÑj<eø‰bá§^™µz£€YSÛÇô¹FÑ̀1ó©X4jyơ+ΔÈ2ªÛEÖđ¾Gú¬\¨‹eaèØJưZZ¥nâÓ%^̃íƒc.1p•DĐ„ô±&jæ QVÏ-$Fbf�Î}qÍn²_Ïl£‘1Û9ØÁÂư²7ŸÏ-»~>¡Wöæó9eĂɦ̉¢'@ÿWơæ´ˆTjóÎY|·æ˜bÜ·Ư…úmÑnèÖJ*9q̣ ë¬TeÎ>*5-³‹3fƒ¿!‹ư»ë(KÈŒK–¹ÉP<µ¯ˆùÛÚ@¦JŸF±+1”,«î ¿l6ÈÏ5…ûÏĂNÿĂúx*Øîç+ÓØÖB¿Ö–=B/˜AÑYLg ËK�ëx@Ç[ÛÇ·¥x`³z[Œ¸Æ·±:`SµµGë�ëMÓosuˆsK¶9¯°p“ù\)˜úœLAÊÅyÓ±¼«­¨L\»k"ê%†r¬2íÔ>£’LûÁæ)¥¹q¶-®$đ¿:ạ́1ÖÖWÏmSZß@n¢²¾‚u ±Ù2v0Ugnœµ‘]88ä—"ÑØ×5ˆT "öª¼L*hT|D ܯhB%Dqp™ẹ̀<LP%Tq?¼ ( ©ácL¤cˆÆQî,]àM ¶TQ:—dæ̃F±đ˜Äê•4Ñ4Ă–ñé£2`¢Đ!x¹§Ë0Á$ͼuƯpŒYañˆy‰̣ú­hơÊ€áAAu)£ÁẦK&""Cæü!:ï°ñ̃¾ï‡.¡Άi’°¸ơÈ%½n¿}BV~¾"ÇäÇ[ˆYïI ›ïó^·×̃ïöJ^´ï÷M‘]Ơ Ø!ó3ÉĂÖà›ˆ“|3è>j?́uÇßÄ4ôĂÔÄm%í6ö†ªr?̃BYßT î? D.È™%­¡KƯyû„ÜêYl?ú ­L ;gh!ÜJܹû—L9ù‹›¸ ÷/'~p«?`ñÉ_52²{Wåàr¯Â ˆzj;úP›¡nÜÛ+m»mEÜ�Ÿ˜´-̉“42÷™wro¹-¹b`=ä ”âÚÁó!7À)4;1åƒUưhưưíH51°¹€ÊnŒæ¸™éº.†à*†ØQ,¦Yơc X FT&*_’9̉uƠæA’EÁ0n‚7Ơ3 ăˆÖéø2áÊ /ç�9Èà₫ß0È9´NæÍ ¡;^åçv̀99#ï1b"m̉ívá·pØ₫à’pHÎLvü°Ưé+‚ù~Ï/́ó‹V'¤ø<ͧíN!`O<o$'á³ÙêØKQß$f.Ô£´êQüv¤ 6÷ZÀ‹\²PéƯ¯–÷]æwTè%¡*uñƯ ³æ0,\Uw�ŒÓyM̀ÍÄêfä’ùî“Z¶d»e§̀‡™ôë9Ë#bÛœ·dwç.Ö½w—³ơï¥,USEV,¢vk°xđˆrÉû²ö•Ơ½îÈzî!²Ûí–`å5}ưûÈZ̉ʺxA{¡°ÂÊ«ØêèEe…³ {ó9 Ô ú:†¾˜©&e®DŚ%-Ă_}Tư0ñâ®îS…q”A×¹,Ë 1ăœ‘Áôa¿ZÆhq¥×S6k["­3}ÎNÛ ể́ ~{)?D7đÑÚ$h’"†R9âFë̀Hm „ó«'‰³„ *|Ô±ƠÖS)Y(o€5F"a÷ơq́̉²=®œ|s+>Èụ̈3M:´®W0Ị̂ƯúiÈTƯŸ`,bL¦ƯvuA¤âñ6û%1 1̉Đܼ̣P-zAê³Üs­œ °Ưu^´h²~”cÀ¯₫¾ÎÅ ¨^̀Ẉc‚íKàÂ8CƠ&w$LŒ®ó‹1b»Q_±\Ü" qÓ æNƠkúº¦ TáögMe%™ˆ™ék‚ŒSîi21ßÈ%£Êªûªèæ ø]çUR³EIœ†@aë÷d¯ˆúwØ eø¸CÙ¨ø½Ú ëØbZB2¡µ†è%˜è…‰BöŸWƠ›2Lưœ‹«Uå=Vö±s]âà%é@¥“XµNIa; ÊUTëNöfcPÓk°s¤€êIJ¦âöăîcbÜB,Í`7 —`ûˆ§̉pĂ•ïf›Gä°Ơ€lV5“Ơ/b¯ê›KƯeñ¬_îH5ƯéôF¨Z_(›¯e—…>—–a5ÏK[ îêZ &ªïöTpßÜe1̉–ªÖªË—rÉ>-¹Ufåª4‘m®—L˜dYƒ/ĂƠ)ßÍ˱ ]íÛm{̉U¢•´M ÎH^|(ieäûå—ïcDC“Ry'J¡ñû{SîL&äXt±̃ósL²'7'yè»S Úø̣(9€êÓ9üF¹fñS¦t5¹ĂîæöhFÉá´Áp¥{Ӳذæ±}üÛk°]̣M"›ßˆ'_6â06âÛ¨¨Ø§Âé±'nÖ±“‡dnLWĐU^/:?ÀsísµE$sÍyu·^´ZèlåĐ%!¾ÿ|=NNHÔ%äÅÂ\=R‰áYôp€™ágÑĂG` ‹°ëè ëÓwŒ¯ƠW¡ùTT¥ø³9ø̣”%lfơ¨tL%²”H́jsỆnlôŒR1 #ch¥K¡` “,Fơ ªXcê#Ø\!̃Â6Eđñ$§zÈ)¡•)y“ƒ©bD)6Ê=¶A:?Ă•̃€c¢¢GfL†˜åDHËK1‘₫Ñ£¶R°²Ó×»ä‘KÛ*¯}N/r/×J­jÇ$<LöQt[Å¿3½̉:vq®'Aï*^Z}·³́÷¾!Ă?{m—ä¾ûp¢ÂJH+[`ŸdŸŸ¨\đ¾²8&ô„´`�̉ê»Çí#˜ x ñ‰Ù³ ơ ”ó2{ß;)Ù°2sóÆĂቈù˜ƒ¡2êăöIU¶Bv×…\¯4>!ú±-4F·uQZ£+₫$¨±Çİ}r�ƒÈ¿rû ŒéȵZ7f×W¯̃jªÆw̉%h}‘%@Mr°ôb>TDV¥àa¢Yơ"ú‚1àæ¹i$ÜF…'Cá/ÎO“øü4# ÿIüó÷« _ô5ä•o.̀7N‡±†q”@@¯[=ͳÜ6câƒ[¨n~¯+ç÷ºj~Gjùđ $_³k“̉Ô%gäư°G†}2|0‡3ú6�r‘̉'´Ohc$bÇ©¾KXâéó2́¼äÖó£Ql8·���~­¤ơn¡Ö‹ ÉåÚ€kû¤ »>Öa×Ä|¼mđunäíC°Y ÉuTơXa«'· S4Đ› UTĐöjûi«�;ƒ’}Ù5—¨1·O#Ưáa®LsT£6×}đ¯ƒ25Zu¡(…b ˜$¦¯ŸyB£F˜ÖzY¦8$vc®Pmç®:­í¤»(Ï2(á껕Ëê’W¨ÓøjúE€_Ç)´Çă!Vœ\¨% 3*U°áÈ„ơ×»̀TR¾0ÿœ!tÇóX”H‚ ,G+yÏëî =…Ä€cĐ²Ó¤Œ¥₫‚;Fŋدç9*,^Ä₫v á6ĂmD́ï•Ơ„[]lÄÄÁóÀÙ>™̀§Å™•ÆËIZ>qĐ®PO©œ¶*u¼†Ô9ëèU´Îb‡”Θ²yÙ­PÈ5±NA+£ÄiŸ˜V‰ØoœPǺcm4Ëq÷Ú×¶ˆdÑ0 Q�h¯j²ùeS8øÄÂܬ)Â…˜l´À×A!dU�“( !ËÙ†mƤ\É́4äEK¶.Z²VíÉæohĐzá₫ñͯíî‘ùûBưÙ=¦tz(t„cM]B•kp™ÜI h*ỪÑ>—Q@l5;rGJ2T&…Á‡BƠ¯}°ëÎ -†‡2¢#­K»¤?xöÓZgKfÑÌï½̃ñ°QOk«iüOnIpr#4Dy,Äf ÿåW¸Ăí™Ũ‘IẠ̊ H,̣ a[K'rMÿđIéír f“5Ö˜cÏlq�bÛ>›́×ö²Er#"`‡óÑXÎ'àdŸï'ÄIµ›·QlíÓV²?le……”g lÊÚGÖVö°ôé°2åa“HÙg\ѧC E"o¼¯+Áo›¼`û útX‹ïŒµ¢¸1zÙfN¡ü}0²µ:[—¿₫øs̀kP¼1TƠÀ:Ö§dôڱςú¾ÜE¥"ÎæÁ›AÁB»ô1ơê”MÍăSLœ/Zóöé›WÔô7.ßB9tƯÆ�Vù·t…sZlX[ ¨7ÔäVHZVŸvqeª­³²„^÷ª¡·z!Ê!WẨ‡ƠĐyË}ü±i|ĂêFiM9T[{¨F3x[­\[r”rÎVVÅ(Ñ¿t¢XŒx ç¯¬LM“ÇfBU<V¶·X KÈeÖÉ-ó"úÖ\¨ôbî«Y¾ƒë'vưưù³V{̃QyÓ‚'t¤ÂÉç!|¢N—aS~CÈLDƠ<×Nó¸® q 5]¿™t(1]Än檽j±l­Rf=̉ƒP1\ í›Áæ\&¤Åºă.™P$"„Ú€¶–„Đ¹›¶H…}ÓK21¿…̀¿�C¶6?B«—À!|î¡:IÙ‘S8r g©¯†{7ƠdG> è¢^=yB̀s›«(äƯƠk¿É]ƠiÙ[¤veˆÚƯP´³́`ñÖ :sđ¶G‡ˆÅhƒ*Ïa´¦ÖjSƒ ªG÷ ƒ†SÎ&"` ©V© ªWÛ uôù‘Z™{ÙrÔÂîrWŃ'Áwƒ÷ƒB4åư²|úïvbGŸ<k̉I² ÖvÊÁ” ‚đU„–rfúÑû±Kfà‡7Óh ±fZœ ‡È×ÉeæS\- 6ĤP÷²â­¥CƒT•æHÈq@h8†¬비Fm¦’yOåñ.™Ú̉-uH9vèü´9öf³ÙÿÊx#Á¹™BÛ5¬FÀ º+¼¹övúBøqđ(XÀˆ:ÀĂˆX̀…Dm•áaäÆ&#ٮżKkq¯1¯úÅĐ ïÖM„,D¬¢XÜôU…—ºfjnX;¹Âæ†e[« #*-øˆÖøUå¤È –wQÜdb‹9¥Aë1£₫b>erí„]]X±/ơ;.ÂLvu8ùÊóH îmqØQɰ—r·Q.åÑ`ư(%‹k`äuH­ ~FZ1…"HXK_¼öºÅ6ZH~œiñüx›m!v»]èU@7²›…N’—£±ôưËŸÚ!óÄf'„:î2|¬-™5¹™¢\…µDQ,¨7ảF¤B³É›+Ç*~"ĐÏ ¤B₫Án—^�·^+âF<{­”}K02$W¹ëVÈ~Ư%ăÖ ZÀwü#F̃ÓxüÏ[́·?fíÿ₫àS -Ö7½‰n•ähWú²]1Ăe‘ºêüIº&p«ö„œ4̀·ó‡:øc–”ÿqẸ̀}­�b³cç­[˜Ë‹Ö-D̃àï2¶†¿_“Ûß®ÛGđƠtW§̣B1¾±¹Tœ̀m…øƒ3CdÂDIGưƒÀWyß·+è]ưYExÉ|eÑWéP&<IŒ­8›C¦,VÈSŽœ~Ă\ÿ¬ŸøËç)¿brFüGđ¤qtQºÖ ̣bui¯…nmÖĐ&ê=S'YŸ­k§ ?º^Úº‹å'iîÉ’{�…¹$@Ê}—ï2B˜´ŒÄM¬iL§QFM/0$ª>å·‚#áh”@â7üÏÖ2v—c×´€¤+G¡¬fˆ_N…ïZCwđ(ˆ[ÿhÑv»Ưu”ô¡çೄ̣@ºPRÉ!“$‰y^<¥]™Đp$b¿ËüôèÿùCÈ#À}ôä+îÑà÷—øư ¥¿´´;I¦Á®AC|ƯÖ[å¿%đ̀æyqwk<ÀÙ¯%¾:l%Ù\³TÈ9�+<âk¯øƒÂ×­ïˆÉ½Z̃ï &÷hŸGïƠ6ïq\fwjʺ„è¿“¿)LU[•€…ÿ`Ú²̣i”’u¬iÇ›Ph±Ăb.î™̣ÆÔ„¶ÓÄ¥ 2dưT G¥E‡³[3‡ơȃ¦áä²W T…«Ó’.ÍĐcHÊHĹwáɰäI++C™sÔdÀÔ™zG•bÎUÁœ`¤èH*f>gij~ïô=ÿÂO„Aˆá3‡ Ù°Px@BíßÄ®(“T¥ŸAÄ9ă|Ä=&ñé4‚fȸ(a‚‰́îệ–S&Uÿ"3 (¹[ÑÙ˜}¼uÉ­R2w{$ È¿¬—}ûàP»)È�;Üơ>›‡[¼Fæz3x[“Vø©å j+Ỷ˜¥ŒÉÓJ2åă ½Đ)|Î4ê]R W©,+P4 “‡©is³Q.aMƠ–¦3€tÚÏ€<‚Ä̀zD* Ènri:¡‘÷ưäj²H]̣Ÿ"w₫sá’¯é4:!owÉ•—`örr½}¬ÁÎđ-Ÿ1Fó˜€ÎaGUË5Đ_‹.]‡\)vñFµ²ăáØ%{­Áÿù_ÿûQÛ%ƒ̃·ÿçưïAJI={ö¸«Tùüèȼ+âñQ¿×í÷úOzư'Ç₫“§[Ï·ŸơzOvæ¹Ø·y?ø@₫‹rACLhè’7]øÿŸA]Gv~µ ›ª¾FºvÉ ^ƒ¥/ÂT=s—¼a4–"$/E°1#ßñœ̃îµÆ¹œ̉9ëIÿ3’=¹ íÏ 7Aü ´ƒ¡₫Jœü[̀ ưos• ` F ’»a¨ÆI¿¦¬Èf̀̉4+÷CËü êÉPˆ­c¥;sRçYú°Rç¼”\D,F£áT,5¨@ Ê›̀„ö²*]A¹–XˆưYU=LO„’û,f>DˆÓ`_‰¼ä1ylØ·̉-HkØF^n#|PÍɉ"NŸºä"�–»ötIŸ\y:­ô;.½˜%¬óÚ¬đă®CÅ₫ ÷̃Ü{ÖÇăá¯ß#Ù£[±< ¾–§¡˳(9t–g0w0,¯ ̀5Ệ ††åƯC{gy*GG±¼-1cm7Û±¶9›ó‰X›ÖP{Ưă'FAƠê©9nkơÓûÀƠ¤­¸ZĂÓúÄ<¸ G3 ›àg Ö^¹ÙåO?lAt >v Ê/*ÙÙEM•Œ·¶W] ÆàÚ6ƯmñÀơx÷ö¯ß»Úöœ#IjÆ(gƒC^EùøĐ›2¦ç̀PVMKO[’­˜9‚<qÚ’b>ZZSXºÓºúå*ö ;8뻜Ú#Ä6…lS_w†i0¬Ưđ’Z¸jBÏÉëṚZt}8Îé�)ta�}·BmWuÉK…_èư4’E.€¥¢¿à̃í²À́Ü>'UgĂ-ê³±4;MKåÄ”dÂ#̣˜“c‚å Î -|ö„|KA"́c̣D}ư)É™¥=†̃fßôViï_ñ]ưrµëŒßߺ$rÉu¾âÙÈ’ưÖ%Ê₫iă$¥äŒÜFø¥¥_j—Ï_ ™Ÿ~¿±2FÈÖ„ ôJÙ" Å€Ư‚+HûD‰&¼‰<ƒ¤{ 1½×–{„é¦đ¹×H–ĂÁg]³†Oè^ăV£Mám¯i£Ÿ oŸ'W£t¯É¢̉KÙï”�Úüb×ßTº{¾àfE tÆÑº3\@Wơ¥@¨JNT®Qó¥nT™z–â¡–†)T(#5™rÓ ‰¶¥ U”³ëhëʦ­Y”•J+“ƠÇØ¤—ñ˜ë·ÅĂ,ñ/W²QŒ é?Uw¡X{fi³–S«v]¢cóyae5Ÿh¶^hQQXËÖ6ˆ‘2Úd}h¬Îñ¸˜P9ˆ^Ă6ÉØQ*‹{o×– O³FÎC™¾’•Lx́°UXVôµ¤2Đ Qµ-ÓMă5ׄ™=pvß³*;OW₫·Eÿ±0v"°¶ÖÖ¹zöPkị* #�F}ôå:̃“!›Đ.̉¸iĂáJ™́K̃wûÇn÷ÑP iÓº́Ég7̃-€~ÛMÊ_¸Fu}¤Ư›«®́‚Ôl™]³äÊÛJ¡¢©Ézáæn`á[«|ÅÚÂ*+.“JË„̀4¦âb1"ë‚qUe?Gó³v['ئ©&!ÆSS¨¤æ[ÎYªÔ]>ó¬a ¤MW…P¨éf³̉&Ï$¦¡±8‹û¶’ˆÜå…ÆËâ&èEx(éxL\Ă¶Ù‘z ¤÷âôqENnIđ[aN$cåæăaö¾'ç2¯m ñS›ß̉$måêî Ưo•äoç.Q(€¹@[½•Dx^c?‹fmR‰cÓ…ØA,ªI€@OQlîY”¯V·Ëæ›ềO%Đ#î!ô¤»ư­Ơé·á÷₫>€ß»Ư.|̣3~̣sÛÉ'®®Ï_-Of½PăR—æÆ¥+ẳ×øÉë¶³œ:́e¿·nI‡ÜöÛú—AßVüÜ.¾ SVkyøº½fúËc���̉å1#3f”3z]ôA愉¥F�ØÓ>™D˜‘ÄÊ+•K°î C×ú + ¶ÓèưUibǦ€/1íT¢$±®-`ö¬j øÄ×f_lƯ0?₫vÍc&¹Ÿ²Ú6MOº}bÛ\4Ê ï.Xûµ́Çëd­ª M77ºdÈưäKÁdí¢Á@I[€F6hˆYơ­7—ß·Q·VÜu¥Vér-Sø•*8‘Jđ ¾¹ü>ă�eŒJááÖªW(@ <L´ÖP DÉSzwÛØP6F“EnlMœó·TfÓsG4“H®fQuÚf¹\’sjŸ]@62Bn½<eÑ5^G…‘±Ô2:QăÔC–¯ëS¥@€Qc^蘤³©đ¢Qpí59iâƠë7}wơ¼²Í̃z#“‘öTZÜÂ^*Zº6?,  –‹ " +×–øÂĂÛ Ê(dƯq-¶B@&2æ*ÿî¯o_ÿƯ.̃óØ„|˜ÂƯå«Ô<:pÎíI®‰ˆ¶ªøo 4[ơ='È/ƒ2gă>h¸¨7­˜”Ÿ†ơ™ºO¸Wđ·‹ŸßüôưƠf’u¦,Kƒ’9Cq}êla‰/Fh®¸”†.Kª°\jóc‚tàa1•¢ªjH|`¦Â,xèĂudi<8ß°Æ„™.–’ĐsƠƠîbbÑà\‹†M,†z׋’Qù-E‰FB ¬?·(ñ‰ƯƯÛˆVˆX­‹^Ζ_}aW_ØƠ'gW·÷‹]Ư,»’Bêk <é>"ê©ÍY•º;£Rö˦ªăĪY€Wù¿9›2hƯO~=2#,F$‹ÁXîɆ«“Đ„u°ä<Uj!.‘rŒ9“ɨ₫L>&ê©íÎ$@mæL&£ưɵÂǦç PtUk{•<8¬•̀dÜÀ}]ñ$”ˆ‡w{́äÉY!A©zJ.Ú¹¡€m,fÏï\²±v&«›ư¢¯ƒX₫R’a¿;ÛưIIbÅë·íw–¢ÆméÓUñ¤n~gäư°n˜áàCE*GáaÚß |ȉÎA7黄%^¶å̉`•q1XdÉ}(¿KSh0d`³@VĐ(ô(ø/ Ük´ó]‡ü(f́†Å®2ëéPSúàX `¯¾]µâ½ ‘i‰º`"×¢t@̣_™‡Kxè) G²\9ă®S%%n¦rϱÏcæ%8åÓªD^›—cC*ÅíqvDC"nX]ɘ̣ĐÔùÆ}`£‘ LS[$•Ư´*|̀¨OZxoaè›rFéåó°ôE»,­"¶U‡>Øm<¥™az«±X+ù,9¬iU•†4c‚Eå×)­R)­º¯wu«º µ{ós¶T;ơN‚T2‚ÔW§¸¸(äDXDlŒ\øú6jD¾ºêå«c¢ÚN¾¨ÍÈW·Ñ~嫵=%ß\o'C�̣F̣ºö+yƯ#|îI&ĂđO¢<ơ@(¥£vÖ2Ô₫"ª}Ơî.ª¤æ|Ơv7Ù«!ÑëδåÖ̃ge *L±…Ñu°BŸÚ[˜¿+Àª ‡ ́Ű×lakÎ*ñÜzÚ́]£̉sÙ̀q‘”·�j�ÿtzƯ§ưüµ§>éu?û€Ál_Çq|BnÉ™Pƒ8º>·ṭ<$½Ơ?4„È@èôºÏz½âĂ«ŸÀƯo{½^~¨Ü'ê5tyXJ¥̃RÄÍ‹¶Z¦5"oƒ"îz âe­ÜBÀm̀~¸óa˜N« Ô,ÜBđÚÙ¶ëz¤†îƠQ,¦y«v©Ñl)‡KÅĂ·ˆzKbñÏZr°CŒn×Ä Îɹ˜“‡äEj>Z3̣>ú.­7]nôAWW¸¯™g?a:mÉBî-Ù>«lqă³/]̉N×}Bû-‘[곩³÷_›ƯYùúÔD�’ 7¹xƠu’ KŒc;—p²j®ºÎÉ~J® R cRÄ·wï<¯øaưa~ª¹ææ§Ù@Ưư8+Hû=Ïèꛜ[ƒ¤ƒ®y¡ñ¹Ï ˆ9åü qV°³¬jxE#=ª åæQ$`jGu¸jÎg–º/¶¨a-®µE Ă·íwŸÉƠßÀ¥ÿ{¹™Băº!#¡á±cPºß¼Ö̉yˆ‰“5ßÄ0ÊRÄü¶QÖöo9ÙÀf²¤ĐWådiÏY15ËLM_mlqT̃@ÖLO™»ÊN´i,º¾úC–߈Åá…. ©ÿkg^?ë>ƒߣª=Ë„"ô¤ơÂ%‚‡µƠT*^¿Ûƒ´<é?í=*|Vø¶wÜ?V…ă§ß>*¾Ưé×½ƯéwŸ>~Ô«z;÷d¯t́gß>ƒ±Í·CJê¼Ư! ¬{ơ¿æ×xÏp{¶”ïï₫¬ñv§;ˆ6ÙU62N¬Z#–ăđî5B#Ä ¸̀Wë»÷Ö•³½›ñ¾´`ôª˜¥:¶‰Jß`UJ¨E@C< ßRI~¸á̃DGḲ‹}Ú!W6É ;S³©̣5÷‹”lMºkOÑ»­ˆP3&t¯M&sŸ‘Ô$ẽC¨óæ ư |EĂH^'Đåm­icµ…¾ùÚêƠË8ª^E÷®&=œåe§â8ë /ư¾ ¶)Ó”åEAº–ƒ¤Ưkî4PY§iûÊ=ÀÚ^+!>÷Z£ơá³M4…ék·îdÜ›Ơu"s\*Ÿè–+…f¾í{{ qÈ¥â©ú@;E6l‘Ø·Đ7K(ĂI÷óFˆÜ‹ß¿}ôÙ`ưGe–KøYÿùëm±̣F»/öÄí‰Å ¨Ëè&c`t—l‹ª Cμ¸Ü¤ÁZ3#±Æâg…o{Ç}bM„Å—µ}±âem_¬z9÷›wZ̀‹Ù·Êº¨,»›o£=Ç?öש2Ü£-5™Æ™?«Qăô0DÎRË#ªưG*ŸßØI>÷·ú8«AvuÈØ“`Û[ùI¥°e¥áJª0ùÿ̉®W1‚8z,Y¼hg%D—ë‹rvG'Ë$/ơ XÛX*¯—'¦hóDøG:$D”ǰϻ¬ë®fÍ₫±PùC<¬®˜9e­&P¬yBÇBªđr ¤v ”#́ºao ßј´ 3È9]„Ä¥fĂUǤ;îxƠ¥\{ªî́ö/zw}Ñ/{\nv ¯6º'C·±Đ¯è×Ùçs›½SYT‹Å£·ªƠ@a*÷&ªVăèà˜D"5!=̉¤µ<¬ôđ Ă&Ú›ó‰RFA£ˆÑ¸„U|*ƯDÖW¯̃:©ß1¨ŒXS£uåYU£ơ[¬á¨ë´ª/6¯ÑZ2₫v5Z‡LJĐZ§Ơ·]ȤRÏmN‚2È»S!kÏÎ+‹j  Uf•ơ”̣-èT†Ë]Y5dG9™ô™´nc!‹E"�yŸÔˆÅ,ôL“DøLWbbawƯyÄ|N»"Á_G/đï‘P1™rWÍJMµ– ~ÛèmÁ-ܦÎà}(Pc±´ûñªnø´³̃àóđK×||̃`Đ—³¡Ö`Ă{u*ƯEdÚÂÙtÜWùG½¶ùûl&•CÀl“�Íäö¼vsOoË/)̣ßXȰ^6%U–ÊùN7oÂŒŸh ²‹*/ÔT1Ï6ü~èªNLj­Đ%¿z*+3Ơ]J3vƠ;MÄhD"₫ͯ‰©Ïi(ë¹DÇH!áQ¿ªàƒmG¸u#wœ£Ûí*h±’I4(ªT",ïÙA~¾åGIwkG¢•÷œ#9Q$‡¼n·»4W¯đ¶°R39 ưI°•Ù’˜-qɯ6ª;`ØÓ‹†¦ÛFƯ¡ë¹~Éâ5ôBæ¤ w«ẪÄ‚^sI¾¦Óè„üLCàß­₫³gƒ6ôÎR©«]³Èk6#ñơs‡üL½)’7é0àrªÑK ™Û½÷Ơ<d@zê$·GÄ<·…èf!7 »iXû̃₫QM±ÿ±¸aQµƒ¼qU=—«j–ó®)ÙÎà{¯ÂƯAá»Zºª„®ÆŸn+ö*₫£zùÿ¨^₫?¶ï°Kµ‘2ïĐP…ñÂDv°máN*#M7µ <D{Ư­zÆ)~ÛƠ–i‹ư©oUQƯu‰ƠA0Áj :LEơ/U¥Lpj¾`ªÖ̀„̃ _iJo¢¢ö«÷úGïŒï^‚­+È覕‹B33mQ¿Ơâ ư¿«xkŸF°$Í,ơÎơØRPt3Èr‡$BC17µoRÉ$Î.ÏàßZx‰xñœü€Á6”DœylÆ¡ÙZ@m“Æ-—,DˆŃæñÄÉæiöQÇ�è-ƒ™@•mÊ !CC"˜?†– G{˜t ƒ]°ÈtH™̉H¡9`#Ø–Đ'’û̀)f xjTa„Å\UûÆv5!OtŸ366¥Q“âe®`á@âXGÍ�\Ú¸l”>àï¸ •åÖ¢v&›H$$öÎTNGïHBĂÖ́›wGƒ¶-t”LØÂ×go8đÊŒĐQÂâ ¼,˜�æƯ„v•ŒDˆb£ôe:̉˜ß2™k¹‡̃›ÅpçØ%̣p©Ụ̀ßk>葌"ÀÏ¿È?À¥K2/d7ü‹¼ị̈çÿ„[Wmû¤₫óŒ\uæyú‹³₫Qëª3o[M¬Bư Èm§cñyNZƒ‡ówí£Ö 3×Î}̃é“ƠU\‘Î×ăä„t Û> ÄkåaûùđeÓxGnªi�åƒ'á‘£w„̉Ï›@ÅJyú_1¾ù\¤à&³aL3â3è¤ê`År9¦exÙ@œG*’m“41T$»éu¥î=n.́9|FUl� ư…WDæD©wº�‰"fUFMQœœ7ôîà?Úgc ̃~ë¿ñö‘ùơö*ú̃ Y‡¶M¤™66n4KÔ ˆ¥Ù²9ơđÑĐcf_©úi@Ɖ† 4wôXyñbF`‚ û‰:7Ï“˜.;Ÿ\2 O(¶£$ï&B2ư™/`ö₫N±TªƠù‚Ơ:ÊÍ%¨éøfäRsă,€óæ͛ͳV T3 —̃Z­á¨z² ´z†¸µ(à‰N‡iÅĐđ\Jk‡tttÇvä–‚D±á¦@¦+0«8 ¡÷§§×¨ÔḥL^!íwP̉đ&̀»ÖíØ4#éX‘Ûưp¡ö_„Ël »¼³…}ÅŔù…PA’†Rñmë ä…®̉'F…©éb{C'à2 è·¡;ĐkD+\©B¡2Ϩld¸ºD€ ÍO§,™_b´g¯úio-�Ó‡ ù¥”B×ÎP‹aGÖ}ƠæÓ$Yç |L���ÔS[ḥjz<B:¼¶mô¼=¹₫”Œƒh¹Ó¾¿ØÈ}&âd²bb|—ϰ$lÎe"ñúŸâm²ÇÀ{p₫óÅ»Ÿ.^œáç*í2á@´“^Qž¸„œü†,L@!(‹’6½å«=%}cj•ESëJ@«á¹ l±ëX¶Ưaͺ̉}đQjíÇ¥æ5e<Qè¼.ÊOβ¾rHL~‡µ5‹̣{í³Üz3s¬)́ưI=–Ÿ¯ŸÍ_yç•WđĐJwe‰ PôYVzÈÆí&´&ȲzUø+ÆSí\TÉW… &ă/WÚT@ớÄ:é¨ 6$C–̀S¼*æ%B¦ßí)çà”u“ÄÅ'3ÑaªÀ·Nf̉]œKœY«ß&_É ™µK²‹±) ;oHUPí` fêÛȺ̣Ñ,”Ä<[–8§0¨X‚ b`Ơ+2QáqmÎô³ă²ñ*P©[ƒ|Ư‰ù{[-c=l§dgs)±#Qj™2Λ«V»È¥Yh]“†æ0k÷¿£¯̣̉5ú©ÆÁ_2&zäÍXúî́j$z?t‰ Đ̉º?X1ưX+đY'[Wµ:ưÆŒR˜¾²§Ẁ̃ô¬:đ̀ä¬đư¯K~|¨ZÙ₫`^r×e˜¥6%+}»kpÉF‘%;/Semó+Å‘ªơ,G™P”bö«!fÚ ĐxlÖÛßyÚ&Œ&›̣²TQ¹‚²—çC]2t‰çL̃[CœˆưzCĂ¢ÛÎ̉€p›15ˆØỏÖP¥“n(!#&vĐ€gƠÚ߬ºrJ\ưVÜT¯)ƒë}–3̃+®WµÈYÔ¯Æv4ĐZ¡[Rxb&k̃”Ù›Ÿu§´_|Ù©²Z£Ø̃yăöj:©³±ưmg Ùr_5…�¢´…Ü Qå_ÊÏ‚Eí9̉D¹‚§<äÓÔÖZWH0ArƠÄ’Ũ1†°›˜ÉH„’oBcêA¸nµÓ¼—xåâ ´zfG˜€ Ê >”½SÉÿPy{í ¦P !—ú)abˆˆ§4à·YE–׋)—I vhÇ43̣¾çö?tI51ĐñmØDM̀Đ…lWó(‚/Fe+ó‘Ï<>dîXIGLÔœ̃0ˆxJX˜̉B”[""D±kË èEƒÎRÁ’²=aÅ5g£¶~Ù8m;;UÁJeµµ®8k¡"Y·vvSz­£¸LüÂ1%‰H½IÍ€å©@»Ba£8dJÓJ+‡’+C­ĂÉ6JQ°áÔŸ÷ÊĂ­.Ú$V *©-1+Ñ́\* ˆ“;óơc™NsùàJg/w )]Gö¶CÆ/£u¿7·yh] Ĭ“³€T m>”¬ L1…±Ú¥›,]=`á8™ÁÚSeV5e±û†A›74X3hîålÏ̀»kPè¨ÈÉPW;PV¶ÄU¢¯ñJ™™«·Êïơß­í:+›KƯäÀäNö‹µ¸)ÓÎÖ¬f6äƠFvµå‹… vˆvt vµ[±ˆ€Àù1†âM­Ä\*ªíÄ%?`° 1;E …ÙT=%‚ø]B. FZÆ•w¹XN¹c&R5ƠD识sƒ{eÉ€-]̣¯[¿¶ÿơÛ�: ½ï?lưzô«×₫­5xƯSN¿÷[«óö¨ßƒé®)¡ĐJ¬¦Á ÄOÓ ¡!© TÖ_=\̀k…B‡ü*Ư·*Èî×È}uÉ[‘ªx¾×F* Ù<±” ®î,lÀ±`¤˜y4đ̉€&L]LöPR‹µeøà*‹2у–"QǃT-đă\cÀ ̃!‰±ÿ ÁµkÛºCVÍ\uđ9̣cÊc¦„ăb²Á•J6ûéMá±.¹©¥ä€ưê9¥¯©w 0D̀Çèɹ´ÖÖ3© Óq!qر¯~àoxÜE¼{•v�YoYû‡Ưܬ¦ înS8w3¨Ué8j{ ™¯­@¡£̣Ăê€Ơ0™èjŒ/'l¸v“3±ÛC‡É Zs<LÈ\¥Æ”½¤T].ª¥Ă[Đă[ë­Í;öG8"­Pøg̃v1v}₫/ä0Đ4"àĂÖ2�₫•ï“đĂ{ưâD½‰ïAÔ}±bΖưjDæ)AG×ĂT:Gîsj áÈ’ß2ÈŘ`hAlƒ×eƯ’,Zf 3nñv»‘{Ö_Nú”èǶ»mưfJ5¨{Qjñ·—[₫¶¢ÂyM´ivI1²áƠ¡„œ¢ưºÓÊƠ¯F…ë :ö.•ŸuÙc̣‹1åÄĐ,¬EegƯ0#¬Ôơ}ûFC|«̀#Úœ‘Órˆÿb¹¯*NØDđwºÇ… •Y_äûƯDƯë7.ÂqÀ6(ZüΔèV•Wú+2̃Hûqt̃êGZ—ôÛô'ï?´zsø#Rư¾:½îñă§O¿Å†ßOŸ÷ñü§³OU‡-¨ûtđd¹ îÖ̉”̀´èkÙ >@щî^�׈eơ$ư™ß¶¤é y& ¬qMfÈøSú&-¶Ă9ylߟWs{uîÉ?ó^5ퟴ[÷Ù”[J¤ŸË?iuÿ”Mâq e…ünƯ”ñSÖ¸)7đR:7å'đR:y/å.NÊƠÆjK>Êf]”Î’̣>»( 'Û̉E©$Ú/.Ê/.Ê/.Ê/.Ê)í‹‹̣‹‹rCåvö넲•æQƒµơ×{Æ–³EeĐœ•|đ'°’ög%¯ĐĐ·°’–™|°™Ü2̉ơf̣ïØT́fơÙT˜û°SÓ0µ̉f®đZ«h¿oÉÇ–—¸A³èà°̀¢ƒ?·YtpXfÑm±}_LmÍíƠá˜Eÿ¬{µ³èàóæmliĐÛvg5Œ>¯a´$o—ÿ̉$w0Œ~±Œ~±Œ„etđÅ2úÅ2úÅ2úÅ2úÅ2úÅ2úÉ-£Y ₫bаetÑ_cTăÜÆ¤`›1¨,ú÷ Ø¦AÑ^LŸ5J_S­5¢¿ çgFôzjÔïµç}B}‰µ$¨̃–‰SÛ°W#ÇŸJj‰5´1{5©|ÏØv[Ö¨IjÑï<ùS–«ưüxưö3•«½ûÊ·,W[©Xṃ_`׈¢ư©ĐtS•#Të€j„o£o–l¶ùfù(YH€k†”T„Ạ̈¨P`‘Çm°‹Ạ_̀°¶åÚa—2oưƒè*MÅ4•MEË‹8₫ZZ¬±¼¡hqÙwï'JăkSöđEÇ)Ö<|úm®æ¡êfGTÈB¡̃áIH~å[hW"”.yzÍhzƒ5̃#bL[izƒÆ4½Á}Ñôû¿êÜ7Mªzƒû¢ê}FLïK×Ü]oÿ¸ÿœº̃à¾èz‡º û̉ơ÷_×ÛjËƠIf]ï³âơ³êzwZùº̃:eO”=ëàËETi|Ôlds_à5>;ʾ4¾•>™Æ78ođ 5¾ÁŸVăC °Fá{¬\‰›ë{èîêºÚÆÏ§ö6Ơi'Ơ‚¶æjj _ <Ü-؃‚¨6åđơĂϾ)ŸIsTûsøă=ƯŸ=¨”jÇî³F¹ơ^6¦ø(Üư9ơÉÏƠÏ¥M̃yƯk•I§ M†YüˆÉKB€̃Ư}‡ G”„¾o©‚¢¦…ó2®5Ô#Đ�JUPXºy-12Ú@°‘îÄåe�ñÙỗJûñÅl³9VéµkµÚ¨ÛƯ`€¼J[®ĐfŸ–ë˜[ S¥Øn¥ÖºÅ1oƯÈg£5»*uvU µoï_-›èö*h‡üE,œ0>uÉôKû¯®K¾3mdßñ)[í´æ’í{âæÜö́Y×!̣†Æ,LyˇŒÇÂ%ßw]̣Z$N,¡i@‰¯:Ộ(à!%ï¾ǘ)é™Ù€(£ưú0xH¹tÉ_/ß¼uÉ ×ë z½ƯÓ‚uÑÅ5Zî±)θ¥ÛLf¿u¯3û-₫öZÿ¶™¤ÿ¥¨ïÏëó¹cEÜJ|¬­°]¬9α™Û¸>Iÿ‰_ß̣>6”¤o`H’~†Œ?e’¾Åöa$éßÛ÷%ñ»¹½:Œ$ư?ó^5¤o·îÔ.½Ë¾îZ®äƒí¯' ó%§|Ÿ9åj7T2¹³C6¹₫V«k›%ƒkóI^Öú’>½*†|IŸÖv©/éÓ_̉§ Øø’>½|±¶HŸ¶Ö¯çä':¥±K~¦±—J̣_<äO¥KN=d˜à {p^o¿"ŸC^̣ØKy"$¹@ pOḤêƠé�9¯0^5’Ó«w¹³>âq4]£Kđ©ÍƠo twƯ­Q¼ÔGIĂ«[«ĂU ‡½˜µFëü¸; ư ›ơơŸ›ÿתXÉdt6ÓzøO‡ÓÖ#Ơ%Fưúï†đ[¯¥4~3wè*Skô Ö‡,ÜWáïâ©><áà韫LÂó̉˜z‹Üåkmơñ[£m›8&;é|s‹ÑÛ®®Ê l‹â˜áÑ?ßDl”èsîDÖç¬EHÇ:ïĐ4ÀCFăN4¡’‘ËWo­§̃óDŒ¤¡3ZOđTßYÔ,@±₫:@÷¼F•vÖ/æ`À¡¶MY2>i^ñ³÷2`xÊYBhĐÍV3" EÂÔ:¾ûååeÿ™Ältöà«Ë_~y‡²kCî}ázÚ$•L™z¸̀FhÅbΧʢ•¥hñ[æ ÖEç¨uÍÿÿÙ{÷æ¶dmü|©¤6‡t@¤|w”zmǽË.[Ùœ=~½©!1$'Â…@QôyÏï³ÿª»çàŒåœ¨v‰3ƒ™¾<ưôd …aE‚Ư'̣…±ë‘$ÜÈ(ŸóĐññ/e2ö¬)Ùé=0₫©Jàä±à©äĂp íR9¤"´C“Z9i¾K¬V>ư ˜¦êK0?#²–̣ƠÙ¼‘LÄ™h«[´…4=Ơ“;^(ÍíS»Î̀¯ßLOa}X#‡E–ŪhÖË“v@Á'ü –ăͦÉ}z4OifÉ'kü{j‹àj÷™ŒXmèƒá9ăñ̉›¥âZb=ô₫6`!¸XÁËl|‘_20¼r™ƒkz¬j‘c3iRN7U5¶¸bPOWJ“ÂÆĐÊ]—÷æöÇ•íỤ̂Æ©àa'GC,+/ăQ*8²Q®úưB/¬SÀSVC1ιŒ'Ó\9̀“1K&:LÏb*°̉lr̀ô2ŸÂ3+^fzk<fÂ>Kû,°t`ÎÈ]Æú,³Tdø@>(xÇơt^B‰u‰F4ô XáZ“G2—zí¤b"ÇÓ›æhg2 ¨‰'lhó̀óf̃Y#ô¼I�₫˜Ø™/ª®}=LHLØI¶Soá1ûÀ[a¿Íx+ÅĂ₫>hÛ …ïn…»úŒ'ư­ ,Z���•í3‹¦Cè7Óa™yÈEéBâ$üÉ©9KB˜®$´3ÛAo5 B�}ÏyËóXæK„sù¬ç¾~e !'Ä@щo"ϳ'…f8£Sh4ÅÅ (D©ưQÖßs‘`¬ äÁÊ›€I¡R.©8/Ïkm¯³‰Ê·{…(ÇWÿÔBœzºîö¾{;^ưʤím±ÿkæ•ä”ÇA(@Lr-øÍ(5ŒFŸµ8Ù|6 ¥̣W×/VWy:e<Á#bó8”W¢ÖeÂø0¹>…£ôÎT}Ê6O‡2Oyºd­l>D'ª„Á©N÷·»l“èg2¾N4³®é¹AtZ÷Đ#ø [Æ9¿Ñà¼= p¬_b>«ê¹~‹Ôơz@­ ¶ú…áÁCĐb[wtơN 8»UcXù:[F‘ÈÓå3NNö@Œù<̀•˽ʨ;̉ ₫§½ZÓz Đ!5Æ×OÇN\Œësf³FƠơÖÔ_ØXÎM¢b@˜LaÓkdÖhuhb⌭Z”Á}Fva˜yN'TyNçe!́®øºẁZJJ Z”g&'q'7 )pLƠ½tïV\É#n'"r˜9<KAyV8¯›Ë̉fH$iµ)q-âbP*Ysu…‹á¬‘›¥Éµ �ơ{»˜£Zœ'3^Ü:ç“R$ÖÎh`rTx<^µ÷đ8—Ơ÷¹søV¸¶�Xh¥ Á‚ç=q ˆ,¯ẁZÏ?= Èô‘ĂOSHƠ%ăA )d.@©ÜÄ€  n¤Rxn|nLØ@f˜'óÄP½æ±¨¶Ùb°¥1 8Jâßôq[0RŸ:äJG±ÖÆ“W¥a—4’Œô ˜—P:º¤z¨@/P^ ½XU Kº÷‡EŸ-ªôg¯R¶¢íŸmơgo­₫ü"e©iïÂ>l)E(đ†H½âuV^ÿÖ6E¶zw­QgyJ œgJ‹#­„Ïàñù4Mæ“)ëºY-väDI)Ị̂s'HRƒ‘kd8§�~Ơ ï`k»œÄ»‰$Ö¢C u¶cÀº³Æ€ïJñƯUܨ»o*Ă¡HóÂÔ•,çqÀÓÀ8Đ«z»ô*c ûç$Ư*XOØ´ñ€áú“ñµHáD&Ë́+Ê'*nwÖÏS¢µ¨X=:°Bdp26BÁIóÂÚÊÚƯmિbÁư<#yœ G̃L¤9h+PWâ?®”êYjÓ­ ÷™H3™å€¬¨÷4'Ăy–Ç"sW<GăĐ×B-i²i²`£0ÉP̣4lÄ/Ăö²d xÈ”#’eI8'+6̉àé¤FF0‡$CôC₫’Údªăäµ²yX²!÷Óx–‘̀ µd̀F"… %9 Àë³î2ö7 I‚ –‰œ́bLñŒSNơ¶•/gr„gí7¡xr ŸD»Đ„êg(®yœĂP"¥ÓD|陋Üáæ2>€GhJ̉A²t‡y@§R¢#ˆD<Œªç)h#Jç<R0ט Oeó˜ü¾æ©U¥ É%y^­8ûf"@^G4ÑYº)£FçƠ­.Äp’ÊÀèߤYå5¢bjÊïDØWß«_´C¡S^ë0K ÿ æ©–ƠÎ|û B|'XH'gÎDĐB"€m¸ô†PD³/…À,™±)êQภ~›gÛL^UÎÖênL̉ ¬´!ñ8R1aƠV‚Đ@ #§ÉB`ÚÜ�&ÓT"ù ĂXÁ·fÄGS£gBm”PF’¦(£!sS߈֙̃è¾G¹Œ%3Sn“º¸¥›Xy+ æÊƠtơ·}–&‹̉ ”Ä,¾m+‘\£ÍêA!&WèÄ™øç]Ø}h v�̀ökâ?¨&â")âÅb‚¦¤×H¶î|z ^–¸¶{¹¾÷&b¸ªÚ̀Gù<Å.<çJ3tœ\z²¬h¢ÄæOsÉCă§ï�†p™IM ‡Ä<̀ÃQOØX)—W«4¤a˜Œ®àˆ7ª�üÁ ¾æ}‡ EÍĂ\¥““`ùưwyúưw9œŒA>=ûª?øÛWUŘjæ{Ïữß¾ú₫©‚kưÎÖîR3'y }Ùª¼ú.üPïđßưY‹|Ư£^uÿ=Ú¹®yÈĐÅMEs'ávÙf̃ĐĂ¯ă§L¢7ùÚG¿‚ E·Âd„àW†῭%p²GgÆ›:ăf‡Ö¡Ú[đ ́6øÅîS«çª³yö}M‰<#z0L’€̣8J¢ˆC1âsˆ äú8É€’!O´´f˜ ’ÉxDqt#dÄÍ(œƒ3(/ơÈù¡‚<N 7Fèl₫u1ÿA!æ?P1ÿùƒTKh̃˜uÎlẸ́Äh±Hc²è'Ȇú•>̀Tü₫I[1ÙN‡ÑTŒ®H·.Ä7»^ùè’Ëx.³1)ºÜtAá†́«ïơo¤!Ơ*œO'i2‡„ø±‹¯ÙO:Ù--W~ʘ½üôØ;ÏØ{t¿×ë=aç1;cçÙÉà û½Ç] èdĂ+'/I‘u½!;#ü2kƯëù́C0Ù½<„ï¿Ù ;}ö¡ÏzÛO Îqă"orÄ—h₫Óæ<v»yÚÇnöº÷X¯û€AÀüCÿS°ºU*àĐƯW`g¢{‰µlÈL¯µv¡ûƒÓưGØïÿÓư±?i#ÿo­ÖÎÆ­A»Ư=¡–'mŸµ&ßLđóÓvûΣoûí?b€ÏLú-ArÄ8é}btơØĂ-ÈZj˜wi˜§́.»Ï²~ïăIŸ>ÂUÔ®îớûså8P}É´ô'óظ6…kÜÊx ¦J’÷9yÂPùLÏ̀*¬5[₫¹Ë^@G±ùSm₫Ù÷?¢›PÆ×<”F´áV>{3ÊÁ~‘„Xy¬†Hđ™è³4 æ#áq£èmdW1@§¦lùø‹@"~&“K5©ôªTơÙ÷?SܘÅèÓej4ëµ{ư2Q—×â 8œ¼!„Ïr~EWQơß‹A¿qW×çê>© ›ù2»ÊvJiˆA·u\†”z‡óy2Ï7¥jÔû©·†]Jñ°1¤­lĂ$½"÷Ueg4 “?6­ƒN¦₫¦-đ˜7ľ`f¸Aö…/z†kóæÉßZ̃é;ạ̀�”#„R₫“Ÿ`k«ƒY• \́Ä0Å1ÂÔø’§~}µlƯF`‹ºÔ¶ĐhƠ¾àèf�¾­̃·y2h»O¯`ë₫ơj°•‹ÓJ"I±‰^ @ÉtQkÁRG`¯Ú=ö¡;¼',¸²zD00Í6CY \"ØÄëaшZA•xß¾ÇÂß²¸ơsl˜K§«›Tí™·l'´Ë=`|d÷8M"Röơë©­¢0²2ŸÎ1nK0ư@̣MV.öø̀Ú[ó~Ú ªRG{ ±³ß¨9_ %©™ë2fÀÍĐe„S`�âuwYëOü>G©›x„«�ÖĂ?ªƒ•rn%œá©HL¦¼Iø¯eFjẦ v‰/₫ ¡À¯¾ÇÿØØ"’éĂB_$„:ˆ‚Â)áà‰@§á JàOOŸ8…ÓBÅĐ@FĐë"A¨=dQ�76¸O¡ÅMÓßéÙRO‚Ï0Œ\>Ô‰ÙAäø ăŰđpéé]S‹Ù°üV�’Q :¢äkÈ·̀ر>E&R€\ › ëˆÇ>DÜÔ9ăƒd×ø¢@¦bœ«etÁáÆG$Ăp~̉Qæäß&ù”E¤Ÿ̀"p_gl!Âñ̀cq÷Ü8 l1ki|ĐëéûxÙ˜uô>);y¯ÀËË>Ä bċڗ˜¤k}tï±ÓÊ; ¶n¯Ï‚á â“Vç~¯ưÑgÛO<æ¸ cŸ}Æ}¶8¾÷9îĂÇ;îÁ‡́ÑGă„qˆÎ)ë‹Î�₫‘ÇtEÏ-hôßÿçËKë’vŸï é~÷.{øñ¤߸¥aDw¼ă£V´½¦Û³ï_ň\̀]"‘. T{xĐæ`m 7Ï ÷ìZ¢;éÂaLÊ¥iö25!Æ̀ÍÇ£$¥ÓSkß—åÜ‚°5÷� Où¶¤¯°#(ÙdÄ_£¬<χ¡̀¦ FAȦ³²á<1^c¿”E²Åw0¸3.SÓ_ÅG{Ô ÿØs÷D¯ ‹å k|Đ»ùÁ Íœß!³ơ@à†}Í^ĂÙ×:>€à”îÇĂ^û f́ wC±÷}6ÀhÁ=vŸ=ÀdÂZ2ܬÿ-Ûjg¢FI.CÚ#‘•¥ r#œ$©̀§‘Âî¸áƠh*'b‹¬èÓB„ôTEHOéSSÉ́&4§¸ ³ºOe2hôÀ‹^€JMêÑ"Qß·dWt‚7°Ç5³œâƠ²Ă‚Â<DÚÁ ‘k‘v´:€(AØÄ-6Z!èB”ÑÀ©ôaîĐsÅJ „¦&_+Ävç–ăP0Ñ<äF¬—ú7̉@ ó˦;s¡�“ñÄsÄÆZUÂhmâëiMĐU B©w8–W·̃­ñ,‰NŒP¡S ơ1+|¬ÖíÁŸ]q™‰´2ˆ²k EF3¥b(˜¾pûmúđnëÈƠ~]뇷ßnăq·v€“rc­¤µ®È•¯̣$lÈçn^Èqë«ư©^Hs“~Üúi_̃¤×°&cj„)œP¨ă–ơ¬eDªt¼joœ÷TÄ÷Đñ%RôÈh63Ça¹–u\Œ‡%ª₫’`Ñ,_*7Ÿđ1×»Óùiừ¯xD©­^·×ëơY«×íÿ­í±bA t‚¡g–À5p¸ê· @}èZñ( ?̉Oç‰J:MR9‘‰ üU&_÷†Åd§YAE<¾ú^Æ×v *Ă:iö – 3ܱ¢ªÜ3Ù·f’Zđ ¨Èö+Û9óíJ¢³Ă z9M"±¿wÙs~-G£©„Z¬î·Ù7a�ÇWjña“&8yÚFî9jÔLoé²W/^¼ h!)½)f€ṛD|öÏ$dwï²Ö£öc68½{÷›8àÙôÉàôîƒ} €.ç³ïNĂÁü N[ëuAÖÆÖjû€4ÛÜ—¤Ü¸3÷§Ôoœ×̣©8·àµ4:ơ_¢óGMưz]G©$GPvH‹ÚV×ù‚t‡ÏÂaaYù-PLzÇPL̉JâÔƯ ô]¶½.¢›=\ Á†~íơßÍà?£/¸eU²²s;ÈçƠFꕆnB���i :K“<Ál₫q©f¬̃ªƠØ'èºÓÚÛb‰»8éâ¬pñ{]X£̣âx¥â  h7¯üT¸r¤̃,ø˜à2Ă%»¥&fÀƯ¿¾‰I¡ �ä¸XôrVu1Ñ÷"M¹Ï ¨»óỆ ñÙ¥HRÉ™€JŸ¿ tçĂúÎÓ$óÙs¢€gÙó§ï.|÷ô܇ ưGO»NÓuE¶©Đ` 4@Ë… ÍW ùk¯woœg"àoq’¦$Ô€Á}t^¿½¨ª}àᲫ¦é#›S›ô´m$ƠÊl‚gµ…Ú®ÀÊueG‰O«¨5ª̉)¯^½c4·…̉€ÙIYêY©„ÖíB_ m]‹tÉb¦É¢Íl‡<̣Â¥¹TEn ơơ´Zp üß UÜ̉fP›Ó‹—rxæyC2ªA5)¸rñE±¬än¾x!{]N癪>#x¬Q¢x_' Äæø¸ Ê*µfÊ-%#±æ2Q‚Iđ:¾‡Á*ưz è¦PüyD2OGâ±Ç̃ é³÷Ỉy0D‚+>ŸJwOE<a—°$=Œ€w₫Z¨.àå£T)SơiŸé9|ª&¾¦»=(½|Ÿ4¹K’ØcA"³~¯Ûï÷\¾¸x₫æ¢ Wuï÷>́ßm*Û²1êŒdÙ)S×m/ĂLÇË,ƠÔqeÔûzEë}½¦ơ~UËLá‚ë°^V|ơKí7�~©“|hµÂ``Û»•öPfrd1«­ßReèyÎ~9ë·¬/…’@%¥́ˆĺ2ö‹®W‡Äe*ư™åPUƯÔ†P!uCơªŒ¢yÚ]:6–ÎQµôCÀTÙèÀ^k(R€²ƒA¢đIÅká/ÏĐ́ê _Q ̉)håt¸‡à�‰¬]‹ËåÛè`’.3ÊÍä¶j́î\—J;„̃‘ª©(#Ơûl™̀1›qD¾°a‘ĂH7ëÛIñ Sé9óu-ơ"@7@ɵ _é@ ¯e0¾}̀ÿV³yñT~RîÓ4è9t™]­úç¿ó [ùy›„xnƯx¬Súa+Ÿlñ•X)–ˆ}LËcv>b7'ÏK‡¹Ó_ý=ë@̉4{Î̃ŸœÔ%°5³çöûC_à̃†z°Áb÷M”çÏô₫ùÉÛûóÑÉûÂ%½Ơ‰× ÷¼¯h`÷¥¿êŸ4÷Æ�öY5æ!û¶Ă²ßÓ¼5ü÷ s>=Ûz@_™q¼ÿ÷à[ødËÑÛi³}5/½u>íàcË ¾€7¯k¯ÁJÓ— Ü»K_5;‡(o›™C;ºøÛ^©[pQøjí|n\P«opx˾f* _57•ÊÏV^+­Á·7—í“Ö ssi¦€f§đ•Æ€}êô‹—Ù¿Wb§og®Ăh̉Üå†-Ÿ\V̀œ₫J=ö’}ú¶ßÔ\T³[³çZCPj†¥RGäI–ÔD•TDG¹ĐºE˜,N¬‚ óú€·ơ<ôϧ 34ø^énst8¨3`´ñá<€+TŒ¦Ü÷̀ùˆ™Œ§­Ơ¡yÈ\‘f"Ă)lj‹˜Ü;sx¢Ị̂¸ ö²ơ¾}ö¾s£†Ÿ̀˜¤ô]ÿ¤ơ¾sC\œ̀xY=JWĐéJDăE-ëj‡̉ŒQGĐû´̃w₫S¶Oô¯¿U›_ºB¦Ø²UNVjZªè"BƯµLX«Ê/ËØ+5Û‹–0³Vùz"R5¶µÔÜ á™Çœ²Œ›…|„ˆPL?́*ˆ0ôÈIŒù<À€S¯OWß9tà+>•ré){{„Ơm)RX7ÀưÄË*—Ï¢„ Ѩ›l?€‹Så>%Í ïØ!•-;–aØ‘›‰ñXŒrŸ¡í˜u–MÁDOơªÏÅ@°!3Ù«3y’xbṇè.ẳ´:#èó<¢Ê .¡¤9Ö °#¡³S!ÏÀ́<«­̉¬µéí§B3ôbvKf³$Íç1u÷Ô „ ô¯4Éc®X˜”¯5r2³Ä]1)̃`ßc"O ôU2…èóeÎĐªÙ<ø"æq¦̣¶´|x¦ø¯€Ôé™O¨l³ˆb̉Ó¼€v¦i.aµ͉®œ]¼†fYs :RṼiÛ ₫Đ»˜¶€ S¥§Q)-^¡G4ÑäƯ¢àcƠzÄà¥î¾¦*Ô4œu}GôÛ4áW2STP¯yœ„ø7Îí.ûA…rß“gè­ĂØz!́_IzơØc¯ù(’Xéëí3`#N¼\ơOSëN©đªÔºTÎ_½ëØ!¯ÏW´ö¬T_ NÓîCL"/¸;Ï—ç+̀–>¡Q8ÎÖy„vû /Ú̃¤Úl ø ½jđtk~5øt¢zÎ’~ưWƒÚ¯æơ 0iwBoáØƠ†ÿäo¡*r›Ê “ŸÄ:ÇÛsËÏ~ |&W²å Ѭ ){₫Qƒæ¤t U3Ц†@usÈ “E—‘dL)ä;™ù„}H|úîDDß#�"#93¤^1gNæR¡àUV5€¬+”Ó$ đ¸C-ṣ_U¼=â35rHyócÁ¥63 ³? ”‡^W!Ạ̈‹|4-¦æ̀æù®ÄĂQ¡@ &ÀÆƯÎ ©g–„Ë8‰$¤#b~RñÄMæùlĂE“|5_=đÎàÛ~)°[»DÍ~®¸dPѳvtÈM§¬ÈúÑcHæW¿1đûúÍ¡nŸIß#Km&µ©Væt\n¨̃U…QØ ø)›Ï smt{‰û©˜~ßG-fHÄ¡êĂÁÇMOÔ›µö‰X£É'e@á¹™à)ÔIeÀà’',;3Ơà.Đpe´ßÂPCûh³0Â¥%ñ²Ë §|—ư@ &K2èƯ}ˆ Ơö£¾¸_xƒ+Û*l.Ơƺ•RËƯÙ²x-zđXS˜_‹Ôs’P̉²ÂîlEdúø °ZE tÊÎHăiö|Öë̃™Iøï}ü/d­|ÖÇáwÈÖ́ôÔŸú¬£>ü»ßo›úA+æ¬ ?¾å3‘>f́U—ửeïE(²X®|öºË~²qÈ.{ßeÏæi:§*.Q`¤Á³"}œ¤̀©˜¢­©ßçDfƒ*|2&pªúö!ẦdnÄ9̀zIw= WÂÇ]0|V4pŸƯ½ß´ß}ô s¯×÷Ù¹¦s`í?zôpEí̃ ~†ÇÍ́Û•±¿^Ë@a'&Ä~C,ˆư&£µ8Ö­èĂúéU‹û4A¸Öow~«g« È¿œƠè‹ûMå1™¿˜©¬ºMÆẢè¢=&CàŸe¦«À£I6âáZé­â æ: ¿®Ó®Ơdø—; ¨ˆBíđ<Å0T[kP=́Û~U‘J®0ºÇ̉*µÄX`Ùy fƒ¨]ÔY¡ü¶9₫u�$IÑs €®·ñqÀÀĐQ¤'NE¢ƠPêÅ̉†EĐ÷ëYSU¹‹1‘MOÙÅʃr ií́ع…¤"Åj7+±˜"9½5«Ơ”#0‘…ơËƠ±>Đˆ=Lº¬®”6™???ѳXüô‡ç₫$Ií‡}úM9oU¢‚Zê|´₫ÍëuVîèçëïNb·zæÖUĂ·ªêÎrDI-<fĂ»ăxăc–̀¨°%˦|VYuÂ-ú]̉vçå§QM¡Ơî™ÍLk¶” ÂÙK!†…Å6jªY± 3s:… IMœ’|ú=êđ8Eס UPh¨ oßÓ¯ÍïÄ~í6„ôë&Ç(⓸ÄE¨£6#�™È*¹ÆÜESÑÙZ VÉ[:Ïñ‘æ̀’³ƠÖĂƠç˜Λ ®I¥̣‰àR%GUÜ·D , }Ö÷ÙMÛ@aK&ev˜MÉl}>•èuOÛÈä~Ñ¿‡Ö$Ú÷>®J…vû c_똓Ë̉--–ơºư›ô«ÖV¹0ĂÎÜ+ôÇ2=~¬·ÓNñA;Ùiƒ†́´Áí±ÓGRâêÉŸ£æ”áÁí±à>Û<ÖÄ~­I–Úoouw[§¹ªÚ)f;…[cù}¡oaGóüP£ĐVEZ-ZW¸¡r´ö¢­«Ÿ©mHo#tÿ: Ku ÖvK¦¶ă]Ñè„•‰ăQe»«¥gê©›g­²MæbIâ$V¬‚0‰8û6ơ¡ç©¤ƒv…₫D^aCă©#*ù¾_¨iŒNvHGLâ\Æódý·y4Ó³ƠƠ±j/—,˜C˜”øM[Ơ«|‰cW6Ơ¯µ©]uGTfû¹$¸ª�[.“\Ñi¨£@*>§ë9‡Úæ­\¥î¶¼ƯăZ¿×P‰S$L½Éuk†Á4¨¬M+¸¤SÅÁá:¡ L“Cíß¾,IƠ²uqÚ•±TÔÔuᬃ“Á½.c?¹Q:¯ƒ̃´<¡ EF™ÉK¿ ‡péOgö₫,ÅC Ev ́CóÏ}ơOÿăéï±}¨i}&©¯¶8`­~¯‡ŒÙ›³0ÉY ₫Ԇ߅UÖ»ÿ‰¶ 'ÜäĂŒµ¦msuIö?©¬T¸¿½ØoÂ^ ×&4>́̃exÑNcØH.#6t{lÆđ°tÄ}ô¿j}ôè0»=Văç›ÉíC«¤¯àÄØ&)Xo—½S,øfqî© )*ñ»̉¡(ă\LRʇ¿MƯsH�÷ÔÓUt­U9º1Cg¶‚únbµë(²©¬¾ă=ơ ï̉”‡c l‡£ÂêN 2!§<Đ eµ©«#³‚öçQÁûl_‡R½G ” ø1pFW©<uCå•Cµ5eÔ@uí$«Âç*˜b¦ ø<£c˜ ëưö¦|¸e¶¢¢Twè‰LA¢b"¼ŒnÏ,7@ÅÊà”_ă°ZÖM†VêMJ‚ZË|=ViÔ,J-êáé&«đNcc‡ƠZœº=xߤ`)ơ,fI  —ø5å¡.Oè.²cd–F¿ø‹[^i$?•)à 1…¥áíYiQ683“/ƒ<à9—!“±…€½*�—HMø‰ ¥½5…̉ôĂ%û »øºèkb„iÏŸœŒâ›n’NN`‰8?‰ú½{ª0đơJĂ=Ë%¾½âà´}¸̣`û\åQ©ÿj(̣5|‡6€º S‚3ÏG)ZXï‚ ÄuCê‰}WMRbªk_Æ,î@}¨Ü4ñ¨^JÊ#0D[RE×Ö%¥KÇ™W*–…¹€œưgBY¦[zẰ9EơT’±Wr‰iª‰¸́dÚđ€J·˜Wi-‹ºƠzǨt”`^"\@Ơbl Z6H&¨• s&Ú LªmVƒ`:~���¬+ßơ+`ƠÿÅ-”�¡¾j¢L₫̃¦ó92‡iA-ÑơƯÖѪ]vÆ›¥ëc�1ňë¾Úå ñM¿ü´̣¾kŸt2øXöÀ¹UÈêU©Y~Ÿ[‚¹̉„·¨&zjJ_aY?ÖooX†Z”Û…^ÔqÅpNm9XªFRµJ̉·Åå̀ª]wf˜ l³ëơ¨ {w;¯T=™̣™ kP”#„ÈY{>çù“±hYc›êêöWüB—+ĂpeɈœ«²t xA•ǼQÍE\«º¢DNÈZOÏ:ƒ̃0™ô{­@\·Û¬Ê ê±V°p¨gÚ佨MG3™Ê°²€̣E½<Bµ(ûsẦjĐzÚyØ}P ±p2d¸GL 8=ǵÿ„áá]¸wĐoÿ*F} xû̃§Ïˆä ¯RNªÿ̃+đ‰ü_¸¥î¹…@ZË ïáÍ1;cĐg Tè̃cÁ¢˜î8¾¶qî5bŸ-|œŸá¢oŸ9行T¼}ưAÑù¦ª̃=̀L��̀₫=§]Kê-t©Ö¿íÓ3Úê!Ơ‹]!è§í‰Ù©zO_÷è`àï3d:¤ÖÖ+ù÷Ùï³_éÂí•üRû‡+ú…÷Söë´Bgx‡¸«ÖP:æ iĐÅIØK‹₫́“P•ư‰&đ:%ø9˜µI“ËÜá¬u₫ê]Ûp*:Ơ^fûûœg²¤Œbnư‘#d(Áb,̣E’^éV†<¾êb¨ǀĂ.ç2DB®’]:bWˆZy £)y ísm±7Mñhôx§D4¸¦´'Pdij̉°́qºîĐ·!q3ª0¬-]_M[qûŒw3Z¼·]¥8普ߦ ¿ëY.ÑeEd0œ½”á8Ö O‰íä³¥̣½r`FHawâyh½l¾['N=ÇMƯƒ·…åÏA³†B}áÁ̉sªÖKÉLåÿn+!U›‡KFlèèéÿÛ{₫Ơ<|¡1Íc§ñ!³yÄ5çơĐ»¿æyƒç°¡·°z÷×[Øđjp{�£sY§Ö z•u^‡)x0úÀĂ Ú e6mGË ¦ Hu/¯uˆOy Á…â«JԘᅅĐs£˜h¯BÎgÙˆ7s.Œklơ!ôt¼*†}&úl8`bÀ†§Lœ2ăÓƯôD^ûD̃«x"o ûmÆ[ÿđ÷A{ûç.jŸkƒ|€Ú‘ª́µvYnœA»ª m›Ü¤êL§)éS*È$hœäy¢µ· Z(¬Ü»‡ªƠ›±)T%GB…\ĐI†¾Ă(Ù*ÙÆÔöµÜ ÷}Ät)Ú̉‚©hxF$Hi€º5ɹm.8"[`ô·}2úl(4Œt…aă`ơ0›$!_®×2ºjºpƠjláØ̉Q!6ă­E¼†d|=PSˆt5cÇ„̉Ü®;b*‹ËcfY|)sY•ơ½®–†q{Ô¥5ê°Ô{~-óOÙƠ²ó#ŒeQ’äS,hn(ÛÇ*l2#̉v:ƯcÖJ‚ Ưe‘KQ¹{[©Ưc€„ d*»mo€]Đ¼Ë^ÅÄb¤“>Ë3›‹`á–¢Bđ4\²4Y`¿ÎUm=ñ8¬th é±L™·rơ đt­o±®‘ ‚PÀ-Ê£€ÀjÙĂ6ñ¸à%±S_̃²Áƒ ZxŒg Ÿå‚Ư´®Ú}>zM:}¬i/ Ôé8̉]u¤“m–7¹2cËÖU›±ó–ô·ÙxHG~Û|ơmÜ‘ïư‚°Â%urƠí]„0€ø[q§4̀8Ă¿¹[çßå&¬#îÿªp—ú¨p§Ch6µÓ¬nIEÄaë§t¸»8b9¦N xé<ÆÜđg±TđH—X¶̀r)Å/æ±̣/•ß;v–?úÉxÎÙ�́ p°ùLwg4O1=�ZW˃³O(ˆu l«”Ϊ̃º3¡¿AHØUcgܹß°̣¤yN.&u ̣�"ơœÅb¡TÁù˜]�u-ÄÀ=)gG̃e3vÿ^oŸ:t$ê çÍyÙO{Qw>²¥²í9;ƯGíFÖ ‰Iâå×:́Q·ÏœK·Ẁ í®9ÍUE[n}Hf倓̣¦! ¡£VÓƠS´̣…Ü©uäÉS5¶Ôé G©NÓ*ÈóƠ!ÜhXA «¾£Ê–+,E×c/~ŸËk¢¤LÀ¡‡wE@kÄê!²Úûl°²½ô*<Ågăqî39WȲµÑH̀ÖæB<ê^´•/µÙ�•/4ÔltS ålc\£QËÆW¡™’t̃µÛĐ@ót5JèOΣ-w#± åÛÉ 2¥̃È™̉‡|3u„*i”¬€8ù¡V³ô _ êTùák̃€·~o2}ƯÛË´ÜÀSm/üiT»¬>¥ÛŸ%vªXáŸÚ¾zæzß™«²Úuñëæfơ¨µê¿°Y­PËU)N̉Ü!–®ÀÈ~2êr)‡0ùIüÛ|ÂsÑA)Ju5ñmĐßåÔ"é9K�Gx đ´´é̉H~ưädLöŸ9ô3<ÄM#LĂà^«rƠơ»2̃èëßp{ZÎu¯Ÿç•¼$tƠ¬�zY¿­‹£Xÿ?ƠIB‘b9vũE<M±ÈDá´1ÿ }²ßë±; ÏqZ~†€̣Á U«ŸC|}„sÑSŒó*³*ôé±ß¡<̃º•̉’íöªûliÆäû„ˆÇ̉†ª@+tqÜ.€b'T(r¬a*#ˆ±j¼®5€f'̉èĐWwÊ+÷ •t́ØO1¤ØQFÙ˜eI$VV8yHTµx*ænÏ̃¾™̣Ư‰ ‹ÙƯ‘±V w¦jQ[yÛơ ¬0é“© U^ ²9“YBl©›Óçʹơx#›€§è#`Ù-_ïc´€|„§®K}Ê׫QwÙèS¾ƒí5 <}Ê6N`·Á4ù”7l˜43°#†e`È{éŸmÈGD#Ád́E@u 'c{pئ2±O‹Å¤2'ó¼Êåœ̃aƯ7äBÊr1C•á’-PúFø(N\1BÁÔ'ÓgßÅ6&Ï€œ&·C…¤̣«C«¬•D|̀ߘg¦‚Cæ1q3KbD<`„„ª¥L ̣ ¯Qùa¡”pbÈ}êÆ¬J)¥hŒ)5ăô«âë5&ëÊ6rYÆ:BJ đ œlÈâøúëBQ4œ\2^°3˜ĂVç·;ƒ;3y§5tÆưöI«uúí;çÑm~£ë̉Ë€8 \uyŒ«ûƠíă₫ÉyÖ^éÑ×_Ö©qßc@,3ú”·neá3^Ÿ=ñâIA“f¿Ï“'¹Ë´9J‘“_d8(ï|̀S ™Üfư?¦̀˜èŒâ9­�‘œ9“rµ}ÆÏú6­{̀nhG<Oåb6' †₫<I# JÂyw†Ëưv°ÂŒ6( ÷X0ÚAaÀöW‚QĂ â( 0°F††¶=&ÆP�Uf£TäBn²ë·ÊF¹Yk£8‰›hªùíÄú¨¤,` äl*£ˆB¾RÙ pȵ^kºwă¿zÏœ¹°c·†íT§-™»©¼QÆ®½IfX\L¤•<àÎÓ_àƠ­%8©CµÏP mñL@ÙQ3áçJ%3öŸ® !oà†l±›ñGè?kÍ$k âoûmvÅNØà‚µ}Æ®Øpwu»]_·à₫Äg½º£�ßE« ,tƯ?¹ •+đĂÁÉEÛǧôíSt9TS*†3¦hçJ<ƒØ’Œqt„r@£f‰äGIA*JŒV¥€$}]}sŸP¾  Đl0Ê>₫>À?¢ü¦‰sc-“ô£î}|îN'G#L̉ĐNăgÇaÜ® {’;{h;ÙM-q:5E››UWúÆùø¸ñ¤t~XÚ̉±²₫Đ­'Ù­di²¤¢ä4dj?VÀÆPin,¨°·W4ä—4ÿ΀Oâo½äz „äN² [mDzEùMặ Gsxv̀¦höÏ/키¬Jµ$“1®Úơ&MƯw]×`zª ǾÓkfÅ¥ 3°¾ót.¤ß\̃y ÿ9;ƒµƠz *Ëåàggg¸´[OÛ¾̣Îå¨+x)\yçR_ ŸƠ)3O×¼bˆÏCbóMHë…²:X7–ư6Oé Ó¦ x�¡+đêb‡ḈáÍC|„mÓ¦«x­�:Œ+§N˜Œ®À7“&ó ”?„&è l°î:gÙ|ˆh&đë„bœ›˜}-3v%f�ºưa÷Tdy’rî‚ÔdM›;Ç̉Rªµ3#¢©¨†«QA†í́¥ƒ9"̀QÄdăÍ‚́!£«vdăÆÙxA¶%01ؘ¨§áHĐ=£÷’KÊ™T½qmíiϱ+â{ª±"KèJÓ”IOF©­,ëm´˜µIÚ*tNqư¼±;µjÉJüVïÈƠ¾o脌¯[›:²EOỤ̈Ö*¿1$CMf,YÆL*qªkÔcUö8wÆXn–Î%ä33ÉûhNÍ ˆÊơçQ~¹ƒÜ)>£ñă6xKàÑ¥¹9ƠUƲ»mU˜¿?<]1˜ĐÓŸqn›@Vc÷W±Ơ—¥Öj› ¾3‡R"\gDê˜zúiê9)�ÑAY"ç­;°^$WĐE[‹²áq�ƯA¶!ôÑï± Û%ö‘5ûÈöŒ}4/°²[4Éö ÜÖÙ/Úâđ(¾²~ /;æâR95r1i‡NÈ¥:0RÄÿÄ$ËÍAÇö¿éç2²ñŒ O1Lü"“1Æ/b ]´. ˆ¡£&®àÙ E_Ùù;»ư³Äăb“x́³`±‹x\4#ÇU}d^»G¯wĐGÇ x@S‚uѨ`ưâæ̣e}N₫³çø¨ư/}C Syüư ¥ô‚_‹P8ô¬Ơÿ¡½Q¥|q ›íµ'’q ¸I„X&µ¾@/SIùc÷k¡•_Ô`àëèI,©£ä‘'‹̣ŒÈDQLJCÓ¥I¼Œ¾‚̉5ßÀ7ß^ç }øq›>�#OS0d=5ïơÍ<ßÿÅÎ7½Xô“]‹”O�g8›¥É$¿ÜÆ™º̃¦m  _•üXü!¥»¦›ïOw8¾±ÁªvMkƯD[ẹ̈8úD^ĐĐ3rLëæŸ‘#†üa®It‹æjç\¶çË–̀¢sà_yÉÓ<KË£‚3Y(v_׫º "c‹y%̀ª~PÁS¯Éu iMÚ4„(å¢Dæ <ƒ@¨‚'ؤ&(ÈHB1 ´ÓMUĐ���ù¥­QY4ÇIºà)åđéÈĂÊx(ÿÈƠh‰›‘˜G ÷Ù%t\2fư“ ü®m²íS&‘„˜1¬`ŸAÂ! 3±€’Ưj@f¦b…ÄtåE@?Ô©ø̃w"̉óñ| àïÿ�ơÿfóè×ÿ–g½ÿù÷_túÿĂ‚̣ăÖ(É>üƒ0Ụ̀äâ#ûlX÷“6üd=U àÄơÑơÖ·üüéûÿ¸#?ÖƯξ;Ñ÷kƒñ[�æ­₫ă»Åpù®Æôx£Ûñđj‹g̣)ƒ‹v8” Ê‹}åZù¸8P@6å<Ä¡5 kjhÇ<'û”ŸoĐߨhÎV÷_x˜M;/yÀ#„[yD•¼Ơç¥WnÄ›­ó_^^¶mi?:! (8s"’¿nØx ®óÖ$¾Í¼Ù*£ Wq§ ø�•Ç ñà{ªß:ÅåT 2ÙW°24ZÎ2(€ªÏúŒ‹S‘§óx„CF7ƠtP™¬ ~ââÀ‰̀ß›kq®[0¶”;£V^±]'‚ÄlÉÊ0…)¦n)”Uô¤ûȈ/ñ–xiÏe 0£‚I?_i¦×n¦̉è¯Â¿ÄÅăt´xÓ÷ª¢Á(8&j\^ezAaîˆåß­~Æ̃UÜÁj÷餙}è¬|@°äíÓü)~(ÑjÛ/8vUÓĂE¶¼A¸ËÔuÛ+¦áĂơ�ƠÔQ-ôéÖ6–™‰£]¼ØÓÎzóp™Ë 6MÆ€V•ÊÈ¡¼NÇ/¹¿„™ư₫+&ÆÅ^é0ííBo4ư‡ẂR}Q>Èi„úijhj•V Sǯtä•àkp¨&7Á¬Ev¤́¢ó ×e¶Íí5”U|ÓoguB§+ê¬KR ¼ᦹëVº">Ùơ+ƠmÖV@^7ÜK¨~;˜®‰ZXhđêÚ:ug·ºÛ«(Ñ£Đ%@ÉBêH×ơÀE3c„2j›77K̉ª7xÀnơÔâü¢jẹ̀»Ô·pđA$7&ưöï!Jyû#H6”÷+÷Nümê!oKʰÜ;gøÖÎÉÙÆÚvœ¬cÏ1g₫�LéÜk0ëØ+a`È:öÊiÇơÇ›ßRÓ™Ç;¤«ü`Dä83}¬SŸa×f_•’‹M+̃;Ë䉾rs¦oÿ>=s·ă¢‘d_¹¶ïQ„ăíÈ–û' ß̃Yù,)ÆrÿăÛ<“GÉNÖ2ÿà,åj èÁYÊB"Aƒ{p+/¥g\“µOÅ̉k­ÎÛîF\úDxî"n›A¦ËÛM—·›.o8½©99n’iwG©/›ÑÑ—ŸEG_6¬£ïĂ•Đ�è[n†=Ĉø§!à˜¼=È1yÛÁ?&ö`Đj¼+¨Zék.uQP¯ Ạ̈Jh Ï ZéÜ.0tùx€ úÖÿPlÔ(Hn zDÈ]dnC¸ Ù<0H̃dlÔØàiÓ6ú†} :H ̃ĂPB¨¡„¼ÊCó/´ĐíD m\7›PCn₫ 5ô¿5Ôh(Ư¢ê\¥»•K›*;—î_vîpve´}zcz¬bv+ơÜJuÜê°#+b{ëÀ_Zư0^ă6 ÔDZ:ç‹„%˜4gDdF²8’±Œæ›M9.Á -”Uám3â%^C²ŒÊƒ>·%~À»7î±3ö ÷„g`uôz½^Q₫køŒ½ü†UÀa6xè³~ïêå'ËÆŸb& §Ÿ%á’µzƯGïAƯ¡›kơ%»Ăfđχ^·ï³₫Ûë⯧ô₫kœv́WœCjˆ#v{=h$åq³V¿7¸ Å’P¯.™Á;’9!¡t€¬Ơ|Œ{Å|Ö†Hbÿ‰Đ«h63Á&a’ç<ÄŒYƯ°3]‰¸ÿ|VäÖÿ½Ÿ 5Ôƒ>@‘èl5Ü8¬uĂºwØ”SƯéo»\ß)NüƯHæW#sñƠ÷oÓd’̣ˆjÿ�¼7<ÔE€̃ºăïNàêï}öêÅ‹́-púû{2Ù/lÚox4{Ẫ'qæ³ ±`ÿJ̉+Ÿơ=xÔ\Ơâ·  ũÏÄvY™\W¸æªgÜï1üéï™₫~ûêÆµ]Ú­Ôñä×ü×^ï̃ÿA¥oƯÓïuû́×_ñºíO™•~̃”<îÉó¶öäYlđ˜Y;àèÖv¤¦>ËÎ&ay^›ä„Đ©ư·f¶ªlL¤ß;ÊT6IưđeMeÅ—çÙ‘fy¯LöY®¢°£ôHïà̃_ï`×wPñí<–ù±vÉư&}~{L{=Ë ¨oĂ„(kÉ •i%IYRÄûúôƯë§,Já¤W }Æk·`â·†gñ<)Ï“J/"N"ĂŸmÁ DŸE¹ªϵ/(!C@Tô˳Bw¹vˆyªê—̀˜*35åáXưÊZʯ̉·—úp1MB¡~÷®¸[ư>ç©t ö¾`¸̉ª~8¸è¨!åg2øô8åĐçă\qW̉,"ç7áe<̣†˜É&[7co•áÈ'±̀çf¹¤̉i ¿P pfN%9i^ă!M…ªđ© \„™‚Eùû\d¹)T:+¬Ï.x®[ÏK5Ăă%’œ́‰á)í¤,Ø *OeÁö²ÛôáJ²m­ÙÀƠb¶^˜^7$̣œÁ7Øù#_ñ ́ æg¦ÑØÏgŸ™cê™Î¤5Zæs÷IÓgç‘•:gÀ{ésÈ€#‘O“¦è—œ7ª5:b8ơ ëÍùÁ1](8uø×doïHÙ:«µÍ"`ªZåäó<IÅ ¡\ R;]₫Îü¼öØM+6™"×í®€?¿eï~ÍxëªƯ½iÅ«v¹ÔÍJé×9h¨n­ àq°Ñj­¨ÙÀáđª|§pï\LÁ烣Ÿ^¤—càÿ/T·…ĐDUæî³kŸ!ƒ.O‡ót ¶ë, Eæ³Q*s‘Ê$Ö¯×Sú¥.˜û oè?ºÿ°ÍH`€:oâëŒ3 FüC ˜%3=ơ*ßưvxñ_sbÙ�5Fv «ơp­ÆÜ&ËB/IÀ½:à�K\a °jx¨‡© Û¬•›n<&'q’¢6!@°ñ Âz÷̀…B>q.&€¨7 ŸUñÜ{æ©y??¿¤_|6âóL'ĂêñæPÈÙñp °½.coÀZXÈLø…;¼2|‚jGëÉC#×&s1¸ơY”@G§¨Gb–@Ơ¼Ê±#v„zGóÑÔcYñ¶”Ê‚ä(†µ É´QPGç t0`YâQú‡ jL–¬ÅSÁÙ+éûÚ*`Ôˆ$–‘è TC̣̀Í‘à1#²t(TŸ¾ûñç×/..ß?öØS�{̀s'ơ"YFÄRÑËM".:5»"åªfÉwscÈÈ\DP,âéUg8C°·P®"q¹N&e†âçơY ­PHɫʳ_M,uY` Zn<ư/ÎèO5{BW:!Ÿ¸MùºđU¸àË ‹¬rz{́„1Bÿ«Æp­ÇPœđ(¹–ñ¤£ˆEƯgé+¾³₫ºÆíFôªl÷<ă! ©<_wnV®6»GU¸áe·ëvK8®Â% ùóTç°½̀jö´¥n¾₫±]Ïø(ØÜ»ß^3P­È{U.–ÖK‘æŸÚ¦¹³¾nêd®˜cŸ¿¹¸|÷æ§ÎûËw¯.~dfu³oâ€gÓ'6§™Ï„³¶Q0¦<å#p §ë±ç a‡>pnPi«2&±nª k®¶ûíèî†N₫ûU7‘oœ?I,2XïÏc·Ü<ºzô¦vÏŒqD¸¶Ù|†Bu£¸’ñ(œ1B­ä×ñÉ Ë(@©îÅ„ç°ÇÜ%–“ƒ~!Ê +w¡ëUy¶|ưa¾HöRÇöØzèà/Ÿ`Uưö”#`müEÊgŒ§É<V`¤•—f‡æ4ô„‰î¤[˜Ä}³~¯ƒîñ¹ªT°ƒ˜*8‹zƯSÖë̃e½î=� ÜEä�ü3@8™Àl*ÇyyG€Oƒ‘@} TL;¾{‚ñ+Í[™ålÁg3Q0>¸¦{F'‚˜¥C ¦—đ$A.k.J!¿D8ó�2MÁÏ`†~…†¬DÖÎı£©Ồ¤S¸à÷­–ôøŒGƠ¶ÆGëÓÆeC_¿r¹;Ăv_¿F•aecÍ03T1@½(¨¥EKÄîĐd̀­u——•J?øä±‹î³.U0sUO5 ØÀŒ¬¼ˆ‚êiÂs:]ơt؉pzÈæ1–I«jƠ+6[¥FÚi¤˜Àr¶*"Á".ï†LD2L&75Ÿ/ËŸ‡É$L&+Wot²?öJÈR̀vƒøA˜äơóăöOJJå7cÁÓư‡ñĐ «;SRơV[¶ &x¦o‚¯ơè÷î„ɤßkͲ ­7!iU+´:îtT8<ĐaΈt^2MÀĐ¢Xpλ—?¿»xñûçÓŸ~~Z櫱EiM¹nuûœ µ_÷º'èïwÑh‡è¢Æ…á1‘åÀ�OojeMgÊfỮ)PV[̃½8ñîÅÅóûĐÿÈ^ü>' Ø ;xHgóû¹7^wÙ?øÇư>ç1�£~â _±×<…ÈƠßÓîcđĐË~oĂ%„2GAÆl&R—¼Ê@ƒÛ%,« €fù́ŸIÈî?̣ÙlÆú§{₫Ư₫#Ÿ]$×]€c=́;0Ưư/£Ü‚.§Œ.Û>袛m•t‰tSŸaM}hg;¸Ïhzê5jº«¤X6N^&_ÅXÉ8Huߪ"Ău_»!öJ_ê¯Ö™ºzA ̣TÄ5₫eü¾Đ’Àµ©Ûj ẪĂr×`Zk¹{£Ô8PŸ(O“?+Ă/"MÑsơ  ›Q&"&O¬+Ẫ9.<—Ăüh́5ÏC>dïú}Ơâéái(-d~ö}Q-c³<Su«C‹l”Ê™N*tĐÂScư@ó̀<öM¤̀)<ѧ²Öƒ6¶çtKŒ‡%Œ6‡bï²ÑNØQC!ØÑ̃Á׆EÂơѡѻú, WŒöç6�/:₫üT!Lé×̀ô}.âgŸ¾ªÄA÷ôhfz?�ñÖOoKfshÛÑ̃êÿơsLØÄhïhú_¯å³áyG{Ăzë#öFé¥I–U„́óú́´JÆMÛ£ ®êímÔ½·O%ưúpw£Â{v̉w›QwÑ�₫£ôƯ?Î΂fdĂ¾›û@™²g^¶‚+Øt¶7ƒ×îÈ đ~{oƯ›^£7fÉbƒ¸Ïè²j3«f(ÏŒ-5‹<Ö£9RúöóHr���¨X*‡"̀X+xÖÆP,è"Á„ R¬Ë‚¶ÜÅ«ôY3ƒa§~ư›µnNú=ƯÑÄùL'c‰C( (¶à;x7ÄIJÀ@œP!‰-(Cl·^-}›̃:k}èô{>P/÷{Û̃7éÓ4}ÑÓ^¯ÇúƯ₫§‡ÿ­Ă»ípP'‹A0<x—FÙVNëL_¸ưNµM¾Wu[_«ÊÎÖ­vW™iư\.«?fí¶2Óø¹\W·bî¾2Óü¹\X_Ä4×ẽÁçre}ùïà˜î,óz>—KëOưźÖ2/¯Q×Ö>odK÷Ö1彜\]íb₫ĂƯ\3ÈơØ :?dxƠöz³jôp¥úµ×<¼GL₫Ô¡éSØë5hí—ñj'!!ç°<ͽWnJÉ^Î-“>´Î/`P–˜K¤…:*Q¨c_¢“֔͒ ïaÅFÉmêă a< qŸ.’ôªë±’ăª¦ơÓ8¡Æó±çȹ ³ÊLóÑá u•7…™ư@¾�…€2s(ƒ\¯,÷F ¥¬…"è’8„"+gS¬6N Óm›JxªíVagx¥³;äTàÏΉøóA§C îƯÿ¸:îó¬bÔº‡k²,L³ư«̀˜GHµ°̃3.ê–§’6μ4Ÿ‰aöËÉ(Ư¿cv†ư©ÎÓ(Á«L×°?û%n8=? …Ă½’9œNí—ÖQïcfwØŸ½̣<́Ï^ÎÄ7œûaȱ?GÈ1ÂWë-«‚f·̀*}c}¢ÈÊÙQ—*bI±?M¥ØŸ­I¬FaĂƠWđ™SJ"¥äûsŒ4ûs„„“ ñº{ꉳôÜ$³ÀUˆŒ†k5ŒäK'!™¡– ËØO2’yá¤*fĐ’F%:©{Êd©U²Ka]ă¾�º+´€P!VZ2&!Ç ¦¬3›réîư2f2g­L̀!ª\J¡œŒv—½£dËO…¬›²,yúWÏÍécEf³4¹Qÿ$MÅ̃Ç?æa8䣫º>Ù3s¬DÓQ„tm¿üđ¼z®m]ơÛàJ÷+zo{üôË+±uK+}Ùå₫ó·/VîcqùY*IKJ¤i’*)ºÚRißç »xs‰'¯_œ•úJ–b.’¯í–ˆ…KoËd¬:E=µFYu̪֕0̣ÈK²ÑÊs±Vçëå«‹Ë÷Î{(pzèL¤¤;S Ê1´Åkñ'®ï×Ùđ‡;Ó0¢½Á›öH¾wp§©fđ§aKÍFôh !E#OÈ‘ru.üʲF́ 1*5À‘; ÏYÖº92v¤0"b]iC²¡Â÷^ Z ¬ơñ#đD̉yY¿Ç G­røvEú&2örµï°_U» ́Wlér€+Q¿ôs8öü8NđÏ(;ăYñ}&³Y .¦­qVƒ@+ ŸĂPàœ¶Î?Ur±„-uüÓ%) }�+¯Á¦bÂ21‰_qEĐ{´Î+Á}éé{P 7&’b…âYU#XI2cÑ<̀å,”¤D­^çé³-=‚6ù[ ˆ-!q`̀y…PR_gÚÀ£âƠƒ\¼4Â0¸ĂjUÓî±—< ô49Ï\g·¥²*ú§Ñ7Må{rú›ù–đ M# †0üV%?â ÅƠ*›•‡¯Y[— ²^óC§@­5ŸÍ’Œ<£XÁŒr¬¹ Ö̉ |Ïr$ˆˆØSwdñœ|Öä§íuïừ28ñ¸²M¹;8Ïúâ*x·°£6P &ÎytwJRƯøKŸæÛWÄAáŸg~ëŸö_ùfïûjû´—ưTd€DnÛ7·H:#¨í"B—Mè°؆-îú»ăU|Cẻ@3ÖÇ�ƒ“$u¢Ú6BS´e°ÉRtfc¸ ¹â&t¾=ON3Ị̂Tđ\­µbơ:»»ơs¤æ­¦�F!LáœĐƠ8GE]'§øN‹qeëçá¼ÓïOÔgÎG,H¹FÆI:TªiàöœV<xñ è ‰̃JñôXaJר¼R9´FƠ¬º¨œƯnÖøÛ››_Gru©×,ôQ×­ömÖ|{û^Ôn¸&ú±º÷ỗ:Ë€¤xư¯ç¡Ë×;}A}©“†"LxÓH¥GÈáY©lđsû0TAỊ́‹ÇV<v…”=€à éË‘Y"î©©Æ¥}5[ü plø,‰µ,ŒLùÉƠ¥m\`å₫I„f©ÈDœ?Q¯#ƒ†¬¥rb“8\ÂDykØ_‹2G-¯r»ß®âdÁ¦É6˜uAT?Oy+QRW%%¡cFD¢¤Y&sV6ŸLD–3Î&I(1æ³Y( p[&`ß³á|ÂR1K̉¼"Ü¿&ÚoeƯº@¿¯•/:²íTWi îU¤JÁJâ©‚c;(AœÄ́—qêdË,Q‡<RÔ‚(ƒ¢ƒh¹ecê¸ÙжjưMÉX)Pó®Éñô¤kct´mĐ7Ñ=Œ v‹7ÿ <…J]˦|†•RăÖ€¬2ˆ¢Û‹bô¡ø@ ̀ÔÏ´X•©»i·Fi¸vf ²»?’€u½ĂyÂÀ­ă(Gµ+Ơˆ¢²gߘ[ơ@5¯êJ(猢7Viëkº?j>$Wµ@ć2[®\·‰EËû¥C£äÆU×A˜xed®ƒ¿üd^qă–ÄS½X(H¸‚¶¯¸ˆ“´¸âèị́lơÅ)®à*Ă¡pP\¨b+!O'?n©±Âœj­(“_CkUIëÏæj80dR~UùTµ�ï1•K3'L\¥ …ưWnñ’ß"-°3­«•¤jµQÆê¨W&Cçáré Öy X§Û[ {%ñxM«£²n0ùBˆ˜ơđ$èw³êCq˜+çƯjĐ9æ¨ Dz²rÀn(Pk,*—º£ỵŒ‘WzUôaë±ß7ÜÈ!“!È so>Ï450MÍÑƠM9Åkmp<êR!ñô«ÂsUÀNås-¶P©E@³ĂơXµvÖë>éQh�J¿ª'!̉(I å™ưÊ'¬np fΫwúEH¬’ˆæ}ÙZƠZÑ´^¢›'¥AED˜‰R̀Çàöeớ¾¦Bz¾ 5)ƒHƒ¶ (m}ÀëE­gn¶²7w‚›iŒY9$nu^ưt›åy±ü}|ß-èG¡¬óHíƯ¹P—––“ø}ÎCXË*.œv­!:4đ÷¥Êăfÿ ôŒ f ₫ûâí!âÍǡӺÁSfÙ®F¥­…¢Fy*í/TÔ_¨(³LHhu)Ä Œ³̣‹Œ“ǾI}ø„OIE”\+8í/5yE($éÊjƒ›ËÍ«v{Ư„× ạ́!Vø²̉¯,®{ü̉->[­œ-U©ụ̀éWư¤$tÜV<©4Ê ª°Qqq„2ÇB2_‰táS+Ym˜•% £~«+ `?FŒª²}�áS6ñËV½ÛIkàƒĂu�mx±R»<øm 9<đà Óq²áŒùPdNF›ơ8÷¯¢©�I…Q¡âЬe‰öÚIa‚ fjæTÔ„d½¡xÉÊÔ*Yan­`[�>P]}RÖCK8tÖ›§æ#F{(­“$¼V{e¹‘wU-µMØbT^ĐrkƠXiè€6¶¶ÊTnŸB$+íW8LÇáDWƠ“r¦†ü€µ¤µ €̀ê�WÂW{ n¹ç»(7W§¶+e³’̉q¬$’¹É[:.VP/m®ÖAXA)û2:IÚH(n”u npÅÆ3¡BVªà2Ö+hÍi¯”lw§› ~µ×;+H›p0Pô#3'¢¯œoÙĐ /D…ÏFÎe¦¯°ëQÅŸ•³ˆ*­p¾¨H«̃º₫÷fíÿxO*tñj×ERKMÚj`O\æw‰Y B|ĐŸ½xưọ̈_àxOÚ¤ ¦¸¥‚ÜÖü¤‚‰|è ££/¡à×NUôÜ`sĂ%[¤R¶™u”~øØơl9�v₫æ{öâÇW/̃© TŒçY™p C&¿: HÈj%B½¤*Ëœ�Öó8»’aˆEá �68–x&Ă%´̀G<–ñ³*ÔbKÜK±¡Hf\2³Täκ́2ö È|Q5áøU_$6IWœg®ïˆ!¬8`CøeÁ—ʉŒcÂTÂËPĂWvô,M†|êgb¶>ªÿgV—Ö©îkÓ,O°]¯¬đä5Ûä®@y<;ˆíqtå í—»8¸óºÜGôĂ¡đơ·}ª<î–}aŒ½›k³?QRä«k%£Ö"x×Ú…•öË«‹̃ü±óŸ/_¾zs¡Ö¼Ăd¡CÄĐg—á¡tfÂLđ+̣êMá„£Ê@„ÉPdl(°jŸQ•đ&˜Ù ¾y(%>‹È”ø: ¯•æBg4>'s˜8Êb́i¹º ;‡ê,“rƯ¤<˜ó^<I¸ºâ Ó ?Ă¢|l!øœ¨¦ïJ´CÈ›yÉă˜µ�#ăIÛgS ’ùlÈÓ<9�…B>ºx́³qÈó<™-`XùÈeüË'<&ÄŒƒ R€'™œ̀̉d{î ½7{ÑU�uç°1µü°_j"đMp–&aØIÆc–*q¿<; ĈSR§Ù~]#cÈ1¢`Û.ă¹�!¥c`„YăCX/ưAđ #'º zP»ØGƯ¸oÊÅ~J¸c+Ûá.cÿR’UƸúËÉÿpIÊ‚T+Q%÷ ³Öxœ·fI–Ïx ßa ÊÊùw{îû½v[ 3#A18ê†Eô_/̃½aoŸ₫đĂ«‹iư—‹ÇK-±Ü)t¿dY.fj}ỳ1ÔIb›uÉÁNÈ%¤*"od%àĂ ¬ Q£P;3d°iÎwThUE“ "%_�”M[å£ß-Ùà77ööư¬U­v¶Ëꀀg±«\¼B+ÎÅÎ…pæ:¯êº®´¨D½ë3¦=Ü\xCï^¼~óOt¯_<½`çï̃¼fï_ưxñô'z]ª+ZÎÊOBu`MhbTq\ 4ó@àWÆSmçS×Yµ‚÷„#ñ†|ẂI:h²fú`͡ŒzåØ@*x‚Ù‡¡˜̣k™ĐI#•}Xđt{™,ĵV·#" ƠJ„Æ­ >¤xj<}w3ùæ‚=sq₫ê¨>Ä^]\¾x÷ϧ?½ÇgVÆ~*¢c=Ă%ô#›§º$¥x³kJN6æơ®Æö²lÑJ–.QđG>Ï2©T̉���ädˆ('|iĐäL'ê`¼a4ƒHÂĐO p ©}fƯ*­ŒøéÇùå)è́;¾ …œÁYêBá]Tô@ÏËr @Y¿ăyXx-Ïß¼~ûộƠ³W?½ºüûåƠåK‡UÖgïúN!:ß,è*<Y%ˆ•›Æ„fR~ü,kduíáŒC¦ÅEXơƒđàSøç®Ï½̃}R„à·aJz¿mđ�Ê­…Yha¬0Å­kL¥A$cÓB‡3êhá^c¢ÚE‚û³(||å"vNó€y•¿aHz¶iï´Í~L ¾e°ĂI’Ê|j<°öüÏjtÄcøb(HÚ§|éú ü"¨’¨ùÅit*àÑüĂj'ó«sÉ FÔ "Öcö U<ç!*äôKÇK˜¯L(à+»{æGS›ć`> ¤4ªŸß?ưñ^m£±*uÅÈÆ a«ˆb§3™À^•I?;”OŸ¥âúWŒ3¥xøØv#W̃̃Üøăg[aN»Ư®ºÙÍ R¥ă™Ơzl†ö+…Y‹¼q£TA@B³Mç´²=Ü—W¦²NRÚn*z₫®×öµrỉnƠô´M₫öƯ‹¾zóóû̉Ël+öáé8ªè 4çt’¦áñqßä¼ë÷;ÿ±₫mê×Wz«ø6 ˜;eùÛß~èJ¤•Øn:Ȳ‚¿ưÍLÿcÜög‘Œ-îÍGE”ggƒ;3é—¤Ïö¸ØưQ@º—¤̉úplăé­ ÅÅÛ«A×ø#'½̣ÄSwuĨû ₫½Ûk@÷ ÁÿG½üÁ·^~é¥Çj-Ø]|„÷]z›g浟<ôíë#[²î-Óá7`²øâ&›,î’)¾ö̉[W×ëM‹›Ü¬Ló¯l¶D#%Vđ—û[ñíV,$›¢`0âÚ$°kËàN×4®Œ”k‘…¸}Às”ÏÔ“p^8«ô2a<Hf¹yZ‡6Kón! A‹IƠa‹đ₫&FÊʲd$O¥|6†>Mçˆwmϲ rio›Q±Âë®™HÁVă“U•Ëßv•ß¿ëoZµu‹ư–¬å¡h(§ ëv”đ4s-₫µ‹VƠuMÊu]- 껾0°º:géïóX0L\r*·ÂÑ7p̣đ,gçÉ<•0 K̉È€́T4@ÇE]»Ûăje³!Ï §€S×"åP^0Cñ>PK¢çc]+¡,»„>pdz§ó@&́ĐQ¤ %ó,—£ŒjÅ>ư¹Ó¿×‚Sq6cz§v.Ù/2 %ØË.{ +—jỤ̂yÈvÙ¥˜_%avE¶·¾ô²Ë₫)�6ª<É"’±g`}²·]vB[ªEÜ Jná!¸#åŒ|„Ï}Ô§xvG†¬Rà²Qùî26ä n%(­·Ñs SLû9–× ´çKÚLS=ä½̉û§Ư‡§/ç¡€ÄƯơùă}¦.Ü!\·Ü@95å¤#₫û 9§¿QoĂßhÍ̉å€WêơîaÛđÉ£sĐgYà#mÈV)å4”ÖCÀ|2̀¤nª́¯j› ójQĐÿ‡¢ó ÁcÍç�ÿ›À¢Œ`‹‡aÓVlg‚¥§§la¢eÈÖä8a;n¯̀V)MVILaÔ+aîơ¨âË)J&ÑÆ$MÅèª`u¬0£T>àVœÀoZFƯ5Ènº]unÓBDÜemåö£:%}©ÀwÚLÅŸƒíôV@Îÿ";ư‹́ô/è÷¡d§́ª¦Ó/ä´b§Ö›–”›¿¨Mÿñÿ/ñÿ9yçÑ-ăwÛd;~GkÅß1oª2îúñ±ÅĂ­ü|, ‰ÿ‚ÛеîÉÁ†¿*ŸeÉè_±ôGÊwØ´Ơ>W"ƒÙhôçcL15ñ¦˜ăß°+U‚ÚHûN8v»(÷*ù³¦ºn>̃êºùX‹M{ê”ÙkwÚZ¦ưFv˜j­YöTwd·ºĐ¦3{•ÚüÜṕ ÎǘUCó–ÏÏÑKc:ó·Wq̀/|₫[ó̉™Ü½ª^₫™'÷˜Å,yß«œåÿ̉y?r•Jç­́U§̣/ƽßû̃²æ–ÊđÚ:˜J/¾}å0§©ƠL+ÔZíôbÓ+ Cơ´t_ơ¥  BÜ—¾`æ‹ïN¦§Û鮫OẂ–º5ä̉@zÆBÆk•ë~·Ïœk·W® 8\»vkV½. î�I­¡å~Gîr‡ (ø‹1»Æ ;©,§›oc ̉«•¢2ÿö[’½2¶™U›l:1kÊÓTfVÖ€/ßaq•ÓÀú*´Øđ+²ùU¶óWn£öZóĂ5 œxÈưƠô$4j”o²e‰<­›…­Î3ƠĂÎḰ⤩(ó[–4*¥k5C»¢&JƠÔZ̀4 Më‘#đ+EÚ́@ẳ¶ô)†]>×Ñç­åæ·}¹ 9¦Ú›™̉ j*²2N¯vœ¥—ä ´ØUpóSf‰�ƒ2¯)”z;Äz<Ïs†äú)+]¿»`7jN²«&#ÚÍ@o‘l×>popÀG–îz"̃0 Ë÷ êă>ªä_₫V xµêPÆ_q™éÀÏ!>™F| kđ.3Wî Ơmă ÈsƯXĂ’Üë3ZϰûèbŸU=HnF`îưî=F—í²l¨Ù&Ö ´Ôô‚¡Ñ|ÆƠ²JÖ²ơ’9àm¦b¸YPÜgêºíß·iøđ®jö›Ư%O°Qå®ÁV8´yM¬œÍÛ¬÷’p6í<Ÿá2›ë]Ö<ï«IZEƯƒH$²<™u†)ÊsÏMîVíˆ<<+æÜ[Mæw¿×ƒ+̀>W)bXhÔPgÂ'å1úPvĂÜwGå¨ư´ŒG¦.<½<Aä%~̀²÷©?̃̀À¥ÂzÈu]̀‘zÄù4\²_Gđú;q-Åsĺ¬?¸ùa]vÿ̃½Îưû=Ÿ=¥2dưG @¯5ÍóÙă““ÅbÑx>ͺù(èJq̣ÿÍBèăÉÛù0”#œ́{Ùă¶3¢ç]ê½ÎS6§)hQ.bM†i„’#Cfaˆ ÀẸ“Â3¦‚óeS93u†‚CĐ"@î…�édbBAç̀ÈÛ4u1¡Îg§wiü§§÷:§wë́YÅƠ2 ÈØ»×¹Fñ©P™ÄG(°j~` ´¢N߇sv‡’¬5“́»:‰ÚÈç₫KëªÍÎXgưO9{¯Üt»®X+a€83Ï´Ơ?´ÙÆéï̃¿[<?ôÚµƯ‚—N#đo€‘$NrMu°¾Àøír€ËNºæ7#¤₫] ÄË4e4ɘCÓŒ+™êZ½B’¨†“„ÆY•È*ÚJªdă í¡Ç"~## ÊCÉ)ö<]îej4d^ˆ›Ùf•á£Ë¶×t³‡+ Œ® «‡³!v[ˆR—‡³)oHÛpfg?•êÎOn›æfç×Aopÿ3­Æße>“2­·s6­¨d1lÙ$†Tl®=Lvă“$“\ĐdưđæùùƯ¯Ø4ă³¯¾>óæa\óÙ÷w¿;ÿÀ.̃Éæµ§¯Î.ṔäÈü¤êI*[/ L€Ñ.+‹º;[†µ¾™ˆ'½6Vê‰Í]t¨Ơ.%Ö‚*c½¶¯¼MX=i(ô£xÀËJ Á³‘׳¥Ö#5Q³â²r˜@Ú”vB¡r«i‚X̀ ÚÁuWZ j)(¾4ư«P›!ÓNwÑ2:½ÓI†¦‡ûŸD>¹Y¶ñÁg’¥Ưp.=tXF·?›Üæ?ŸlkÍÚ´îÈnYë ³Q˶Ùa)bá ¾Ñ`Åq¿1N±­Ụœ]&³ƯÍù̉h5ơ%>SOÔ¸µhÅÜ‚†Ùë³ëw¢™5`3Émö-ëwđ£»ôQÁ˜ê@¢îÇøư}sK¯Û; ೇê:û IŔŒIem,Ïz£N_å[¬ƯÀ°I÷DכȌ¡~.Tu…z™̃ξƒ&(”Ÿ(œ#ư*FyúH(ÀÎ 1¹Ärá8` ḥŒg¹`R9C&P8B¦r2eđ)ïµÄh”¤˜»'́Cÿăă‚‚€¶7d·jBeƒµûx(‡)' î`NÙÇy‚<̣±˜„r‚8–K¤©S€¸ƒ~äđÙû'́¥HĂù8ƒ×Ë'�f|ø ­6ÎÏD´�¢R´=-£‡ŒÙç—�tôTÍw™±Ö[à¼ye¨yŸ¥s¨Í£Ùö߸HÙ¥Mét&· »Hº§ŸE¶ºát|Äô…ÛŸ¶éĂOFƯV³ç¢Ó-8Í=›b•»w o¯%VlôääÛ₫ !Dî<RJ=g[+' Ơ^€ܤ k‚ cÔơ]. "¹æ‚RúIvÆ<M1ÜÈN{oí�đ^(:."aJq3c-Öiñ;7íǸzLáÆv¹ÖÙŒ^Ç�PZ˜_"æú…¼03Ä ]vTcKÑD1óI T ľØîzPp=›&ó¸SÙ˜*Â+Ú`Œo+Fd0#·'‰î₫ ]́U]½â)mÁà@d˺ÈÚÍÈ´-0Ï=¦¯ÜQ¨5¤îë¶ Ôn‹ªo†Ø¼P;b ëĐ–‘w»*»®ŒkRÄykÅT•ˆÛ]Àq]Q!ơ ªs-ö–r-%ă"-ă"ŸEíC¥àÿ7I„>ƒ«¶—Ôæá’�ÚiV Đ8nÀ¡5ºû›Ú‘ |p£¦}Ón |¨h²ÿ•ßb̀á »¸‘YNÆđwYQ- G_}ÿúéåOOŸ}w‚_|_"$‡rB¾®Sd;ăAo*†£ê±¢e/G±jư`]‘Λ΅rLo2èv?¨¥fO=[p>¨á5zB47¼ í  ‡*ˆÿÀîj{a›¯€̃ÓTb=8Sii»  ©0,D3ƒô?»́Íl&â©y´<ö®Ë~é²÷£)C¸‡dƯ2¥"K°,ßS™(@è�’F3?ƒPGPÆód́öºª#©Ñ#~Cª˜2ÏÙÍYÉ́ˆ€œ!Đ¾‡²Ơ3€œ́÷4oơ;­Á›“¨Ưư÷�P9WPèèŒmåĐÏXt2`r<c7ê¿ÑÉ`²SzxµKyŸh\’‹Y fß$jOàûöâÖmÿp‘k[kV́º#»¢×f£â·ÙaIMwߨ²~œÁ9ÔFÔ<¦3‰₫Rço¡:¿›ü¶T‹™Ê‡×<àé'± ­Ä]f.Ư¡îm½Êº±fE¹3¬Ï˜̣{ñ¥eipϦÅsÏÀ€vX;¦íFá¢ûƠ€?���;¨ÛƯˆdo¡ïÌZ¼{Ơå]Ø̃x¯€ ¼§÷vBˆº¸êwđ¢UÛ`Ó½¯÷ËöKÖ´|øUM5+ề€¾̀$¸LLøsê‘7åhÊù2L̉-VĐf.ƯåÔ¶̃¤Ükî×Ô¾bo•Î÷ Œû^jÿÑwL‡¤ÚxÀ^ œ·}†*\z g ¨ÙÛ‹bóK½ï»_eăG½½¼Xz’UºIÁ1ºfT¬¥S:ï¶ÙïsẸ́̉#.Ñ"ù3>r̀K€²àw>à9£T°Pa₫«̣I<¹ü&’ñ<{rÚkS^UÜî̀(á0ăVúÉ¥CEă`m“©* >•læ<6¡A6M±}ú;Í ₫Øc?$"M—>û&ÄŒç<ça2æ»á%¶~ĂTˆñ¥÷2˜�¡*,™ƒ^ÿÁ>‡³J]>ü,†â„“MñCF×íp «vàÇ–æW£9†·màƒú°«Ç~CyEÄ¡9ÑD*\/z¤$+ƒDPæ$]‹»E¥n`›ºàYêR1æ$ÖÚ‡nw*ßâwªüFÚ̀®o‰}˦5q3³ÜàatYax%Èä^JqS–>¿Ë-tàGL_¹Ăæ3m7°ưT[ o@3¦[àü7Cl–Æ¿Á!VÑ?hF^B÷´äiÁ*gWq²ˆ¡,î‘Q’ÉXtr8ÍL¾C{»m]o•w]Ñ@0Ö3D¤øÄÅjƒ#Ô—Đ!ưU—8”¨ê'l;=¼¡¯üÓ́Ạl«ƒđ₫z¶ÎsŸúRe~¯kÁ6ĐSÀF­^Q®z•Z”Z¦2(F›yE¬Ù}•jÆR{ç© æï]F!ßS!”74Û*1ƒỔS^̣4‚ÄGöTgc˜@€Ik•̉£ºË Sú“bªƒ“„Ná@Vû÷}HÔ`}ŸưÇs.Yÿу‡¾Ç̃BEđû|öâw¡?}¸pnÊA1ó-܃Sn/™Mˇ fƠT“ùé«„íơ´ö7Ñ|{¶v3OG…º';!Tv>%ô|7è₫₫óÍ7ÏM-U2ÏRëùoĐWơç›ÿpå„Í¿}au/à6ÏñưN•C‹æ{ÓIüæ)ÏfS‘b>ă®Ykđjº— K“0s ;C±â2ßO‚Z-ƒjm¾QỆ©LB*¸î#WÚö¬«ˆđi'¦ù6ÿÄæÔV”[QĂÊæ£©eGTÊCÏăVÖ¶\dER  ̉ ‰ƒ¬p“ÙăDó>d"ÏŒ÷‹Ù!¸₫~ôOeÔÿ°N—±§ ¼ÇX¨�Çy-ăIEpOozV¥‰Z™`{«Üy8ÛÚD¦:ÆŸçư§XOw"IU?Ö́ û Ö<îØévÍúóÿ$w³›%ƠW\Vơ5)Ïx-̉!Ïe䲂ÁOëơÏ:]1€=‡²í́?_ÿ¬I®N^·ÙGŸ±+HÖöACív»>{Ưéû%páëN_¡ mNús]Öµ´™udøG1ñÏEÚvèµô "²Ï�晦OIQÂÔnÛŒ½¶á?ư23ưMÅÇj¤Ïa2;́Ü´"ö- !Û¿óßu~:€öăzª¢ÂÜȼ¯ø‰:o•wmMÏmoÁh‰ÜÅßḶ'đ‘÷L ¥ï›_áMwó£zöW÷uŸÓÚñzɰN+Z¿AùL’–KbØøÆs‘F°8Úk¬F»ù j,ØóåZ¸„.s&ÂD½©Ç¯¤ÚT’WU¾d#9®³ÊK•¯?ƒ€l`²Í ¥Ë˜!‘ó(Ă=”›dŒÏ�ơ@ù2Ë pÄ—,æé¦ît¸Ó^tqç)̉@ʘÀ̀è{@¤´=4]Nʹ1Üd.€‘Eÿ{_̃ܶ±́û??E—S/&"(É‹¹.eK‘¼_Ië”Ë/5†â�‚…U§îgƠ= �àb’¶r륇&ÆLÏ »§—_³ø¦ƯÏ|Ÿ§xxóÅË·¬où'½ü@¹ÜÅÓö;Ù0úS̀=aúL]FœcߦÊV:ZđG© '>wm…‡€­Rm8 ®QZ¹߇Ϡüï”t/^âXy|¹„—¶½ fôäĐöà5OÄ5=~j}åp…p±öSl /©O2óáƠÅ̀My,’T¸‰­%ßô.?Yà́î8»VƒP%»ưƯv·ót¿0ÀË4æ"µà¶Àyñ|1<ÓÛ°ëă ’#IHa@b2c”¡âZ¤ÚD^¯D¹R,±¥¿Â†̃%h·+!.Îó¶ă<×CÙÉüUS U(fcĐäÔ·k ÷ƒúÊåư9íơÖf=Ăùœ€gØLq£áMNqK)áfâM߯Ä7•.»đ­\†TºMçlc̣xƯ¹¥´œv3ØùĐvZÿ·k@pôµcI›³öymç›:̣Íf–ËdiÁѹ]ÉăæOsÿ3!ư±Fåö™‰ơf•Èó®ă‡œ¹CàÊU¯±XØÅHx©cC3v”%)‚jL·ë˜3\́O]åÀ³XPră g>hs'„Qsg>Ëg+"µÛ‰đCÊU˜4ï)„(¸Y„æQ˜é¨ÄÄơ…KsˆÇ̀‡¥–̉jèâQ¼/đ¸$÷·Ÿ^)Ôr¬Qf™³"Ëf8Vƒ­›Å4·¾7SJ“–g‘ẾêÄÜ妢»u);XnĐ]¿†óL³a 9<¨÷mJûJmĐá₫À9VƠ=8›4ö̃ µ̉FBvëP¥.t5qѺQNÅOgơÙ@»%Ø,Ê/UZ%xÿK¿ñZj�ô‚ 0ÏR5Œ>«đ»…‘ö`áÁṆ̃$Ø^~8+âÊm®çí%ơümŸ{˜×?P€₫sßV^¯ºßvA₫ å_—o[3˜ƠúಸŸÅó󽺶̣²åŤ&»¾˜””¶Ơ¬÷ÔŒk¹Y>ú£™·†¨¨o“…>ßT3vÅë­F4ÿ—đºâW7è́ÀW¸>đ•î¡PüaYÆüÚcŒ94{-́‹,³eqÄçwà±”ÍJ_Ưj<÷ßEÊ)±ư‰ÂåmuÖ‘-Ä‘äq_S£ñç-}~Ñ}T̉†|::a¢®ÍÆ<Æô ELú¬cîe.¯ÔzXiØ‚  WÊ$"¼@rưÅ™lè]€îën<ú@r'Œ&5TMÓ9?zˆÅE‰§–ª‘·¸HT{‹y,œ .₫øü₫äĂƠ¥ôÅ/å¬ăUCá zj¥µGl̃nl@ú<Æ̉×Ú¢7¼Ä0 “œ=sư�cæ‹ÜΩ ÅáXx̉—\7À©Ûr(í„û*›Ë\`¼ĂÑ%•cKBK¢,a–4Ô÷¨ûÑ5̀<<0‘§8ßøt. B…1/zsq§ƒH¡‰éQoÙDùOß³˜àvÏ– Ü ¯‚̣%G;=³*\Ơ{{₫ÊUŸá×ÀcÉđXÅáܱä¸wSîÁÛ̀÷û̀½)9”Íô¡s7èäײ̀̃¿̉ä ưù”̣±U -Nï†ảđB3O_êÆÓO'37(ơ?Ê=Û„¬Ü ÅŒ8A¹|>^ÑA˜ƠoŸi_íÅÉƠç‹'¯áÏ̃»Ï'k½”Lï]_$™m~úÍi•$5¤ ËÉô¥½'‚(Káw>̉$±7Ô£—wÍ ơûQ½fI.Î^ËơµVI7¶Ó5©ôϧߜàXáH‚µŒ[6~ƒËÏï5oZö]3hß´êh7G:Z6ƒ̃]§ưÍ@̣w†ow8ÀĐđ0eR2ÈXrơF<6=Ê(>‹¯Zë)E¥Ï�u²êF?>泿ZÆ•n̉¨|Ô=A¾·¢̃œ̃–gçFCà_›¸È\Éóđ%˜‚$|0ÓUế_a¦hå¥ơƠ7 TŸ„Üb -›̉fxâÊkdđfE pQ¢F—è– é%¦"̉6*Qkgà’ëÑÈ×zÈư<Æ<đ4@@³Û‚s9,/ ”œH)×nuö†‰j*o${%+ ü®î0 .ú‡F›¤(NYèó̉R|KwJf VײWÑ¡[¬\¾U|˨%µ†È¶@/^ª#Ê'˜v+ñYO÷¬ :úåAÁGßËfróãE_0·êằbhhµÓؘ gªèÔIF¼ßmA¯lc’‡¶Ê²S1_¼ØĂđ<Q!QO"ÓÏÂ]1b©ÏúƯ�©cî¦%hø¯Nàă¸<yẉêêüăxuq~urq₫ñC₫>ôÎ_Y€zË‚·ç¯hd’!H¶Ïđˆ%Ơ“yO¤•7‚ôEiCâÖ÷™Ï0UBFĐÉvÆĐp-!r ¶ÊF.»Æb°†¸¹ïë}%hăD½ˆ=5B)OĐ�ơë`²™q”#-%•{ϵ:o¿ă¯ƒ‡ÑÚk•äQ÷ˆmRÅ9aœ­̉íDÇbăëˆÂLÖ©Á×½oḈÅÉéÉÅɇW'q„đưoÂa€È7<.æîAÀosh₫”B̉gª¹�ƳcäÙTh&ø¡wơ˜7Æñ I3oçA’4CË>˜…4“ï“Q4dø¤¤ÓçÀăñ-y¸{n˜Q\Ù‚“ q‡|àµ÷Yà%ô²klƯØîî¢=÷´A₫µû .S‘™÷6Y”ô²ÀçxÇn%Ϥ1obû çÀ¥–|† Æ̣£­#Đ 7ƠO±"%’ááé Œ>ƒ³û¼Óvöœ˜?–¡o'öî7ø"|_°œÙsOTºFæ#œÜÏnB?¹‘óÑ—^Ùđ'ÇNL>Áç̃´º>Æ̣,ødcgˆ àñ$Ÿí‡l¤ÿ1wE$¯,’VØ•!@B Pª›ŸÁ£³ xÀ¥Gxđú±đ®y!+A΃ºđëḤ̣RI/g×.”C~Ưû½¾×~‹\̣ëa˜±@ʰ÷LÜ38æ7,fÅí*q<¢»|•+ È\¼è÷1Ï{,¾¿ùË©gˆK( ˜Ê‡¨Ú̀4y*zØï6n‹{w×Ùkïîâö|˜yñ=±y„];bÂâI&mÈ9À.ÈËVñJ²›đ"¥­LØ̉îÍ†íø™6æÏ#ư³ưy?ÏI9h%¢e–¢¾¯- iª!§¿0U§±ÔK™ïzÂå‘{½ÖT™ñ̉B5¯)ç/{5)VAªwQ:Ñ,"1® A‘dT˜u•[‘º© UwÎ*´¾(Ÿà!§«t²ŒŸÂ@*ÅCÆ¥°Ø?¥úELÊpw±¸ygAÔ¢lL:(à ÈSt•Z*YÛdÖØ²m»Đ[Ä���ÈeCÓ’³pà̃1îsw–Q÷SR£[Δ+"ơù¢x+ËóÀƠÄ™¯÷F'fT'̣¼@¥}:GGDIT6'A)¯,1ùºÉgĐåξđ1†,Ú=RE>ßǵ£dj½ä‚ünièó˜Ñé3»³@ƪԹ²Đ2ñv8¡aBŸ<©¥¡>¨á‰ơ,¼åc[x¼wo$`ù±xtE­ÆœĂy~ÈLy‚KoÔÊ, :̀˜säÚêUcÜ ôë.¨ë–W°†đúV‘"¤–3Bj9¥?ƒcù¿̃†¾[½e”€Wó̀:µ‚c+èm�îh©¹º_Ïxk“´¾üØiºu:û}üĂ«úkä³€ÿTvX_¿á¿4̀<'Ї4ô 7pLVúu 1fŒ’nÇÍûÖN¯yO™~ÇÍÿ’´¤ó@†shYo€^÷´QørG8-fÄáéëXKK¿Ô/~*ÂI­åÈ{‚ăiÇG•ɈUE273m+×£R̃2Ó£1IqX¥!r«Œđ/6ôü$´Êug@ 3…6:]’Ü\\P̃¿>₫é85H̀ƠÉÓËî‹—yº./²§/¡&’.b1aV¨uØ�'c¤™œüeÊŵ/̉ûö{÷8\k¦óí}jÜư ] ƯKa!.yv`z.ׯ±tœS¼…%I6̉*rÎÚ& ÉGräœáíDG6Á¶ZĂAᙪ•Zw1ó r[%èÈ‚wx\¢E!ÂêåW®ĐK1}í±¹––ûhj!àêX®ˆ]ŸCS/][z²¤aeÁ}[n"ZƠt“2Ưß»‰¬NÊwÎ夆̣™,L3¦f̣R¾̀•¯ª~?ïoĐá ‹Ñîoø]Ô¤�NÛi=9m̃´Z2XZÉhâ¸@_;–½ÿMù§q'Üß-¦“”éađk²T[3f©:U²–‹Z)ù‰flÊă¦Óµœ½Ö¡ó×3ë$¼ylơ,§ûÜüx<´zCü¹([÷,s÷Ù0¿/Ơß{"‰I‹ 4ÿç?+ABë?ÿ#ø?ƒÇ–;6ÏÚgĂV«uX‡5JXbIî‹}cĂG.G"ê¼ö+íj•G¤×ª²åTnU¯CÎ@J S>¾rr˜<Ăô¢È×_(yù§}¬Xù4´_Ûˆ́‘đ8eÆm‡¡ *2ÂÂ"Yud‘»tÆ^Á•gÁ›,àè´Üµ ÂXÂ~çÂØ2¦it°³ăºñˆÙ‰¢`s/ÛùŸ‡É:9`Ø¿Ñ%÷—F�ùëyú×{Ê]±‡éÈßA,°È÷ô₫HV6É“ ÚäÉC5Ê“mXå fụ̂̀d;vùRµ>ñgì\2AŸư\nä†èc̉ăeLQe}*ù3Ç�=C½f¾olÂÍ-ĐœÈJ¶géÙ˜²=§\'LÆá:S̃̀@’ü´G+l3+ÿµ©+B62U",³Vµ‘%«V1´TvÖ<cëKÑđÓ¼¨Ùé6l€c8‚¯ÎNœo‡:ØƠ£ïßÜûjv¬½¢u�p¦´B†Ăm₫ĂŒá€/Ă­åXNáæa~7^]¼‹Í[ë+ë'ͳÖ!ưoØúf’h|Dđ?Æâ“¦[ß«nÅs*<árÓÂüP6Õué²^¶S”•ÂăxÆ<Y_»̃/Đ®û‰÷+k×û j×û‡ª]ï·¡]̀ö'h×ûíh×¥&úđ´ëưÚÚU9z~ºv]Í¥ó ÔjRSÔ°<1E¢ơÿumåù{oêø}Z:~?¨£÷ºÍçc$á|@†®ưô…Ëë¶œôúºMÓzxµS1,Ÿ3q�æ6”Sa¸ºÉ¬_‡Ü÷Etøăù±JVÏ*iöu÷EĐ~§̀¿c‘G„úcN9s†<BOv“¹ƒ¦sµZđ„:Ú·ñ‹îAô›ÓR@&³ơ«cÁr#~ÓXZEᩪ¥|RF&? PzQpm%2ëN™¯y€•Ë<LLă§̀I_…˜R!ærEĂÜÆÔù J»N@ª»‘öîSƒÄȆVÛ± 1((—–•g<=Ưè4e ˜a²âUªüQ!‹¾¬L4¬2‰ù�j³̃ft|)n®ÿ¨p³•̣đơº|¦¼}”檌Àbv¢‹Ù2«B›¦Ú�̀Nư‡¥l®£a"wry~ä® WàTJä>ü;ưúIa뫃h£ đ~>G¶˜ˆ¼Ú*Zo½-r½‚½±µễw6ˆ¤û0¸³‰dLÔ¯5äa¢jnÝ¡ûóTYac$|$1÷ºTkºä°¡KceyT‘ $<À²äåÍy*-e}ªPUa?eªip¥Ñ t •6”…RÀ·¯+¢¦2́bBh¦`/L‰4Í+ró¢ñ:.·Ó¡<iZ Q5ͮ‘s #©ĐÍZ÷+Vé7¦·V]T7êßœÖ7ƒRÙªØư)5EÊ•Mi”AV»ăÔÔ…#`p"3DtÊÆâơ’YŒ½Ù§úU–Æâ*¦4Ô+X,Ë ưlÈÎÍ×,öä£Xˆ‡©¶cíÊ™à;)ß[J‘8Ÿº`6ßÉRxZ8¨Å˜3»ëœÇ©—BÓ«IVœ)ª~ị̈§+‹\T`È”Ÿ¾j¦®Zúx´AĐéư¸`)o¿²àÏC|™¹XÁ½́‚ü đ'?­€ơR1†Ơ€^PntÙ|§Å®í€¾pyă2'½¾…©im×i1²ÀĂ²‚]4È|ơỰz1çÚÊ1µ#ˆ a†Á?Ëñ=œ̉ô«̀†ë¿ÓI½ ‹y—€̀RJUz|ớM]©]†%AVâ/ ¥N/c*+°©YE¨–^Nh~h÷'í¥Z¬gŔHH ₫ÄŒm̉L[«]ùíkw”z£Ÿ£{Q‘xR˜ Ïû+™É—E;Tr¹ = ¤ºªđ¥ .lÇV1Ẹ̀¶ç­ DLĨƒ5ÚpŸû90euj̀ø;®‘{l=z9TZÄFÑKå|)ï Ü–ˆáifŒ¬±GèØ \Ú:M¼œ;l̀�¤^“äˆa#n:ë2"¢Y8Ă|²ư Á(ÜĂÑƠ£ÅGcO½Q”Ê� Zøx¢—¥!úÊ\ Ï&I»» ú‹¥T”¯¸Ù(evh[‚Ơë *Ô7І´D» «6úơlX´1́‘NEg•́Û È‹TƠ{G¦Æ´4Û//g' {¤X˜Cl&´0ÄUƒ_†kä5Nơ›J¾s¶ƠƠ$"Ÿ\Y~P½vÓåUÚ-X5º j5+I‘[»œÅă.• ̀‰.è W0' é ˜ÖV½V“¥}493¶r„₫{S6‚æÚ6=[k¿Ô ¹}??7èưúÁǜ-0鈸`›ü5ám î A˜Ú“rBo¼LÅR˜j×-– =đĂ[D₫DèäT0_°¤Pí‰ú óœs\P5†(²”–§½DÚ#ăÉ܆b7 ¨¨|Ư¼{.œFºÈnTz+‚²·ÂÔsX–Q° Đç̉j˜ư®PS+Uh²K†é2;=¿0a5ƠÛƒ™Œ…Ư-&=»œÄ!Í™ºµ®‚—=}Ñæ$œ5:+`C{Ăi¿ü(Û˜̃E.e1æœÜ²‰,ªE$% ç™øá­?AßÈ„Z¶ụ̈‹6Ô鲜₫΄{“_de”&]ˆa2›h\’$jŸLXOh!¨!Á ,9C@_~>p7âU½5..Ë,ü.-Ñ#ˆƒyF¡ïcÏeå9Âå₫DÛ\åéѤû#…’¿²YA)*RKt·¦Gđ™³¤́¤Ø¯é cwœƒîaƒầîPÄ4S ºØû8-Ă₫Θ‡UUºU�ü†f&4»O"ñ$}̉±)!eGùz`¡8}KȽʹé8]cÚN§Ó±àN}¡Ѿ>Ôyœ‡ê)‡0 }<SÂ/ª‹÷Ê$'Mç`·@1>|­FăM“ ¦¬·±„ÏHóæ̃.ä—®`đÈoÀä3ÔÑW`ÉV ˜™)9çˆá÷ƒ8W…³>$<ă6ª´p, .„RòăIí#Ó!p™2««ÚwéS±ßU¡ƒœ#¾tå—{BBêׇJr^DS¨0r£PY A’ræÉƒw¥>êE…́€3ëa!5³*Ă ˜%¢T%N±q(<lC¦ổE%»fî TG<Íä¥9,Ơ¥Ô±]w₫Ó¾§Ù´f ¥ÎØ&%̉³,È¢ˆ½�?ȯ6�'ÏX ÷@;#–Ï­—d7‘Y”ˆ6>™‡|êV{¢÷Gpl‹ªLṇ̃aœ·./+~ùâÎMñŒfOîẉˆ̀ÿ¶TÄœ!»O₫~üæà‘QêØy'Gø{åc¥Ê= jè–¾́Øû3ç½yǽï‚G®8�âYăÈœ4àîˆÍÔêZö¾åt¬Çæpñ¸ơ["‚C…ÜÍ;2ùU6Â]«…‰đXK�¿3ǿ¬ß–k#Ï æüñ„ æđ±ÄÙ£’Àd@|x^ "…{÷¦¿Wº¿x™ơ}ÅY¥ú{•®V¶kkVMhnƯ7O\^»æ¤×ׯÖvåơaƠạ́±ñœQÛLÛ¢f6¼~ºùgó³~7TØ¥XW6Ơf¼¦gqÑ<Ç ¬†¸Sï†+T+{Eđ…¹é¤Í(± a…yÖ§:…ˆQ”ù Ïˉê&*‘́j¼hÂÀå=˜ü$¿“X/ S¼̃RÇ;ƠƯŒÓ‰‹»,.82/ø€àߨđµÑe7B"ÿ¾¦õ³ ôñ;«a€Af0hàS,W`ƒ==óD¶b,€‚ •=<=y¶…༡ë1ß'̃g6f/E6<-¯û !ˆÿ´á#Ff‡\Œ°{/B0]ºC6PđDolụ̈8soh¬%¼í 7¨¹zùW ^Új˜µåÀœ/^¬+ùƠ)màªOsËË}Cx}±¯H-úïBæQÇG-’¶( 7¶"Œ†›û$Œ´qkB´Ơpsæ̃•+â;6ÓRfÄ3ăXe;mÎŒĐ´ÈA=gƃö”®= ƒàÇpí{¼¤gIô!¼JóºGµh%Đçé-çrơié\¯a)[^ûM5‡j¼¦Ëx áỲæC_ẽ%¢œÔ“C5.(i(ôưĐ½©4ft|”f¼ç1`s¼›ËŒ₫„ÆRû=Áă's’¢Kש|è= oA}»|*ôÔCWË‚NR–rúz>î×í@áÚåeséë‹ç¹­Jh=Í%N‰5kÈœ̃†äq‘MÛÉ?—MU¢¹/‚Muÿ,2����q›Ó‡̀Ī^̀äÜ7X́÷¿‰Ç?SË6¶ù₫6}gÅ5¨:Ùˆ$ ¯c6J–÷¤}ç:m¬FµÈ»§ˆwU{FE"ÿ4î>ûî₫ ‰‘e¢« ‰¸4µ(Ọ́ó-Sevi””P₫8³–*đ“å>}Îû%.ÙCEÑ. ơxRÑ¢v%YU¢óÁô¥ÍÇŒ—BÓéttXªµˆzQÖ•È_©j6q‰U»fUI€%aY?²�E}ƠG{ÑHbµ4’®ÉœP…Ƹ®ùœ}‚ë QÄc™e˜Øđ§¬¾³ÁÀåHÀr×V_T”0 ₫æç«ïXíâ^Á;úA.ƠơÆê‡·r¯.́|3-]J”Ï Ü0[¢Î”ª¡ƠÇ,<°%•Ü9`ă0K# r–—6—Sm ˤù®:̃(—H"ŸMT<«XÚ²æyđs*|‘NæœƠê ¸êïËŸ₫̀#V;÷ơ³Á€ÇøØ9‡¾}Ûyạ́罜đú‡=Ek›vạ́>%͈́Qª÷ê†Q£ie=«ø¼Uă¯>pz¿x†Ë+«¯Ï\u~Lạ̈w¤¡F›Ä ;YÈ&_TdêQ©Á˜¯&Ï«: ™:Ơ”`ạ̈"Ó9j¼†X̃^>Æ$v•h®:«®ṇ̃)¶"bÎtô!đ‡Î^‘…©ƒ®†\̀dÍÉâÁEƒëå‰1>¶öL‡¬¢tX» e ‚rJÊ”̀ Û£¶ÑÇØ5jª˜̣æĐ…eƠ¥¦ị̈<dÎâÙ™\ß¹ª ÅÈ«„pSĂœ÷.hœP=eÄK™33[ưªÇJÉEh b„GHbb°‰¶‘*soó‡“Y>QƠÏÊl”íơLBE!d—“Z ¬µó@ø¾§CèâñêẪ̉ÈM.±pựNt¶q^è©E÷Î@†˜uÔ2Ó¾\´Îéazóv(‰¸BǛÖ›÷J–˪¢ê(扔Z䡳7£Êáêâ$mäà(µ\*×·—ß´”çL’S䮘Œy4ÅèHŨêe cè@ˆ¯Ë­Hxµ½=ư.bÖÁµÏ•iä|ÅÔ˜ç™~riHÛZ612p¯J³+ĐÚú·Ú¾m”ḶÔ»?æ#&$/5DlŸuf}Ü9…JđF^?ܬä;qĂ‘[̉V\Xüúynö ƒÀP₫Ê1PGEdi†é†„Y\©@ñO­>Qc¡U±ó”TL"¸^;ÏÍơ³üy½À0îBụ̀å äéǬo&—)n5,¢%¼»¥íæi>­a?gAXăô”yÙw3Ê Ơe~@ ’}¢ô8đ³£{3Ơ s¸RY@5²oxà©¿éÚU(›P"”¡¯_o2¬ª$h>%)Í( !̀0k½º,YE©G\if²ùk“Db>¸Ü÷-́\.î98ˆ‹2Cøƒ9‡È.Zµ4´$˜µ*çN₫‘°´—E1•F‡â …!RQ(-RÇX{Yµ@R|«)-·AèH¸‹ˆ2qxkÆ;µ¤hKêâç¹aq=q8:§(, ñve͘YTnºÛ0¾I0Óo /¯Ă6øßÙ(J ökp7“xY—,³Ùf}+JËÀÜd(‹å.˜+——‘âë‹GĆ\àƠVü › Ûå<} ??ˆo+&ú^∔¼¡óÏüü̃f&‰èûze$A« G5ÚVƯè”t̀K$ªLïan¯m6'wùố.I‹µ¶É6b±›æ÷̃·÷@]·¼�2„×?ÔVͲ¿—~Q 'ÖÁʯ1nH¼hmS¸<0U%l˜›Û̀aùÇp³â—4ôç•ÿ½ GQ¦°„%(œ́‚ó&ÿ[p¦ăOƯĂ•S )¸…„̉ w°Â9ׂ“ÙÛỒYÖÍ“J}¥k G"%dº´T=èØ�½ Ó‘�ÍcDØóyŒ¨¶³T ÷`Ä&Ö \?ó*P{*N÷<JJ@nDB *¸>đ@䆣’Œêe¤Û(±dPU/BCúa”÷—F¹ Æwá6*×ÏđÀ'—Ơœ Ë+Ăórl<rđó$ᾮ€4Η0ÿnµ§ÑđP¢₫$÷eËDØ\ÿ.«êæºỲÜ Ư$F"ƠÚ,5ơ6j�z‰É”“¡d¢8́³>âÇ K(Kø óKu5²ơîbƒi¶‹L¤CÅ›D5†€ ܯÂ8 ă)èϽ ûʆËa§¦|¯ �øóRÀ«¡hKrDJ<¸À‚|L8‚?_G£{{kSơ&s/¡v¿‰í†£(ë›"µO<QŒK Æó+öí}0W.opˆ¯orb[5:N—ù~¬!ôëô¤µ¿œv–̣Éx—¤ôL]Nc·Ö:ÊG”ß̃ÄẸA:îc4ăµă& !„§³x²u3–F¸îQ£‘2¯åËV?guȽåa*(]q]�™[(!ÔR·B LE-H)„X–¸œ\u—\%†°)·̉¥=pZˆ¹Ù(Sr4ÉFyÿ́)2±À{ộq®²Q’ 9h¦-û‰'h¦­&¶<=à÷­ƠÑ<Ëà£}WÁ<vú/D'–pZđ"O`@åăÓơµsI§ÍY†T8­¶gÅéö×À‚Ô‚ƯøWg¼Đ·x›ßmÙñ^}EÓ6¸N)?Ÿ~oµ`§ø̉¦nDˆvjÁăđ±¥.µÉÖ&ÊƠàúÆR‹µöyP•ÖwóøÀYưfoY¡¶¡âq(q˜¡ºU1~—.-Ç«xµ»¥>ëåj‘¬¯1ƠKư߸˜“àŒ3à$8 v¤Ü} ¾é €RÉBlgçJ_BỞ(³SÀ’Ü\TH÷® é )™¥w+wÉøC ©€sÆ¡ŒO<”+]HyccĂƯ×Î7Ù+4İ_�¬OMàøÔÓ§LW™ ›Ÿ˜à…œJPœV#Ç; î”̀M3æë,—·dû7´§ª’5SÖMƯa‹ëïæ3P×­đBjÂë¿…Ô)÷ÚßúcÙ7N̉¿:]ÏYÜ�wfÛơK¶èư4s^đ.Ö{/g“BÇ~ƯOq¢̃§#g]†‰gu;Ư§‹94ë@×2Èû1mŒ}…䯪îÁçºq2?ê ¹t‡xv| ¦dm&Gg…•á|ÙÄ{ñV ø0?T6 kyb$1̃u¬Û6_1¿.đgrNà<¥³,5q*µ̉©0µûY%¶¨iT]™ï!s²Ua'”a˜S̀+38F́f·ª¡Ö2¡ư9IăÜoAÉËMas¨b(Ôÿ r$hz­6<v‡·êyÖ!‰f|fCuú1Ï”19:m߆J1—ƯDÈÛ¦6Ä0æ Á�©[)£™%Ø₫uÏw˜t₫΅<H\æ3lf•É«°̣d4¢jQ`1Ê¡cM±‚k_Û₫Ǿ›±–¯̣8êT’Œl+ 2Rë$É[<•ً뉋F)ØY%%Zø¡k‰–ÚtdÑ»W`/•f@Qßê<6oJMƒé„¹-d¾‡ëˆÖ¿‹|Tt:)8”°đỳuZ‚xIƠû€¹q˜$”ư’@[n$¥*åăhI léFJx Ÿ]ÓSgÎúe›#èĐI¥Sj qz„̉iÚ¾oĐ3±î›–›óllúNFk8ö>téOù_è@çtALIB%₫êØ»àØO¿áY³ü¡ùơ&ßdḯƯÁ?åÇ}ưÑÉ¿ụo»ô­“;û±[A¡3û±„?L²,¨Æ…0¥Ê°ÏÇưS„NñKû3WŒÀ•¶øÚöœÀ·FƯs(^¼:ć|Äæ`>̃ƒúŒÙJ{¼¡ˆR‰{#à{¹7§“–F“9îC å‘gDËĐ»ÏÙ]²Ù•JÍ¡&Ó‘à XƯ¡2¦r‚Êù<:?¶Î."cÁg.uÊ-MzÉåÚ> ơl¡ Î̀=6–H·Ô;†™ïQ†sCÙ+2·Ve[ͱYqÖ1xU£ư<5'?À¿WÜ|ĐäÍn‹�öÉSÖø5îÅñ!€£BƯG£hª>Ö<åkÛú÷[ƠƒÚ₫7çcáAs¯]ßÙ·1¬çÛÎçC=ïÛ/€®Z^Ă(¢ë«"ô@tâÁV”IMĐ|ee"ùơ0´Èà×*•|²°ü.Åt°¥eºÉä­ôêÉ[TX2PËü|U#äó ¤gƯÆ|¼¨À´xƠ ¯)ÑÜÀ[óñCyI‰ëï¹ÊƯs�_ª‰·iLTØJSöÈbCayy?đE”yưß×̃MXJCf,r;.M_½üî*?cư]V¤·Ư(NgéíVæ̀VDƯ<³Yăd$Å 3K•{ˆ)³Ù€eL&Ml‹–÷4à®Íî„î:«Z̃×4Ÿ]a·Ê–Qq¦³Ætù-À Ó Lỷ.Å¥ư_3ä̀£­vª¿’{µñûpúêv?ô&ù¿3Úg§?^9`óÁÑ£_^|uê<zÙDo>{ùûÎpŸ¸đƆ3»ñ̃}åsßgW6 í'FèÀƒwC ¬/ÔªgTö[ŒÀ¹„¢€¡×”Œ¼>F©e#}'Wâ! kØƯSÙ!ÅT`ŸœœÀÙ‚Ć^æ‰N°wI27̀’Ô¶ăĐ·¡÷¹ƯÅ0ö‹g»D‘ û§¿K†‡ûƯ}[.ï*<ê–xÔ}ô²Ù-óèE"l\b2̃¯,ù‡7°áTesL£!+|c™-m¦ˆhÀø5vÑÎXàơĂđÙר…$6$¸§“½.m€·6¼ì4`đ©­̣±-xø"|>ià—”ößÂ¿Âø†P€ÿœư}Å¿î³gv£™KĂ,ö5o†i%;;ĂpÄ#́?f§Y ́ØI‘;v‚Üa7b‡†ó—„yƒG/¿ûV\„Öêë¹[ZÏƯG/›»åơ|kĂ¹;×Ü‚÷èF½e¸ àZæ•Ùp E¾Đ=ʸK9œäx3á�̃‹@îr¹̃ïd5½ Å`ñ—iư‚}%b7Ăx�­›LZ³đ'î₫½g|mjÍÖ¥¦g´„Îsµ†NÇy¶:ÏöJ<Û{ô²¹7Ă³̃Øđ+E‡ĐĂVẦeqxíg†E'w²­Ö[}¡r�8e#áçEÖ—çŸÎߨ‰Đ4ö,èe×w;Îîw¼½û¥‘ï?zÙÜ/ü̉nÀ̀ăjèg6œñØÏ ¶uT#—£¥D×ÓÓ+`ó'‰H ù [ç·̀®¸; ¨̣ ~ »VăŒûüÛ3|ùœÏŸé¬Bynü¾ƒsÀo†éÈÙøÿ…_í��� �m�e�d�f�i�l�t�1����3�.�4�.�3� �m�e�d�f�i�l�t�1������*�s�i�g�n�a�l�.�h�t�m�l�#�m�o�v�i�n�g�r�m�s����3�.�4�.�4� �m�o�v�i�n�g�r�m�s������,�s�i�g�n�a�l�.�h�t�m�l�#�s�g�o�l�a�y�f�i�l�t��� �3�.�4�.�5� �s�g�o�l�a�y�f�i�l�t������&�s�i�g�n�a�l�.�h�t�m�l�#�s�o�s�f�i�l�t����3�.�4�.�6� �s�o�s�f�i�l�t������6�s�i�g�n�a�l�.�h�t�m�l�#�F�i�l�t�e�r�-�A�n�a�l�y�s�i�s���&�3�.�5� �F�i�l�t�e�r� �A�n�a�l�y�s�i�s������,�s�i�g�n�a�l�.�h�t�m�l�#�f�i�l�t�e�r�n�o�r�m��� �3�.�5�.�1� �f�i�l�t�e�r�n�o�r�m������&�s�i�g�n�a�l�.�h�t�m�l�#�f�i�l�t�o�r�d����3�.�5�.�2� �f�i�l�t�o�r�d������"�s�i�g�n�a�l�.�h�t�m�l�#�f�r�e�q�s����3�.�5�.�3� �f�r�e�q�s������4�s�i�g�n�a�l�.�h�t�m�l�#�f�r�e�q�s�_�0�0�5�f�p�l�o�t��� �3�.�5�.�4� �f�r�e�q�s�_�p�l�o�t������ �s�i�g�n�a�l�.�h�t�m�l�#�f�w�h�m����3�.�5�.�5� �f�w�h�m������(�s�i�g�n�a�l�.�h�t�m�l�#�g�r�p�d�e�l�a�y����3�.�5�.�6� �g�r�p�d�e�l�a�y������ �s�i�g�n�a�l�.�h�t�m�l�#�i�m�p�z����3�.�5�.�7� �i�m�p�z������*�s�i�g�n�a�l�.�h�t�m�l�#�i�s�a�l�l�p�a�s�s����3�.�5�.�8� �i�s�a�l�l�p�a�s�s������,�s�i�g�n�a�l�.�h�t�m�l�#�i�s�m�a�x�p�h�a�s�e��� �3�.�5�.�9� �i�s�m�a�x�p�h�a�s�e������,�s�i�g�n�a�l�.�h�t�m�l�#�i�s�m�i�n�p�h�a�s�e���"�3�.�5�.�1�0� �i�s�m�i�n�p�h�a�s�e������(�s�i�g�n�a�l�.�h�t�m�l�#�i�s�s�t�a�b�l�e����3�.�5�.�1�1� �i�s�s�t�a�b�l�e������$�s�i�g�n�a�l�.�h�t�m�l�#�p�h�a�s�e�z����3�.�5�.�1�2� �p�h�a�s�e�z������$�s�i�g�n�a�l�.�h�t�m�l�#�z�p�l�a�n�e����3�.�5�.�1�3� �z�p�l�a�n�e������:�s�i�g�n�a�l�.�h�t�m�l�#�F�i�l�t�e�r�-�C�o�n�v�e�r�s�i�o�n���*�3�.�6� �F�i�l�t�e�r� �C�o�n�v�e�r�s�i�o�n������(�s�i�g�n�a�l�.�h�t�m�l�#�r�e�s�i�d�u�e�d����3�.�6�.�1� �r�e�s�i�d�u�e�d������(�s�i�g�n�a�l�.�h�t�m�l�#�r�e�s�i�d�u�e�z����3�.�6�.�2� �r�e�s�i�d�u�e�z������$�s�i�g�n�a�l�.�h�t�m�l�#�s�o�s�2�s�s����3�.�6�.�3� �s�o�s�2�s�s������$�s�i�g�n�a�l�.�h�t�m�l�#�s�o�s�2�t�f����3�.�6�.�4� �s�o�s�2�t�f������$�s�i�g�n�a�l�.�h�t�m�l�#�s�o�s�2�z�p����3�.�6�.�5� �s�o�s�2�z�p������"�s�i�g�n�a�l�.�h�t�m�l�#�s�s�2�t�f����3�.�6�.�6� �s�s�2�t�f������"�s�i�g�n�a�l�.�h�t�m�l�#�s�s�2�z�p����3�.�6�.�7� �s�s�2�z�p������$�s�i�g�n�a�l�.�h�t�m�l�#�t�f�2�s�o�s����3�.�6�.�8� �t�f�2�s�o�s������"�s�i�g�n�a�l�.�h�t�m�l�#�t�f�2�s�s����3�.�6�.�9� �t�f�2�s�s������"�s�i�g�n�a�l�.�h�t�m�l�#�t�f�2�z�p����3�.�6�.�1�0� �t�f�2�z�p������$�s�i�g�n�a�l�.�h�t�m�l�#�z�p�2�s�o�s����3�.�6�.�1�1� �z�p�2�s�o�s������"�s�i�g�n�a�l�.�h�t�m�l�#�z�p�2�s�s����3�.�6�.�1�2� �z�p�2�s�s������"�s�i�g�n�a�l�.�h�t�m�l�#�z�p�2�t�f����3�.�6�.�1�3� �z�p�2�t�f������:�s�i�g�n�a�l�.�h�t�m�l�#�I�I�R�-�F�i�l�t�e�r�-�D�e�s�i�g�n���*�3�.�7� �I�I�R� �F�i�l�t�e�r� �D�e�s�i�g�n������(�s�i�g�n�a�l�.�h�t�m�l�#�b�e�s�s�e�l�a�p����3�.�7�.�1� �b�e�s�s�e�l�a�p������&�s�i�g�n�a�l�.�h�t�m�l�#�b�e�s�s�e�l�f����3�.�7�.�2� �b�e�s�s�e�l�f������(�s�i�g�n�a�l�.�h�t�m�l�#�b�i�l�i�n�e�a�r����3�.�7�.�3� �b�i�l�i�n�e�a�r������$�s�i�g�n�a�l�.�h�t�m�l�#�b�u�t�t�a�p����3�.�7�.�4� �b�u�t�t�a�p������$�s�i�g�n�a�l�.�h�t�m�l�#�b�u�t�t�e�r����3�.�7�.�5� �b�u�t�t�e�r������&�s�i�g�n�a�l�.�h�t�m�l�#�b�u�t�t�o�r�d����3�.�7�.�6� �b�u�t�t�o�r�d������ �s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b����3�.�7�.�7� �c�h�e�b������&�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�1�a�p����3�.�7�.�8� �c�h�e�b�1�a�p������(�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�1�o�r�d����3�.�7�.�9� �c�h�e�b�1�o�r�d������&�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�2�a�p����3�.�7�.�1�0� �c�h�e�b�2�a�p������(�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�2�o�r�d����3�.�7�.�1�1� �c�h�e�b�2�o�r�d������$�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�y�1����3�.�7�.�1�2� �c�h�e�b�y�1������$�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�y�2����3�.�7�.�1�3� �c�h�e�b�y�2������"�s�i�g�n�a�l�.�h�t�m�l�#�e�l�l�i�p����3�.�7�.�1�4� �e�l�l�i�p������&�s�i�g�n�a�l�.�h�t�m�l�#�e�l�l�i�p�a�p����3�.�7�.�1�5� �e�l�l�i�p�a�p������(�s�i�g�n�a�l�.�h�t�m�l�#�e�l�l�i�p�o�r�d����3�.�7�.�1�6� �e�l�l�i�p�o�r�d������"�s�i�g�n�a�l�.�h�t�m�l�#�f�i�r�p�m����3�.�7�.�1�7� �f�i�r�p�m������(�s�i�g�n�a�l�.�h�t�m�l�#�f�i�r�p�m�o�r�d����3�.�7�.�1�8� �f�i�r�p�m�o�r�d������(�s�i�g�n�a�l�.�h�t�m�l�#�i�m�p�i�n�v�a�r����3�.�7�.�1�9� �i�m�p�i�n�v�a�r������.�s�i�g�n�a�l�.�h�t�m�l�#�i�n�v�i�m�p�i�n�v�a�r�����!�$�3�.�7�.�2�0� �i�n�v�i�m�p�i�n�v�a�r������$�s�i�g�n�a�l�.�h�t�m�l�#�n�c�a�u�e�r����3�.�7�.�2�1� �n�c�a�u�e�r������F�s�i�g�n�a�l�.�h�t�m�l�#�p�e�i�_�0�0�5�f�t�s�e�n�g�_�0�0�5�f�n�o�t�c�h���,�3�.�7�.�2�2� �p�e�i�_�t�s�e�n�g�_�n�o�t�c�h������&�s�i�g�n�a�l�.�h�t�m�l�#�s�f�t�r�a�n�s����3�.�7�.�2�3� �s�f�t�r�a�n�s������:�s�i�g�n�a�l�.�h�t�m�l�#�F�I�R�-�F�i�l�t�e�r�-�D�e�s�i�g�n���*�3�.�8� �F�I�R� �F�i�l�t�e�r� �D�e�s�i�g�n������"�s�i�g�n�a�l�.�h�t�m�l�#�c�l�2�b�p����3�.�8�.�1� �c�l�2�b�p������ �s�i�g�n�a�l�.�h�t�m�l�#�f�i�r�1����3�.�8�.�2� �f�i�r�1������ �s�i�g�n�a�l�.�h�t�m�l�#�f�i�r�2����3�.�8�.�3� �f�i�r�2������"�s�i�g�n�a�l�.�h�t�m�l�#�f�i�r�l�s����3�.�8�.�4� �f�i�r�l�s������*�s�i�g�n�a�l�.�h�t�m�l�#�k�a�i�s�e�r�o�r�d����3�.�8�.�5� �k�a�i�s�e�r�o�r�d������2�s�i�g�n�a�l�.�h�t�m�l�#�q�p�_�0�0�5�f�k�a�i�s�e�r����3�.�8�.�6� �q�p�_�k�a�i�s�e�r������"�s�i�g�n�a�l�.�h�t�m�l�#�r�e�m�e�z����3�.�8�.�7� �r�e�m�e�z������$�s�i�g�n�a�l�.�h�t�m�l�#�s�g�o�l�a�y����3�.�8�.�8� �s�g�o�l�a�y������,�s�i�g�n�a�l�.�h�t�m�l�#�T�r�a�n�s�f�o�r�m�s����3�.�9� �T�r�a�n�s�f�o�r�m�s������.�s�i�g�n�a�l�.�h�t�m�l�#�b�i�t�r�e�v�o�r�d�e�r���"�3�.�9�.�1� �b�i�t�r�e�v�o�r�d�e�r������"�s�i�g�n�a�l�.�h�t�m�l�#�c�c�e�p�s����3�.�9�.�2� �c�c�e�p�s������(�s�i�g�n�a�l�.�h�t�m�l�#�c�p�l�x�r�e�a�l����3�.�9�.�3� �c�p�l�x�r�e�a�l�������s�i�g�n�a�l�.�h�t�m�l�#�c�z�t����3�.�9�.�4� �c�z�t�������s�i�g�n�a�l�.�h�t�m�l�#�d�c�t����3�.�9�.�5� �d�c�t������ �s�i�g�n�a�l�.�h�t�m�l�#�d�c�t�2����3�.�9�.�6� �d�c�t�2������$�s�i�g�n�a�l�.�h�t�m�l�#�d�c�t�m�t�x����3�.�9�.�7� �d�c�t�m�t�x������$�s�i�g�n�a�l�.�h�t�m�l�#�d�f�t�m�t�x����3�.�9�.�8� �d�f�t�m�t�x������2�s�i�g�n�a�l�.�h�t�m�l�#�d�i�g�i�t�r�e�v�o�r�d�e�r���&�3�.�9�.�9� �d�i�g�i�t�r�e�v�o�r�d�e�r�������s�i�g�n�a�l�.�h�t�m�l�#�d�s�t����3�.�9�.�1�0� �d�s�t�������s�i�g�n�a�l�.�h�t�m�l�#�d�w�t����3�.�9�.�1�1� �d�w�t�������s�i�g�n�a�l�.�h�t�m�l�#�f�h�t����3�.�9�.�1�2� �f�h�t������ �s�i�g�n�a�l�.�h�t�m�l�#�f�w�h�t����3�.�9�.�1�3� �f�w�h�t������&�s�i�g�n�a�l�.�h�t�m�l�#�h�i�l�b�e�r�t����3�.�9�.�1�4� �h�i�l�b�e�r�t������ �s�i�g�n�a�l�.�h�t�m�l�#�i�d�c�t����3�.�9�.�1�5� �i�d�c�t������"�s�i�g�n�a�l�.�h�t�m�l�#�i�d�c�t�2����3�.�9�.�1�6� �i�d�c�t�2������ �s�i�g�n�a�l�.�h�t�m�l�#�i�d�s�t����3�.�9�.�1�7� �i�d�s�t������ �s�i�g�n�a�l�.�h�t�m�l�#�i�f�h�t����3�.�9�.�1�8� �i�f�h�t������"�s�i�g�n�a�l�.�h�t�m�l�#�i�f�w�h�t����3�.�9�.�1�9� �i�f�w�h�t������"�s�i�g�n�a�l�.�h�t�m�l�#�r�c�e�p�s����3�.�9�.�2�0� �r�c�e�p�s������F�s�i�g�n�a�l�.�h�t�m�l�#�P�o�w�e�r�-�S�p�e�c�t�r�u�m�-�A�n�a�l�y�s�i�s���8�3�.�1�0� �P�o�w�e�r� �S�p�e�c�t�r�u�m� �A�n�a�l�y�s�i�s������<�s�i�g�n�a�l�.�h�t�m�l�#�g�_�t�_�0�0�5�f�_�0�0�5�f�p�o�w�e�r����3�.�1�0�.�1� �_�_�p�o�w�e�r������,�s�i�g�n�a�l�.�h�t�m�l�#�a�r�_�0�0�5�f�p�s�d����3�.�1�0�.�2� �a�r�_�p�s�d������$�s�i�g�n�a�l�.�h�t�m�l�#�c�o�h�e�r�e����3�.�1�0�.�3� �c�o�h�e�r�e������ �s�i�g�n�a�l�.�h�t�m�l�#�c�p�s�d����3�.�1�0�.�4� �c�p�s�d�������s�i�g�n�a�l�.�h�t�m�l�#�c�s�d����3�.�1�0�.�5� �c�s�d������$�s�i�g�n�a�l�.�h�t�m�l�#�d�b�2�p�o�w����3�.�1�0�.�6� �d�b�2�p�o�w������(�s�i�g�n�a�l�.�h�t�m�l�#�m�s�c�o�h�e�r�e����3�.�1�0�.�7� �m�s�c�o�h�e�r�e������"�s�i�g�n�a�l�.�h�t�m�l�#�p�b�u�r�g����3�.�1�0�.�8� �p�b�u�r�g������$�s�i�g�n�a�l�.�h�t�m�l�#�p�o�w�2�d�b����3�.�1�0�.�9� �p�o�w�2�d�b������$�s�i�g�n�a�l�.�h�t�m�l�#�p�w�e�l�c�h����3�.�1�0�.�1�0� �p�w�e�l�c�h������&�s�i�g�n�a�l�.�h�t�m�l�#�p�y�u�l�e�a�r����3�.�1�0�.�1�1� �p�y�u�l�e�a�r�������s�i�g�n�a�l�.�h�t�m�l�#�t�f�e����3�.�1�0�.�1�2� �t�f�e������,�s�i�g�n�a�l�.�h�t�m�l�#�t�f�e�s�t�i�m�a�t�e���$�3�.�1�0�.�1�3� �t�f�e�s�t�i�m�a�t�e������8�s�i�g�n�a�l�.�h�t�m�l�#�W�i�n�d�o�w�-�F�u�n�c�t�i�o�n�s���*�3�.�1�1� �W�i�n�d�o�w� �F�u�n�c�t�i�o�n�s������.�s�i�g�n�a�l�.�h�t�m�l�#�b�a�r�t�h�a�n�n�w�i�n���$�3�.�1�1�.�1� �b�a�r�t�h�a�n�n�w�i�n������4�s�i�g�n�a�l�.�h�t�m�l�#�b�l�a�c�k�m�a�n�h�a�r�r�i�s���*�3�.�1�1�.�2� �b�l�a�c�k�m�a�n�h�a�r�r�i�s������6�s�i�g�n�a�l�.�h�t�m�l�#�b�l�a�c�k�m�a�n�n�u�t�t�a�l�l���,�3�.�1�1�.�3� �b�l�a�c�k�m�a�n�n�u�t�t�a�l�l������*�s�i�g�n�a�l�.�h�t�m�l�#�b�o�h�m�����a�n�w�i�n��� �3�.�1�1�.�4� �b�o�h�m�a�n�w�i�n������$�s�i�g�n�a�l�.�h�t�m�l�#�b�o�x�c�a�r����3�.�1�1�.�5� �b�o�x�c�a�r������&�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�w�i�n����3�.�1�1�.�6� �c�h�e�b�w�i�n������$�s�i�g�n�a�l�.�h�t�m�l�#�e�x�p�w�i�n����3�.�1�1�.�7� �e�x�p�w�i�n������,�s�i�g�n�a�l�.�h�t�m�l�#�f�l�a�t�t�o�p�w�i�n���"�3�.�1�1�.�8� �f�l�a�t�t�o�p�w�i�n������(�s�i�g�n�a�l�.�h�t�m�l�#�g�a�u�s�s�i�a�n����3�.�1�1�.�9� �g�a�u�s�s�i�a�n������(�s�i�g�n�a�l�.�h�t�m�l�#�g�a�u�s�s�w�i�n��� �3�.�1�1�.�1�0� �g�a�u�s�s�w�i�n������ �s�i�g�n�a�l�.�h�t�m�l�#�h�a�n�n����3�.�1�1�.�1�1� �h�a�n�n������$�s�i�g�n�a�l�.�h�t�m�l�#�k�a�i�s�e�r����3�.�1�1�.�1�2� �k�a�i�s�e�r������,�s�i�g�n�a�l�.�h�t�m�l�#�n�u�t�t�a�l�l�w�i�n���$�3�.�1�1�.�1�3� �n�u�t�t�a�l�l�w�i�n������*�s�i�g�n�a�l�.�h�t�m�l�#�p�a�r�z�e�n�w�i�n���"�3�.�1�1�.�1�4� �p�a�r�z�e�n�w�i�n������(�s�i�g�n�a�l�.�h�t�m�l�#�p�o�i�s�s�w�i�n��� �3�.�1�1�.�1�5� �p�o�i�s�s�w�i�n������&�s�i�g�n�a�l�.�h�t�m�l�#�r�e�c�t�w�i�n����3�.�1�1�.�1�6� �r�e�c�t�w�i�n������*�s�i�g�n�a�l�.�h�t�m�l�#�t�a�y�l�o�r�w�i�n���"�3�.�1�1�.�1�7� �t�a�y�l�o�r�w�i�n������$�s�i�g�n�a�l�.�h�t�m�l�#�t�r�i�a�n�g����3�.�1�1�.�1�8� �t�r�i�a�n�g������(�s�i�g�n�a�l�.�h�t�m�l�#�t�u�k�e�y�w�i�n��� �3�.�1�1�.�1�9� �t�u�k�e�y�w�i�n������&�s�i�g�n�a�l�.�h�t�m�l�#�u�l�t�r�w�i�n����3�.�1�1�.�2�0� �u�l�t�r�w�i�n������(�s�i�g�n�a�l�.�h�t�m�l�#�w�e�l�c�h�w�i�n��� �3�.�1�1�.�2�1� �w�e�l�c�h�w�i�n������$�s�i�g�n�a�l�.�h�t�m�l�#�w�i�n�d�o�w����3�.�1�1�.�2�2� �w�i�n�d�o�w������B�s�i�g�n�a�l�.�h�t�m�l�#�S�y�s�t�e�m�-�I�d�e�n�t�i�f�i�c�a�t�i�o�n���4�3�.�1�2� �S�y�s�t�e�m� �I�d�e�n�t�i�f�i�c�a�t�i�o�n������$�s�i�g�n�a�l�.�h�t�m�l�#�a�r�b�u�r�g����3�.�1�2�.�1� �a�r�b�u�r�g������$�s�i�g�n�a�l�.�h�t�m�l�#�a�r�y�u�l�e����3�.�1�2�.�2� �a�r�y�u�l�e������&�s�i�g�n�a�l�.�h�t�m�l�#�i�n�v�f�r�e�q����3�.�1�2�.�3� �i�n�v�f�r�e�q������(�s�i�g�n�a�l�.�h�t�m�l�#�i�n�v�f�r�e�q�s����3�.�1�2�.�4� �i�n�v�f�r�e�q�s������(�s�i�g�n�a�l�.�h�t�m�l�#�i�n�v�f�r�e�q�z����3�.�1�2�.�5� �i�n�v�f�r�e�q�z������(�s�i�g�n�a�l�.�h�t�m�l�#�l�e�v�i�n�s�o�n����3�.�1�2�.�6� �l�e�v�i�n�s�o�n�������s�i�g�n�a�l�.�h�t�m�l�#�l�p�c����3�.�1�2�.�7� �l�p�c������<�s�i�g�n�a�l�.�h�t�m�l�#�S�a�m�p�l�e�-�R�a�t�e�-�C�h�a�n�g�e���.�3�.�1�3� �S�a�m�p�l�e� �R�a�t�e� �C�h�a�n�g�e������(�s�i�g�n�a�l�.�h�t�m�l�#�d�a�t�a�2�f�u�n����3�.�1�3�.�1� �d�a�t�a�2�f�u�n������(�s�i�g�n�a�l�.�h�t�m�l�#�d�e�c�i�m�a�t�e����3�.�1�3�.�2� �d�e�c�i�m�a�t�e������,�s�i�g�n�a�l�.�h�t�m�l�#�d�o�w�n�s�a�m�p�l�e���"�3�.�1�3�.�3� �d�o�w�n�s�a�m�p�l�e������$�s�i�g�n�a�l�.�h�t�m�l�#�i�n�t�e�r�p����3�.�1�3�.�4� �i�n�t�e�r�p������(�s�i�g�n�a�l�.�h�t�m�l�#�r�e�s�a�m�p�l�e����3�.�1�3�.�5� �r�e�s�a�m�p�l�e������&�s�i�g�n�a�l�.�h�t�m�l�#�u�p�f�i�r�d�n����3�.�1�3�.�6� �u�p�f�i�r�d�n������(�s�i�g�n�a�l�.�h�t�m�l�#�u�p�s�a�m�p�l�e����3�.�1�3�.�7� �u�p�s�a�m�p�l�e������2�s�i�g�n�a�l�.�h�t�m�l�#�P�u�l�s�e�-�M�e�t�r�i�c�s���$�3�.�1�4� �P�u�l�s�e� �M�e�t�r�i�c�s������.�s�i�g�n�a�l�.�h�t�m�l�#�s�t�a�t�e�l�e�v�e�l�s���$�3�.�1�4�.�1� �s�t�a�t�e�l�e�v�e�l�s������&�s�i�g�n�a�l�.�h�t�m�l�#�U�t�i�l�i�t�y����3�.�1�5� �U�t�i�l�i�t�y������(�s�i�g�n�a�l�.�h�t�m�l�#�b�u�f�f�e�r�-�1����3�.�1�5�.�1� �b�u�f�f�e�r������4�s�i�g�n�a�l�.�h�t�m�l�#�c�l�u�s�t�e�r�s�e�g�m�e�n�t���*�3�.�1�5�.�2� �c�l�u�s�t�e�r�s�e�g�m�e�n�t������*�s�i�g�n�a�l�.�h�t�m�l�#�f�r�a�c�s�h�i�f�t��� �3�.�1�5�.�3� �f�r�a�c�s�h�i�f�t������&�s�i�g�n�a�l�.�h�t�m�l�#�m�a�r�c�u�m�q����3�.�1�5�.�4� �m�a�r�c�u�m�q������*�s�i�g�n�a�l�.�h�t�m�l�#�p�r�i�m�i�t�i�v�e��� �3�.�1�5�.�5� �p�r�i�m�i�t�i�v�e������<�s�i�g�n�a�l�.�h�t�m�l�#�s�a�m�p�l�e�d�2�c�o�n�t�i�n�u�o�u�s���2�3�.�1�5�.�6� �s�a�m�p�l�e�d�2�c�o�n�t�i�n�u�o�u�s������&�s�i�g�n�a�l�.�h�t�m�l�#�s�c�h�t�r�i�g����3�.�1�5�.�7� �s�c�h�t�r�i�g������0�s�i�g�n�a�l�.�h�t�m�l�#�u�p�s�a�m�p�l�e�f�i�l�l���&�3�.�1�5�.�8� �u�p�s�a�m�p�l�e�f�i�l�l������"�s�i�g�n�a�l�.�h�t�m�l�#�w�k�e�e�p����3�.�1�5�.�9� �w�k�e�e�p������ �s�i�g�n�a�l�.�h�t�m�l�#�w�r�e�v����3�.�1�5�.�1�0� �w�r�e�v������0�s�i�g�n�a�l�.�h�t�m�l�#�z�e�r�o�c�r�o�s�s�i�n�g���(�3�.�1�5�.�1�1� �z�e�r�o�c�r�o�s�s�i�n�g ���œT�êÖ¼¨rZ@*öܦ~dN6 æ Ö º „ t b N 6 "  ø æ ̀ ¶ œ € b J ,  � ̃ ̀ ²   „ f H .   è Î ¸ ¢ Œ x d N : &  ü è Î ¶ œ † p X F . üầ¶¢p\B(̣ª–„r^B"øØÄªxbL(øæÎ¼¨–„p\9 ÷çÑ·£w_N/羡qZ; ̣Û¼Ÿ„kN7èѺ£oT���������������������� invfreqzinvfreqz�� invfreqsinvfreqs�� invfreqinvfreq�� aryulearyule�� arburgarburg�� windowwindow�� welchwinwelchwin�� ultrwinultrwin�� tukeywintukeywin�� triangtriang�� taylorwintaylorwin�� rectwinrectwin�� poisswinpoisswin�� parzenwinparzenwin�!� !nuttallwinnuttallwin �� kaiserkaiser �� hannhann �� gausswingausswin �� gaussiangaussian �!� !flattopwinflattopwin�� expwinexpwin�� chebwinchebwin�� boxcarboxcar�� bohmanwinbohmanwin&�+� +blackmannuttallblackmannuttall$�)� )blackmanharrisblackmanharris�#� #barthannwinbarthannwin�!� !tfestimatetfestimate��� tfetfe�� pyulearpyulear~�� pwelchpwelch}�� pow2dbpow2db|�� pburgpburg{�� mscoheremscoherez�� db2powdb2powy�� csdcsdx�� cpsdcpsdw�� coherecoherev�� !ar_psdar_005fpsd!u�� 1__powerg_t_005f_005fpowert�� rcepsrcepss�� ifwhtifwhtr�� ifhtifhtq�� idstidstp�� idct2idct2o�� idctidctn�� hilberthilbertm�� fwhtfwhtl�� fhtfhtk�� dwtdwtj�� dstdst"i�'� 'digitrevorderdigitrevorderh�� dftmtxdftmtxg�� dctmtxdctmtxf�� dct2dct2e�� dctdctd�� cztcztc�� cplxrealcplxrealb�� ccepsccepsa�#� #bitrevorderbitrevorder`�� sgolaysgolay_�� remezremez^�� 'qp_kaiserqp_005fkaiser]�� kaiserordkaiserord\�� firlsfirls[�� fir2fir2Z�� fir1fir1Y�� cl2bpcl2bpX�� sftranssftrans.W�+� ;pei_tseng_notchpei_005ftseng_005fnotchV�� ncauerncauerU�#� #invimpinvarinvimpinvarT�� impinvarimpinvarS�� firpmordfirpmordR�� firpmfirpmQ�� ellipordellipordP�� ellipapellipapO�� ellipellipN�� cheby2cheby2M�� cheby1cheby1L�� cheb2ordcheb2ordK�� cheb2apcheb2apJ�� cheb1ordcheb1ordI�� cheb1apcheb1apH�� chebchebG�� buttordbuttordF�� butterbutterE�� buttapbuttapD�� bilinearbilinearC�� besselfbesselfB�� besselapbesselapA�� zp2tfzp2tf@�� zp2sszp2ss?�� zp2soszp2sos>�� tf2zptf2zp=�� tf2sstf2ss<�� tf2sostf2sos;�� ss2zpss2zp:�� ss2tfss2tf9�� sos2zpsos2zp8�� sos2tfsos2tf7�� sos2sssos2ss6�� residuezresiduez5�� residuedresidued4�� zplanezplane3�� phasezphasez2�� isstableisstable1�!� !isminphaseisminphase0�!� !ismaxphaseismaxphase/�� isallpassisallpass.�� impzimpz-�� grpdelaygrpdelay,�� fwhmfwhm +�!� )freqs_plotfreqs_005fplot*�� freqsfreqs)�� filtordfiltord(�!� !filternormfilternorm'�� sosfiltsosfilt&�!� !sgolayfiltsgolayfilt%�� movingrmsmovingrms$�� medfilt1medfilt1#�� filticfiltic"�� filtfiltfiltfilt!�� xcovxcov �� xcorr2xcorr2�� xcorrxcorr�� wconvwconv�� convmtxconvmtx�� cconvcconv�� rssqrssq�� rmsrms�� peak2rmspeak2rms�� peak2peakpeak2peak�� findpeaksfindpeaks�� vcovco�#� #unshiftdataunshiftdata�� uencodeuencode�� udecodeudecode�� tripulstripuls�� squaresquare�� specgramspecgram&�'� /sigmoid_trainsigmoid_005ftrain�� shiftdatashiftdata �� shanwavfshanwavf �� sawtoothsawtooth �� rectpulsrectpuls �� pulstranpulstran �� morletmorlet�� meyerauxmeyeraux�� mexihatmexihat�� gmonopulsgmonopuls�� gauspulsgauspuls�� diricdiric�� cmorwavfcmorwavf�� chirpchirp�� bufferbuffer ��� ¯�åÔ¹hM4øß¸›‚e6 ú å ̉ ¯��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� 1�%� %zerocrossingzerocrossing0�� wrevwrev/�� wkeepwkeep .�%� %upsamplefillupsamplefill-�� schtrigschtrig,,�1� 1sampled2continuoussampled2continuous+�� primitiveprimitive*�� marcumqmarcumq)�� fracshiftfracshift$(�)� )clustersegmentclustersegment'�� bufferbuffer-1&�#� #statelevelsstatelevels%�� upsampleupsample$�� upfirdnupfirdn#�� resampleresample"�� interpinterp!�!� !downsampledownsample �� decimatedecimate�� data2fundata2fun�� lpclpc�� levinsonlevinsonsignal-1.4.6/doc/signal.qhc�������������������������������������������������������������������������0000644�0000000�0000000�00000340000�14673270174�012454� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������SQLite format 3���@ ���#���������������������������������������������������������������#�.v‰ ²�¨�†’$ º  w † ä h ó z ó H¾"¾fó| ¨������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������b''tableVersionFilterVersionFilterCREATE TABLE VersionFilter (Version TEXT, FilterId INTEGER)n++tableComponentFilterComponentFilterCREATE TABLE ComponentFilter (ComponentName TEXT, FilterId INTEGER)u--tableComponentMappingComponentMappingCREATE TABLE ComponentMapping (ComponentId INTEGER, NamespaceId INTEGER)q))tableComponentTableComponentTableCREATE TABLE ComponentTable (ComponentId INTEGER PRIMARY KEY, Name TEXT)VtableFilterFilterCREATE TABLE Filter (FilterId INTEGER PRIMARY KEY, Name TEXT)b%%tableVersionTableVersionTableCREATE TABLE VersionTable (NamespaceId INTEGER, Version TEXT)))mtableTimeStampTableTimeStampTableCREATE TABLE TimeStampTable (NamespaceId INTEGER, FolderId INTEGER, FilePath TEXT, Size INTEGER, TimeStamp TEXT)551tableOptimizedFilterTableOptimizedFilterTableCREATE TABLE OptimizedFilterTable (NamespaceId INTEGER, FilterAttributeId INTEGER)(77otableFileAttributeSetTableFileAttributeSetTableCREATE TABLE FileAttributeSetTable (NamespaceId INTEGER, FilterAttributeSetId INTEGER, FilterAttributeId INTEGER) 33/tableContentsFilterTableContentsFilterTableCREATE TABLE ContentsFilterTable (FilterAttributeId INTEGER, ContentsId INTEGER )w --!tableIndexFilterTableIndexFilterTable CREATE TABLE IndexFilterTable (FilterAttributeId INTEGER, IndexId INTEGER)s ++tableFileFilterTableFileFilterTable CREATE TABLE FileFilterTable (FilterAttributeId INTEGER, FileId INTEGER)z ''3tableContentsTableContentsTable CREATE TABLE ContentsTable (Id INTEGER PRIMARY KEY, NamespaceId INTEGER, Data BLOB) !!‚ tableIndexTableIndexTable CREATE TABLE IndexTable (Id INTEGER PRIMARY KEY, Name TEXT, Identifier TEXT, NamespaceId INTEGER, FileId INTEGER, Anchor TEXT)''MtableFileNameTableFileNameTable CREATE TABLE FileNameTable (FolderId INTEGER, Name TEXT, FileId INTEGER PRIMARY KEY, Title TEXT)e'' tableSettingsTableSettingsTableCREATE TABLE SettingsTable (Key TEXT PRIMARY KEY, Value BLOB )9M'�indexsqlite_autoindex_SettingsTable_1SettingsTable�������h##tableFilterTableFilterTableCREATE TABLE FilterTable (NameId INTEGER, FilterAttributeId INTEGER )l++tableFilterNameTableFilterNameTableCREATE TABLE FilterNameTable (Id INTEGER PRIMARY KEY, Name TEXT ){55tableFilterAttributeTableFilterAttributeTableCREATE TABLE FilterAttributeTable (Id INTEGER PRIMARY KEY, Name TEXT )u##1tableFolderTableFolderTableCREATE TABLE FolderTable (Id INTEGER PRIMARY KEY, NamespaceId INTEGER, Name TEXT )x))+tableNamespaceTableNamespaceTableCREATE TABLE NamespaceTable (Id INTEGER PRIMARY KEY, Name TEXT, FilePath TEXT ) ���Ù�Ù���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������%�;!octave.community.signalsignal.qch ���÷�÷���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� doc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���#�Ô¶{fS>#�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������9FullTextSearchFallback%CreationTimefípÑ) HideAddressBar- EnableAddressBarA EnableDocumentationManager; HideFilterFunctionality? EnableFilterFunctionality*-;LastRegisterTime2024-09-20T08:55:45.051 ���?�Z~“Î?k²́���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������9FullTextSearchFallback%CreationTime)HideAddressBar-EnableAddressBarAEnableDocumentationManager;HideFilterFunctionality?EnableFilterFunctionality- LastRegisterTime ���¦�Á¦���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� !�!signal.csssignal.css= #�gsignal.htmlOctave Signal - Signal Toolkit for GNU octave���ú����ú�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������" ����ç��ç�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������₫� ü ��������s�i�g�n�a�l�.�h�t�m�l���h�O�c�t�a�v�e� �S�i�g�n�a�l� �-� �S�i�g�n�a�l� �T�o�o�l�k�i�t� �f�o�r� �G�N�U� �o�c�t�a�v�e� �M�a�n�u�a�l������(�s�i�g�n�a�l�.�h�t�m�l�#�O�v�e�r�v�i�e�w����1� �O�v�e�r�v�i�e�w������D�s�i�g�n�a�l�.�h�t�m�l�#�I�n�s�t�a�l�l�i�n�g�-�a�n�d�-�l�o�a�d�i�n�g���0�2� �I�n�s�t�a�l�l�i�n�g� �a�n�d� �l�o�a�d�i�n�g������6�s�i�g�n�a�l�.�h�t�m�l�#�W�i�n�d�o�w�s�-�i�n�s�t�a�l�l���&�2�.�1� �W�i�n�d�o�w�s� �i�n�s�t�a�l�l������,�s�i�g�n�a�l�.�h�t�m�l�#�I�n�s�t�a�l�l�i�n�g����2�.�2� �I�n�s�t�a�l�l�i�n�g������&�s�i�g�n�a�l�.�h�t�m�l�#�L�o�a�d�i�n�g����2�.�3� �L�o�a�d�i�n�g������<�s�i�g�n�a�l�.�h�t�m�l�#�F�u�n�c�t�i�o�n�-�R�e�f�e�r�e�n�c�e���(�3� �F�u�n�c�t�i�o�n� �R�e�f�e�r�e�n�c�e������&�s�i�g�n�a�l�.�h�t�m�l�#�S�i�g�n�a�l�s����3�.�1� �S�i�g�n�a�l�s������$�s�i�g�n�a�l�.�h�t�m�l�#�b�u�f�f�e�r����3�.�1�.�1� �b�u�f�f�e�r������"�s�i�g�n�a�l�.�h�t�m�l�#�c�h�i�r�p����3�.�1�.�2� �c�h�i�r�p������(�s�i�g�n�a�l�.�h�t�m�l�#�c�m�o�r�w�a�v�f����3�.�1�.�3� �c�m�o�r�w�a�v�f������"�s�i�g�n�a�l�.�h�t�m�l�#�d�i�r�i�c����3�.�1�.�4� �d�i�r�i�c������(�s�i�g�n�a�l�.�h�t�m�l�#�g�a�u�s�p�u�l�s����3�.�1�.�5� �g�a�u�s�p�u�l�s������*�s�i�g�n�a�l�.�h�t�m�l�#�g�m�o�n�o�p�u�l�s����3�.�1�.�6� �g�m�o�n�o�p�u�l�s������&�s�i�g�n�a�l�.�h�t�m�l�#�m�e�x�i�h�a�t����3�.�1�.�7� �m�e�x�i�h�a�t������(�s�i�g�n�a�l�.�h�t�m�l�#�m�e�y�e�r�a�u�x����3�.�1�.�8� �m�e�y�e�r�a�u�x������$�s�i�g�n�a�l�.�h�t�m�l�#�m�o�r�l�e�t����3�.�1�.�9� �m�o�r�l�e�t������(�s�i�g�n�a�l�.�h�t�m�l�#�p�u�l�s�t�r�a�n����3�.�1�.�1�0� �p�u�l�s�t�r�a�n������(�s�i�g�n�a�l�.�h�t�m�l�#�r�e�c�t�p�u�l�s����3�.�1�.�1�1� �r�e�c�t�p�u�l�s������(�s�i�g�n�a�l�.�h�t�m�l�#�s�a�w�t�o�o�t�h����3�.�1�.�1�2� �s�a�w�t�o�o�t�h������(�s�i�g�n�a�l�.�h�t�m�l�#�s�h�a�n�w�a�v�f����3�.�1�.�1�3� �s�h�a�n�w�a�v�f������*�s�i�g�n�a�l�.�h�t�m�l�#�s�h�i�f�t�d�a�t�a��� �3�.�1�.�1�4� �s�h�i�f�t�d�a�t�a������:�s�i�g�n�a�l�.�h�t�m�l�#�s�i�g�m�o�i�d�_�0�0�5�f�t�r�a�i�n���(�3�.�1�.�1�5� �s�i�g�m�o�i�d�_�t�r�a�i�n������(�s�i�g�n�a�l�.�h�t�m�l�#�s�p�e�c�g�r�a�m����3�.�1�.�1�6� �s�p�e�c�g�r�a�m������$�s�i�g�n�a�l�.�h�t�m�l�#�s�q�u�a�r�e����3�.�1�.�1�7� �s�q�u�a�r�e������&�s�i�g�n�a�l�.�h�t�m�l�#�t�r�i�p�u�l�s����3�.�1�.�1�8� �t�r�i�p�u�l�s������&�s�i�g�n�a�l�.�h�t�m�l�#�u�d�e�c�o�d�e����3�.�1�.�1�9� �u�d�e�c�o�d�e������&�s�i�g�n�a�l�.�h�t�m�l�#�u�e�n�c�o�d�e����3�.�1�.�2�0� �u�e�n�c�o�d�e������.�s�i�g�n�a�l�.�h�t�m�l�#�u�n�s�h�i�f�t�d�a�t�a���$�3�.�1�.�2�1� �u�n�s�h�i�f�t�d�a�t�a�������s�i�g�n�a�l�.�h�t�m�l�#�v�c�o����3�.�1�.�2�2� �v�c�o������<�s�i�g�n�a�l�.�h�t�m�l�#�S�i�g�n�a�l�-�M�e�a�s�u�r�e�m�e�n�t���,�3�.�2� �S�i�g�n�a�l� �M�e�a�s�u�r�e�m�e�n�t������*�s�i�g�n�a�l�.�h�t�m�l�#�f�i�n�d�p�e�a�k�s����3�.�2�.�1� �f�i�n�d�p�e�a�k�s������*�s�i�g�n�a�l�.�h�t�m�l�#�p�e�a�k�2�p�e�a�k����3�.�2�.�2� �p�e�a�k�2�p�e�a�k������(�s�i�g�n�a�l�.�h�t�m�l�#�p�e�a�k�2�r�m�s����3�.�2�.�3� �p�e�a�k�2�r�m�s�������s�i�g�n�a�l�.�h�t�m�l�#�r�m�s����3�.�2�.�4� �r�m�s������ �s�i�g�n�a�l�.�h�t�m�l�#�r�s�s�q����3�.�2�.�5� �r�s�s�q������N�s�i�g�n�a�l�.�h�t�m�l�#�C�o�r�r�e�l�a�t�i�o�n�-�a�n�d�-�C�o�n�v�o�l�u�t�i�o�n���>�3�.�3� �C�o�r�r�e�l�a�t�i�o�n� �a�n�d� �C�o�n�v�o�l�u�t�i�o�n������"�s�i�g�n�a�l�.�h�t�m�l�#�c�c�o�n�v����3�.�3�.�1� �c�c�o�n�v������&�s�i�g�n�a�l�.�h�t�m�l�#�c�o�n�v�m�t�x����3�.�3�.�2� �c�o�n�v�m�t�x������"�s�i�g�n�a�l�.�h�t�m�l�#�w�c�o�n�v����3�.�3�.�3� �w�c�o�n�v������"�s�i�g�n�a�l�.�h�t�m�l�#�x�c�o�r�r����3�.�3�.�4� �x�c�o�r�r������$�s�i�g�n�a�l�.�h�t�m�l�#�x�c�o�r�r�2����3�.�3�.�5� �x�c�o�r�r�2������ �s�i�g�n�a�l�.�h�t�m�l�#�x�c�o�v����3�.�3�.�6� �x�c�o�v������*�s�i�g�n�a�l�.�h�t�m�l�#�F�i�l�t�e�r�i�n�g����3�.�4� �F�i�l�t�e�r�i�n�g������(�s�i�g�n�a�l�.�h�t�m�l�#�f�i�l�t�f�i�l�t����3�.�4�.�1� �f�i�l�t�f�i�l�t������$�s�i�g�n�a�l�.�h�t�m�l�#�f�i�l�t�i�c����3�.�4�.�2� �f�i�l�t�i�c������(�s�i�g�n�a�l�.�h�t�m�l�#��� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���Ø�Ø��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������& !3signal.qch0�2024-09-20T08:55:45 ���û�û������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� � �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���ø�ø�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������doc ���û�û������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���¢^�ëØ¿¬“xaH3èÏ´t_H1 û ́ Ñ ¶ } j S @ -   î Ù À ¥ ˆ q T = * ø ß Î ³ – y ` K 6   ï Ú Å ² Ÿ w d O < )  ù à Ë ¶ Ÿ w ^ G .  ñÚÁ®•|]Hï̃ͺŸ€mX9& ₫ï̃É´‘‚sdS<+öăĐ®•€o`K2 ỡΰjB&øâĪ~hJ.üàʰ˜~hR<$ đÖÆ¬’t^������������������"�� interpinterp!�!� !downsampledownsample �� decimatedecimate�� data2fundata2fun �� lpclpc�� levinsonlevinson�� invfreqzinvfreqz�� invfreqsinvfreqs�� invfreqinvfreq�� aryulearyule�� arburgarburg�� windowwindow�� welchwinwelchwin�� ultrwinultrwin�� tukeywintukeywin�� triangtriang�� taylorwintaylorwin�� rectwinrectwin�� poisswinpoisswin�� parzenwinparzenwin�!� !nuttallwinnuttallwin �� kaiserkaiser �� hannhann �� gausswingausswin �� gaussiangaussian �!� !flattopwinflattopwin�� expwinexpwin�� chebwinchebwin�� boxcarboxcar�� bohmanwinbohmanwin%�+� +blackmannuttallblackmannuttall#�)� )blackmanharrisblackmanharris�#� #barthannwinbarthannwin�!� !tfestimatetfestimate ��� tfetfe�� pyulearpyulear~�� pwelchpwelch}�� pow2dbpow2db|�� pburgpburg{�� mscoheremscoherez�� db2powdb2pow y�� csdcsdx�� cpsdcpsdw�� coherecoherev�� !ar_psdar_005fpsd u�� 1__powerg_t_005f_005fpowert�� rcepsrcepss�� ifwhtifwhtr�� ifhtifhtq�� idstidstp�� idct2idct2o�� idctidctn�� hilberthilbertm�� fwhtfwht l�� fhtfht k�� dwtdwt j�� dstdst!i�'� 'digitrevorderdigitrevorderh�� dftmtxdftmtxg�� dctmtxdctmtxf�� dct2dct2 e�� dctdct d�� cztcztc�� cplxrealcplxrealb�� ccepsccepsa�#� #bitrevorderbitrevorder`�� sgolaysgolay_�� remezremez^�� 'qp_kaiserqp_005fkaiser]�� kaiserordkaiserord\�� firlsfirls[�� fir2fir2Z�� fir1fir1Y�� cl2bpcl2bpX�� sftranssftrans-W�+� ;pei_tseng_notchpei_005ftseng_005fnotchV�� ncauerncauerU�#� #invimpinvarinvimpinvarT�� impinvarimpinvarS�� firpmordfirpmordR�� firpmfirpmQ�� ellipordellipordP�� ellipapellipapO�� ellipellipN�� cheby2cheby2M�� cheby1cheby1L�� cheb2ordcheb2ordK�� cheb2apcheb2apJ�� cheb1ordcheb1ordI�� cheb1apcheb1apH�� chebchebG�� buttordbuttordF�� butterbutterE�� buttapbuttapD�� bilinearbilinearC�� besselfbesselfB�� besselapbesselapA�� zp2tfzp2tf@�� zp2sszp2ss?�� zp2soszp2sos>�� tf2zptf2zp=�� tf2sstf2ss<�� tf2sostf2sos;�� ss2zpss2zp:�� ss2tfss2tf9�� sos2zpsos2zp8�� sos2tfsos2tf7�� sos2sssos2ss6�� residuezresiduez5�� residuedresidued4�� zplanezplane3�� phasezphasez2�� isstableisstable1�!� !isminphaseisminphase0�!� !ismaxphaseismaxphase/�� isallpassisallpass.�� impzimpz-�� grpdelaygrpdelay,�� fwhmfwhm+�!� )freqs_plotfreqs_005fplot*�� freqsfreqs)�� filtordfiltord(�!� !filternormfilternorm'�� sosfiltsosfilt&�!� !sgolayfiltsgolayfilt%�� movingrmsmovingrms$�� medfilt1medfilt1#�� filticfiltic"�� filtfiltfiltfilt!�� xcovxcov �� xcorr2xcorr2�� xcorrxcorr�� wconvwconv�� convmtxconvmtx�� cconvcconv�� rssqrssq �� rmsrms�� peak2rmspeak2rms�� peak2peakpeak2peak�� findpeaksfindpeaks �� vcovco�#� #unshiftdataunshiftdata�� uencodeuencode�� udecodeudecode�� tripulstripuls�� squaresquare�� specgramspecgram%�'� /sigmoid_trainsigmoid_005ftrain�� shiftdatashiftdata �� shanwavfshanwavf �� sawtoothsawtooth �� rectpulsrectpuls �� pulstranpulstran �� morletmorlet�� meyerauxmeyeraux�� mexihatmexihat�� gmonopulsgmonopuls�� gauspulsgauspuls�� diricdiric�� cmorwavfcmorwavf�� chirpchirp�� bufferbuffer ���V�æÎ´”|V:"ØÀxV��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�%� %zerocrossingzerocrossing0�� wrevwrev/�� wkeepwkeep.�%� %upsamplefillupsamplefill-�� schtrigschtrig+,�1� 1sampled2continuoussampled2continuous+�� primitiveprimitive*�� marcumqmarcumq)�� fracshiftfracshift#(�)� )clustersegmentclustersegment'�� bufferbuffer-1&�#� #statelevelsstatelevels%�� upsampleupsample$�� upfirdnupfirdn#�� resampleresample����m�e�d�f�i�l�t�1����3�.�4�.�3� �m�e�d�f�i�l�t�1������*�s�i�g�n�a�l�.�h�t�m�l�#�m�o�v�i�n�g�r�m�s����3�.�4�.�4� �m�o�v�i�n�g�r�m�s������,�s�i�g�n�a�l�.�h�t�m�l�#�s�g�o�l�a�y�f�i�l�t��� �3�.�4�.�5� �s�g�o�l�a�y�f�i�l�t������&�s�i�g�n�a�l�.�h�t�m�l�#�s�o�s�f�i�l�t����3�.�4�.�6� �s�o�s�f�i�l�t������6�s�i�g�n�a�l�.�h�t�m�l�#�F�i�l�t�e�r�-�A�n�a�l�y�s�i�s���&�3�.�5� �F�i�l�t�e�r� �A�n�a�l�y�s�i�s������,�s�i�g�n�a�l�.�h�t�m�l�#�f�i�l�t�e�r�n�o�r�m��� �3�.�5�.�1� �f�i�l�t�e�r�n�o�r�m������&�s�i�g�n�a�l�.�h�t�m�l�#�f�i�l�t�o�r�d����3�.�5�.�2� �f�i�l�t�o�r�d������"�s�i�g�n�a�l�.�h�t�m�l�#�f�r�e�q�s����3�.�5�.�3� �f�r�e�q�s������4�s�i�g�n�a�l�.�h�t�m�l�#�f�r�e�q�s�_�0�0�5�f�p�l�o�t��� �3�.�5�.�4� �f�r�e�q�s�_�p�l�o�t������ �s�i�g�n�a�l�.�h�t�m�l�#�f�w�h�m����3�.�5�.�5� �f�w�h�m������(�s�i�g�n�a�l�.�h�t�m�l�#�g�r�p�d�e�l�a�y����3�.�5�.�6� �g�r�p�d�e�l�a�y������ �s�i�g�n�a�l�.�h�t�m�l�#�i�m�p�z����3�.�5�.�7� �i�m�p�z������*�s�i�g�n�a�l�.�h�t�m�l�#�i�s�a�l�l�p�a�s�s����3�.�5�.�8� �i�s�a�l�l�p�a�s�s������,�s�i�g�n�a�l�.�h�t�m�l�#�i�s�m�a�x�p�h�a�s�e��� �3�.�5�.�9� �i�s�m�a�x�p�h�a�s�e������,�s�i�g�n�a�l�.�h�t�m�l�#�i�s�m�i�n�p�h�a�s�e���"�3�.�5�.�1�0� �i�s�m�i�n�p�h�a�s�e������(�s�i�g�n�a�l�.�h�t�m�l�#�i�s�s�t�a�b�l�e����3�.�5�.�1�1� �i�s�s�t�a�b�l�e������$�s�i�g�n�a�l�.�h�t�m�l�#�p�h�a�s�e�z����3�.�5�.�1�2� �p�h�a�s�e�z������$�s�i�g�n�a�l�.�h�t�m�l�#�z�p�l�a�n�e����3�.�5�.�1�3� �z�p�l�a�n�e������:�s�i�g�n�a�l�.�h�t�m�l�#�F�i�l�t�e�r�-�C�o�n�v�e�r�s�i�o�n���*�3�.�6� �F�i�l�t�e�r� �C�o�n�v�e�r�s�i�o�n������(�s�i�g�n�a�l�.�h�t�m�l�#�r�e�s�i�d�u�e�d����3�.�6�.�1� �r�e�s�i�d�u�e�d������(�s�i�g�n�a�l�.�h�t�m�l�#�r�e�s�i�d�u�e�z����3�.�6�.�2� �r�e�s�i�d�u�e�z������$�s�i�g�n�a�l�.�h�t�m�l�#�s�o�s�2�s�s����3�.�6�.�3� �s�o�s�2�s�s������$�s�i�g�n�a�l�.�h�t�m�l�#�s�o�s�2�t�f����3�.�6�.�4� �s�o�s�2�t�f������$�s�i�g�n�a�l�.�h�t�m�l�#�s�o�s�2�z�p����3�.�6�.�5� �s�o�s�2�z�p������"�s�i�g�n�a�l�.�h�t�m�l�#�s�s�2�t�f����3�.�6�.�6� �s�s�2�t�f������"�s�i�g�n�a�l�.�h�t�m�l�#�s�s�2�z�p����3�.�6�.�7� �s�s�2�z�p������$�s�i�g�n�a�l�.�h�t�m�l�#�t�f�2�s�o�s����3�.�6�.�8� �t�f�2�s�o�s������"�s�i�g�n�a�l�.�h�t�m�l�#�t�f�2�s�s����3�.�6�.�9� �t�f�2�s�s������"�s�i�g�n�a�l�.�h�t�m�l�#�t�f�2�z�p����3�.�6�.�1�0� �t�f�2�z�p������$�s�i�g�n�a�l�.�h�t�m�l�#�z�p�2�s�o�s����3�.�6�.�1�1� �z�p�2�s�o�s������"�s�i�g�n�a�l�.�h�t�m�l�#�z�p�2�s�s����3�.�6�.�1�2� �z�p�2�s�s������"�s�i�g�n�a�l�.�h�t�m�l�#�z�p�2�t�f����3�.�6�.�1�3� �z�p�2�t�f������:�s�i�g�n�a�l�.�h�t�m�l�#�I�I�R�-�F�i�l�t�e�r�-�D�e�s�i�g�n���*�3�.�7� �I�I�R� �F�i�l�t�e�r� �D�e�s�i�g�n������(�s�i�g�n�a�l�.�h�t�m�l�#�b�e�s�s�e�l�a�p����3�.�7�.�1� �b�e�s�s�e�l�a�p������&�s�i�g�n�a�l�.�h�t�m�l�#�b�e�s�s�e�l�f����3�.�7�.�2� �b�e�s�s�e�l�f������(�s�i�g�n�a�l�.�h�t�m�l�#�b�i�l�i�n�e�a�r����3�.�7�.�3� �b�i�l�i�n�e�a�r������$�s�i�g�n�a�l�.�h�t�m�l�#�b�u�t�t�a�p����3�.�7�.�4� �b�u�t�t�a�p������$�s�i�g�n�a�l�.�h�t�m�l�#�b�u�t�t�e�r����3�.�7�.�5� �b�u�t�t�e�r������&�s�i�g�n�a�l�.�h�t�m�l�#�b�u�t�t�o�r�d����3�.�7�.�6� �b�u�t�t�o�r�d������ �s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b����3�.�7�.�7� �c�h�e�b������&�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�1�a�p����3�.�7�.�8� �c�h�e�b�1�a�p������(�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�1�o�r�d����3�.�7�.�9� �c�h�e�b�1�o�r�d������&�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�2�a�p����3�.�7�.�1�0� �c�h�e�b�2�a�p������(�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�2�o�r�d����3�.�7�.�1�1� �c�h�e�b�2�o�r�d������$�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�y�1����3�.�7�.�1�2� �c�h�e�b�y�1������$�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�y�2����3�.�7�.�1�3� �c�h�e�b�y�2������"�s�i�g�n�a�l�.�h�t�m�l�#�e�l�l�i�p����3�.�7�.�1�4� �e�l�l�i�p������&�s�i�g�n�a�l�.�h�t�m�l�#�e�l�l�i�p�a�p����3�.�7�.�1�5� �e�l�l�i�p�a�p������(�s�i�g�n�a�l�.�h�t�m�l�#�e�l�l�i�p�o�r�d����3�.�7�.�1�6� �e�l�l�i�p�o�r�d������"�s�i�g�n�a�l�.�h�t�m�l�#�f�i�r�p�m����3�.�7�.�1�7� �f�i�r�p�m������(�s�i�g�n�a�l�.�h�t�m�l�#�f�i�r�p�m�o�r�d����3�.�7�.�1�8� �f�i�r�p�m�o�r�d������(�s�i�g�n�a�l�.�h�t�m�l�#�i�m�p�i�n�v�a�r����3�.�7�.�1�9� �i�m�p�i�n�v�a�r������.�s�i�g�n�a�l�.�h�t�m�l�#�i�n�v�i�m�p�i�n�v�a�r������$�3�.�7�.�2�0� �i�n�v�i�m�p�i�n�v�a�r������$�s�i�g�n�a�l�.�h�t�m�l�#�n�c�a�u�e�r����3�.�7�.�2�1� �n�c�a�u�e�r������F�s�i�g�n�a�l�.�h�t�m�l�#�p�e�i�_�0�0�5�f�t�s�e�n�g�_�0�0�5�f�n�o�t�c�h���,�3�.�7�.�2�2� �p�e�i�_�t�s�e�n�g�_�n�o�t�c�h������&�s�i�g�n�a�l�.�h�t�m�l�#�s�f�t�r�a�n�s����3�.�7�.�2�3� �s�f�t�r�a�n�s������:�s�i�g�n�a�l�.�h�t�m�l�#�F�I�R�-�F�i�l�t�e�r�-�D�e�s�i�g�n���*�3�.�8� �F�I�R� �F�i�l�t�e�r� �D�e�s�i�g�n������"�s�i�g�n�a�l�.�h�t�m�l�#�c�l�2�b�p����3�.�8�.�1� �c�l�2�b�p������ �s�i�g�n�a�l�.�h�t�m�l�#�f�i�r�1����3�.�8�.�2� �f�i�r�1������ �s�i�g�n�a�l�.�h�t�m�l�#�f�i�r�2����3�.�8�.�3� �f�i�r�2������"�s�i�g�n�a�l�.�h�t�m�l�#�f�i�r�l�s����3�.�8�.�4� �f�i�r�l�s������*�s�i�g�n�a�l�.�h�t�m�l�#�k�a�i�s�e�r�o�r�d����3�.�8�.�5� �k�a�i�s�e�r�o�r�d������2�s�i�g�n�a�l�.�h�t�m�l�#�q�p�_�0�0�5�f�k�a�i�s�e�r����3�.�8�.�6� �q�p�_�k�a�i�s�e�r������"�s�i�g�n�a�l�.�h�t�m�l�#�r�e�m�e�z����3�.�8�.�7� �r�e�m�e�z������$�s�i�g�n�a�l�.�h�t�m�l�#�s�g�o�l�a�y����3�.�8�.�8� �s�g�o�l�a�y������,�s�i�g�n�a�l�.�h�t�m�l�#�T�r�a�n�s�f�o�r�m�s����3�.�9� �T�r�a�n�s�f�o�r�m�s������.�s�i�g�n�a�l�.�h�t�m�l�#�b�i�t�r�e�v�o�r�d�e�r���"�3�.�9�.�1� �b�i�t�r�e�v�o�r�d�e�r������"�s�i�g�n�a�l�.�h�t�m�l�#�c�c�e�p�s����3�.�9�.�2� �c�c�e�p�s������(�s�i�g�n�a�l�.�h�t�m�l�#�c�p�l�x�r�e�a�l����3�.�9�.�3� �c�p�l�x�r�e�a�l�������s�i�g�n�a�l�.�h�t�m�l�#�c�z�t����3�.�9�.�4� �c�z�t�������s�i�g�n�a�l�.�h�t�m�l�#�d�c�t����3�.�9�.�5� �d�c�t������ �s�i�g�n�a�l�.�h�t�m�l�#�d�c�t�2����3�.�9�.�6� �d�c�t�2������$�s�i�g�n�a�l�.�h�t�m�l�#�d�c�t�m�t�x����3�.�9�.�7� �d�c�t�m�t�x������$�s�i�g�n�a�l�.�h�t�m�l�#�d�f�t�m�t�x����3�.�9�.�8� �d�f�t�m�t�x������2�s�i�g�n�a�l�.�h�t�m�l�#�d�i�g�i�t�r�e�v�o�r�d�e�r���&�3�.�9�.�9� �d�i�g�i�t�r�e�v�o�r�d�e�r�������s�i�g�n�a�l�.�h�t�m�l�#�d�s�t����3�.�9�.�1�0� �d�s�t�������s�i�g�n�a�l�.�h�t�m�l�#�d�w�t����3�.�9�.�1�1� �d�w�t�������s�i�g�n�a�l�.�h�t�m�l�#�f�h�t����3�.�9�.�1�2� �f�h�t������ �s�i�g�n�a�l�.�h�t�m�l�#�f�w�h�t����3�.�9�.�1�3� �f�w�h�t������&�s�i�g�n�a�l�.�h�t�m�l�#�h�i�l�b�e�r�t����3�.�9�.�1�4� �h�i�l�b�e�r�t������ �s�i�g�n�a�l�.�h�t�m�l�#�i�d�c�t����3�.�9�.�1�5� �i�d�c�t������"�s�i�g�n�a�l�.�h�t�m�l�#�i�d�c�t�2����3�.�9�.�1�6� �i�d�c�t�2������ �s�i�g�n�a�l�.�h�t�m�l�#�i�d�s�t����3�.�9�.�1�7� �i�d�s�t������ �s�i�g�n�a�l�.�h�t�m�l�#�i�f�h�t����3�.�9�.�1�8� �i�f�h�t������"�s�i�g�n�a�l�.�h�t�m�l�#�i�f�w�h�t����3�.�9�.�1�9� �i�f�w�h�t������"�s�i�g�n�a�l�.�h�t�m�l�#�r�c�e�p�s����3�.�9�.�2�0� �r�c�e�p�s������F�s�i�g�n�a�l�.�h�t�m�l�#�P�o�w�e�r�-�S�p�e�c�t�r�u�m�-�A�n�a�l�y�s�i�s���8�3�.�1�0� �P�o�w�e�r� �S�p�e�c�t�r�u�m� �A�n�a�l�y�s�i�s������<�s�i�g�n�a�l�.�h�t�m�l�#�g�_�t�_�0�0�5�f�_�0�0�5�f�p�o�w�e�r����3�.�1�0�.�1� �_�_�p�o�w�e�r������,�s�i�g�n�a�l�.�h�t�m�l�#�a�r�_�0�0�5�f�p�s�d����3�.�1�0�.�2� �a�r�_�p�s�d������$�s�i�g�n�a�l�.�h�t�m�l�#�c�o�h�e�r�e����3�.�1�0�.�3� �c�o�h�e�r�e������ �s�i�g�n�a�l�.�h�t�m�l�#�c�p�s�d����3�.�1�0�.�4� �c�p�s�d�������s�i�g�n�a�l�.�h�t�m�l�#�c�s�d����3�.�1�0�.�5� �c�s�d������$�s�i�g�n�a�l�.�h�t�m�l�#�d�b�2�p�o�w����3�.�1�0�.�6� �d�b�2�p�o�w������(�s�i�g�n�a�l�.�h�t�m�l�#�m�s�c�o�h�e�r�e����3�.�1�0�.�7� �m�s�c�o�h�e�r�e������"�s�i�g�n�a�l�.�h�t�m�l�#�p�b�u�r�g����3�.�1�0�.�8� �p�b�u�r�g������$�s�i�g�n�a�l�.�h�t�m�l�#�p�o�w�2�d�b����3�.�1�0�.�9� �p�o�w�2�d�b������$�s�i�g�n�a�l�.�h�t�m�l�#�p�w�e�l�c�h����3�.�1�0�.�1�0� �p�w�e�l�c�h������&�s�i�g�n�a�l�.�h�t�m�l�#�p�y�u�l�e�a�r����3�.�1�0�.�1�1� �p�y�u�l�e�a�r�������s�i�g�n�a�l�.�h�t�m�l�#�t�f�e����3�.�1�0�.�1�2� �t�f�e������,�s�i�g�n�a�l�.�h�t�m�l�#�t�f�e�s�t�i�m�a�t�e���$�3�.�1�0�.�1�3� �t�f�e�s�t�i�m�a�t�e������8�s�i�g�n�a�l�.�h�t�m�l�#�W�i�n�d�o�w�-�F�u�n�c�t�i�o�n�s���*�3�.�1�1� �W�i�n�d�o�w� �F�u�n�c�t�i�o�n�s������.�s�i�g�n�a�l�.�h�t�m�l�#�b�a�r�t�h�a�n�n�w�i�n���$�3�.�1�1�.�1� �b�a�r�t�h�a�n�n�w�i�n������4�s�i�g�n�a�l�.�h�t�m�l�#�b�l�a�c�k�m�a�n�h�a�r�r�i�s���*�3�.�1�1�.�2� �b�l�a�c�k�m�a�n�h�a�r�r�i�s������6�s�i�g�n�a�l�.�h�t�m�l�#�b�l�a�c�k�m�a�n�n�u�t�t�a�l�l���,�3�.�1�1�.�3� �b�l�a�c�k�m�a�n�n�u�t�t�a�l�l������*�s�i�g�n�a�l�.�h�t�m�l�#�b�o�h�m�����a�n�w�i�n��� �3�.�1�1�.�4� �b�o�h�m�a�n�w�i�n������$�s�i�g�n�a�l�.�h�t�m�l�#�b�o�x�c�a�r����3�.�1�1�.�5� �b�o�x�c�a�r������&�s�i�g�n�a�l�.�h�t�m�l�#�c�h�e�b�w�i�n����3�.�1�1�.�6� �c�h�e�b�w�i�n������$�s�i�g�n�a�l�.�h�t�m�l�#�e�x�p�w�i�n����3�.�1�1�.�7� �e�x�p�w�i�n������,�s�i�g�n�a�l�.�h�t�m�l�#�f�l�a�t�t�o�p�w�i�n���"�3�.�1�1�.�8� �f�l�a�t�t�o�p�w�i�n������(�s�i�g�n�a�l�.�h�t�m�l�#�g�a�u�s�s�i�a�n����3�.�1�1�.�9� �g�a�u�s�s�i�a�n������(�s�i�g�n�a�l�.�h�t�m�l�#�g�a�u�s�s�w�i�n��� �3�.�1�1�.�1�0� �g�a�u�s�s�w�i�n������ �s�i�g�n�a�l�.�h�t�m�l�#�h�a�n�n����3�.�1�1�.�1�1� �h�a�n�n������$�s�i�g�n�a�l�.�h�t�m�l�#�k�a�i�s�e�r����3�.�1�1�.�1�2� �k�a�i�s�e�r������,�s�i�g�n�a�l�.�h�t�m�l�#�n�u�t�t�a�l�l�w�i�n���$�3�.�1�1�.�1�3� �n�u�t�t�a�l�l�w�i�n������*�s�i�g�n�a�l�.�h�t�m�l�#�p�a�r�z�e�n�w�i�n���"�3�.�1�1�.�1�4� �p�a�r�z�e�n�w�i�n������(�s�i�g�n�a�l�.�h�t�m�l�#�p�o�i�s�s�w�i�n��� �3�.�1�1�.�1�5� �p�o�i�s�s�w�i�n������&�s�i�g�n�a�l�.�h�t�m�l�#�r�e�c�t�w�i�n����3�.�1�1�.�1�6� �r�e�c�t�w�i�n������*�s�i�g�n�a�l�.�h�t�m�l�#�t�a�y�l�o�r�w�i�n���"�3�.�1�1�.�1�7� �t�a�y�l�o�r�w�i�n������$�s�i�g�n�a�l�.�h�t�m�l�#�t�r�i�a�n�g����3�.�1�1�.�1�8� �t�r�i�a�n�g������(�s�i�g�n�a�l�.�h�t�m�l�#�t�u�k�e�y�w�i�n��� �3�.�1�1�.�1�9� �t�u�k�e�y�w�i�n������&�s�i�g�n�a�l�.�h�t�m�l�#�u�l�t�r�w�i�n����3�.�1�1�.�2�0� �u�l�t�r�w�i�n������(�s�i�g�n�a�l�.�h�t�m�l�#�w�e�l�c�h�w�i�n��� �3�.�1�1�.�2�1� �w�e�l�c�h�w�i�n������$�s�i�g�n�a�l�.�h�t�m�l�#�w�i�n�d�o�w����3�.�1�1�.�2�2� �w�i�n�d�o�w������B�s�i�g�n�a�l�.�h�t�m�l�#�S�y�s�t�e�m�-�I�d�e�n�t�i�f�i�c�a�t�i�o�n���4�3�.�1�2� �S�y�s�t�e�m� �I�d�e�n�t�i�f�i�c�a�t�i�o�n������$�s�i�g�n�a�l�.�h�t�m�l�#�a�r�b�u�r�g����3�.�1�2�.�1� �a�r�b�u�r�g������$�s�i�g�n�a�l�.�h�t�m�l�#�a�r�y�u�l�e����3�.�1�2�.�2� �a�r�y�u�l�e������&�s�i�g�n�a�l�.�h�t�m�l�#�i�n�v�f�r�e�q����3�.�1�2�.�3� �i�n�v�f�r�e�q������(�s�i�g�n�a�l�.�h�t�m�l�#�i�n�v�f�r�e�q�s����3�.�1�2�.�4� �i�n�v�f�r�e�q�s������(�s�i�g�n�a�l�.�h�t�m�l�#�i�n�v�f�r�e�q�z����3�.�1�2�.�5� �i�n�v�f�r�e�q�z������(�s�i�g�n�a�l�.�h�t�m�l�#�l�e�v�i�n�s�o�n����3�.�1�2�.�6� �l�e�v�i�n�s�o�n�������s�i�g�n�a�l�.�h�t�m�l�#�l�p�c����3�.�1�2�.�7� �l�p�c������<�s�i�g�n�a�l�.�h�t�m�l�#�S�a�m�p�l�e�-�R�a�t�e�-�C�h�a�n�g�e���.�3�.�1�3� �S�a�m�p�l�e� �R�a�t�e� �C�h�a�n�g�e������(�s�i�g�n�a�l�.�h�t�m�l�#�d�a�t�a�2�f�u�n����3�.�1�3�.�1� �d�a�t�a�2�f�u�n������(�s�i�g�n�a�l�.�h�t�m�l�#�d�e�c�i�m�a�t�e����3�.�1�3�.�2� �d�e�c�i�m�a�t�e������,�s�i�g�n�a�l�.�h�t�m�l�#�d�o�w�n�s�a�m�p�l�e���"�3�.�1�3�.�3� �d�o�w�n�s�a�m�p�l�e������$�s�i�g�n�a�l�.�h�t�m�l�#�i�n�t�e�r�p����3�.�1�3�.�4� �i�n�t�e�r�p������(�s�i�g�n�a�l�.�h�t�m�l�#�r�e�s�a�m�p�l�e����3�.�1�3�.�5� �r�e�s�a�m�p�l�e������&�s�i�g�n�a�l�.�h�t�m�l�#�u�p�f�i�r�d�n����3�.�1�3�.�6� �u�p�f�i�r�d�n������(�s�i�g�n�a�l�.�h�t�m�l�#�u�p�s�a�m�p�l�e����3�.�1�3�.�7� �u�p�s�a�m�p�l�e������2�s�i�g�n�a�l�.�h�t�m�l�#�P�u�l�s�e�-�M�e�t�r�i�c�s���$�3�.�1�4� �P�u�l�s�e� �M�e�t�r�i�c�s������.�s�i�g�n�a�l�.�h�t�m�l�#�s�t�a�t�e�l�e�v�e�l�s���$�3�.�1�4�.�1� �s�t�a�t�e�l�e�v�e�l�s������&�s�i�g�n�a�l�.�h�t�m�l�#�U�t�i�l�i�t�y����3�.�1�5� �U�t�i�l�i�t�y������(�s�i�g�n�a�l�.�h�t�m�l�#�b�u�f�f�e�r�-�1����3�.�1�5�.�1� �b�u�f�f�e�r������4�s�i�g�n�a�l�.�h�t�m�l�#�c�l�u�s�t�e�r�s�e�g�m�e�n�t���*�3�.�1�5�.�2� �c�l�u�s�t�e�r�s�e�g�m�e�n�t������*�s�i�g�n�a�l�.�h�t�m�l�#�f�r�a�c�s�h�i�f�t��� �3�.�1�5�.�3� �f�r�a�c�s�h�i�f�t������&�s�i�g�n�a�l�.�h�t�m�l�#�m�a�r�c�u�m�q����3�.�1�5�.�4� �m�a�r�c�u�m�q������*�s�i�g�n�a�l�.�h�t�m�l�#�p�r�i�m�i�t�i�v�e��� �3�.�1�5�.�5� �p�r�i�m�i�t�i�v�e������<�s�i�g�n�a�l�.�h�t�m�l�#�s�a�m�p�l�e�d�2�c�o�n�t�i�n�u�o�u�s���2�3�.�1�5�.�6� �s�a�m�p�l�e�d�2�c�o�n�t�i�n�u�o�u�s������&�s�i�g�n�a�l�.�h�t�m�l�#�s�c�h�t�r�i�g����3�.�1�5�.�7� �s�c�h�t�r�i�g������0�s�i�g�n�a�l�.�h�t�m�l�#�u�p�s�a�m�p�l�e�f�i�l�l���&�3�.�1�5�.�8� �u�p�s�a�m�p�l�e�f�i�l�l������"�s�i�g�n�a�l�.�h�t�m�l�#�w�k�e�e�p����3�.�1�5�.�9� �w�k�e�e�p������ �s�i�g�n�a�l�.�h�t�m�l�#�w�r�e�v����3�.�1�5�.�1�0� �w�r�e�v������0�s�i�g�n�a�l�.�h�t�m�l�#�z�e�r�o�c�r�o�s�s�i�n�g���(�3�.�1�5�.�1�1� �z�e�r�o�c�r�o�s�s�i�n�gsignal-1.4.6/doc/signal.texi������������������������������������������������������������������������0000644�0000000�0000000�00000007430�14673270174�012661� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% Copyright (C) 1996-2024 The Octave Project Developers % % This file is part of Octave. % % Octave 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. % % Octave 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 Octave; see the file COPYING. If not, see % <https://www.gnu.org/licenses/>. \input texinfo @c Octave Signal - Signal Toolkit for GNU octave. @c For manually generating the documentation use @c LANGUAGE=en makeinfo --html --no-split signal.texi @c %*** Start of HEADER @documentencoding UTF-8 @setfilename signal.info @settitle Octave Signal - Signal Toolkit for GNU octave @afourpaper @paragraphindent 0 @finalout @c @afourwide @c %*** End of the HEADER @dircategory Math @direntry * Octave Signal: (signal). Signal Toolkit for Octave @end direntry @include version.texi @include macros.texi @c ------------------------------------------------------------------------- @c @contents @c ------------------------------------------------------------------------- @ifnottex @node Top @top Octave Signal Toolkit Copyright © The Octave Project Developers Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions. @end ifnottex @c ------------------------------------------------------------------------- @node Overview @chapter Overview @cindex Overview The Signal Toolkit contains signal processing tools, including filtering, windowing and display functions. @c ------------------------------------------------------------------------- @node Installing and loading @chapter Installing and loading @cindex Installing and loading The Signal Toolkit must be installed and then loaded to be used. It can be installed in @acronym{GNU} Octave directly from octave-forge, @section Windows install @cindex Windows install If running in Windows, the package may already be installed, to check run: @example pkg list signal @end example @section Installing @cindex Installing With an internet connection available, the Signal package can be installed from octave-forge using the following command within @acronym{GNU} Octave: @example pkg install -forge signal @end example The latest released version of the toolkit will be downloaded and installed. Otherwise, if the package file has already been downloaded it can be installed using the follwoing command in @acronym{GNU} Octave: @example pkg install signal-@value{VERSION}.tar.gz @end example @section Loading @cindex Loading Regardless of the method of installing the toolkit, in order to use its functions, the toolkit must be loaded using the pkg load command: @example pkg load signal @end example The toolkit must be loaded on each @acronym{GNU} Octave session. @c ------------------------------------------------------------------------- @node Function Reference @chapter Function Reference @cindex Function Reference @include functions.texi @c ------------------------------------------------------------------------- @bye ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/doc/version.texi�����������������������������������������������������������������������0000644�0000000�0000000�00000000133�14673270174�013062� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@c autogenerated from Makefile @set VERSION 1.4.6 @set PACKAGE signal @set DATE 2024-09-20 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/����������������������������������������������������������������������������������0000755�0000000�0000000�00000000000�14673270174�010715� 5����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/__firpm_probe__.m�����������������������������������������������������������������0000644�0000000�0000000�00000002461�14673270174�014176� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������######################################################################## ## ## Copyright (C) 2021 The Octave Project Developers ## ## See the file COPYRIGHT.md in the top-level directory of this ## distribution or <https://octave.org/copyright/>. ## ## This file is part of Octave. ## ## Octave 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. ## ## Octave 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 Octave; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## ######################################################################## function is_odd = __firpm_probe__ (respFn, params) try symm=feval (respFn, 'defaults', params); catch is_odd=0; return end_try_catch if (strcmp (symm, 'even')) is_odd=0; elseif (strcmp (symm, 'odd' )) is_odd=1; else error ("firpm respFn symmetry must be 'even' or 'odd'") endif endfunction ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/__load_signal__.m�����������������������������������������������������������������0000644�0000000�0000000�00000002650�14673270174�014146� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2023 John Donoghue ## ## 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 ## <http:##www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {} {} __load_signal__ () ## Undocumented internal function of signal package. ## @end deftypefn ## PKG_ADD: __load_signal__ () function __load_signal__ () # on package load, attempt to load docs try pkg_dir = fileparts (fullfile (mfilename ("fullpath"))); doc_file = fullfile (pkg_dir, "doc", "signal.qch"); doc_file = strrep (doc_file, '\', '/'); if exist(doc_file, "file") if exist("__event_manager_register_documentation__") __event_manager_register_documentation__ (doc_file); elseif exist("__event_manager_register_doc__") __event_manager_register_doc__ (doc_file); endif endif catch # do nothing end_try_catch endfunction ����������������������������������������������������������������������������������������signal-1.4.6/inst/__power.m�������������������������������������������������������������������������0000644�0000000�0000000�00000006105�14673270174�012527� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{P}, @var{w}] =} __power (@var{b}, @var{a}) ## @deftypefnx {Function File} {[@dots{}] =} __power (@var{b}, @var{a}, @var{nfft}) ## @deftypefnx {Function File} {[@dots{}] =} __power (@var{b}, @var{a}, @var{nfft}, @var{Fs}) ## @deftypefnx {Function File} {[@dots{}] =} __power (@var{b}, @var{a}, @var{nfft}, @var{Fs}, @var{range}) ## @deftypefnx {Function File} {[@dots{}] =} __power (@var{b}, @var{a}, @var{nfft}, @var{Fs}, @var{range}, @var{units}) ## @deftypefnx {Function File} {} __power (@dots{}) ## ## Plot the power spectrum of the given ARMA model. ## ## b, a: filter coefficients (b=numerator, a=denominator) ## nfft is number of points at which to sample the power spectrum ## Fs is the sampling frequency of x ## range is 'half' (default) or 'whole' ## units is 'squared' or 'db' (default) ## range and units may be specified any time after the filter, in either ## order ## ## Returns P, the magnitude vector, and w, the frequencies at which it ## is sampled. If there are no return values requested, then plot the power ## spectrum and don't return anything. ## @end deftypefn ## FIXME: consider folding this into freqz --- just one more parameter to ## distinguish between 'linear', 'log', 'logsquared' and 'squared' function varargout = __power (b, a, varargin) if (nargin < 2 || nargin > 6) print_usage; endif nfft = []; Fs = []; range = []; range_fact = 1.0; units = []; pos = 0; for i=1:length(varargin) arg = varargin{i}; if strcmp(arg, 'squared') || strcmp(arg, 'db') units = arg; elseif strcmp(arg, 'whole') range = arg; range_fact = 1.0; elseif strcmp(arg, 'half') range = arg; range_fact = 2.0; elseif ischar(arg) usage(usagestr); elseif pos == 0 nfft = arg; pos++; elseif pos == 1 Fs = arg; pos++; else usage(usagestr); endif endfor if isempty(nfft); nfft = 256; endif if isempty(Fs); Fs = 2; endif if isempty(range) range = 'half'; range_fact = 2.0; endif [P, w] = freqz(b, a, nfft, range, Fs); P = (range_fact/Fs)*(P.*conj(P)); if nargout == 0, if strcmp(units, 'squared') plot(w, P, ";;"); else plot(w, 10.0*log10(abs(P)), ";;"); endif endif if nargout >= 1, varargout{1} = P; endif if nargout >= 2, varargout{2} = w; endif endfunction �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/__unload_signal__.m���������������������������������������������������������������0000644�0000000�0000000�00000002672�14673270174�014515� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2023 John Donoghue ## ## 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 ## <http:##www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {} {} __unload_signal__ () ## Undocumented internal function of signal package. ## @end deftypefn ## PKG_DEL: __unload_signal__ () function __unload_signal__ () # on package unload, attempt to unload docs try pkg_dir = fileparts (fullfile (mfilename ("fullpath"))); doc_file = fullfile (pkg_dir, "doc", "signal.qch"); doc_file = strrep (doc_file, '\', '/'); if exist(doc_file, "file") if exist("__event_manager_unregister_documentation__") __event_manager_unregister_documentation__ (doc_file); elseif exist("__event_manager_unregister_doc__") __event_manager_unregister_doc__ (doc_file); endif endif catch # do nothing end_try_catch endfunction ����������������������������������������������������������������������signal-1.4.6/inst/ar_psd.m��������������������������������������������������������������������������0000644�0000000�0000000�00000027171�14673270174�012353� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} ar_psd (@var{a}, @var{v}) ## @deftypefnx {Function File} {} ar_psd (@var{a}, @var{v}, @var{freq}) ## @deftypefnx {Function File} {} ar_psd (@var{a}, @var{v}, @var{freq}, @var{Fs}) ## @deftypefnx {Function File} {} ar_psd (@dots{}, @var{range}) ## @deftypefnx {Function File} {} ar_psd (@dots{}, @var{method}) ## @deftypefnx {Function File} {} ar_psd (@dots{}, @var{plottype}) ## @deftypefnx {Function File} {[@var{psd}, @var{f_out}] =} ar_psd (@dots{}) ## ## Calculate the power spectrum of the autoregressive model ## ## @example ## @group ## M ## x(n) = sqrt(v).e(n) + SUM a(k).x(n-k) ## k=1 ## @end group ## @end example ## ## where @math{x(n)} is the output of the model and @math{e(n)} is white noise. ## This function is intended for use with ## @code{[a, v, k] = arburg (x, poles, criterion)} ## which use the Burg (1968) method to calculate a "maximum entropy" ## autoregressive model of @var{x}. ## ## If the @var{freq} argument is a vector (of frequencies) the spectrum is ## calculated using the polynomial method and the @var{method} argument is ## ignored. For scalar @var{freq}, an integer power of 2, or @var{method} = ## "FFT", causes the spectrum to be calculated by FFT. Otherwise, the spectrum ## is calculated as a polynomial. It may be computationally more ## efficient to use the FFT method if length of the model is not much ## smaller than the number of frequency values. The spectrum is scaled so ## that spectral energy (area under spectrum) is the same as the time-domain ## energy (mean square of the signal). ## ## ARGUMENTS: ## All but the first two arguments are optional and may be empty. ## @itemize ## @item ## @var{a} ## list of M=(order+1) autoregressive model ## coefficients. The first element of "ar_coeffs" is the ## zero-lag coefficient, which always has a value of 1. ## @item ## @var{v} ## square of the moving-average coefficient of the AR model. ## @item ## @var{freq} ## frequencies at which power spectral density is calculated, or a scalar ## indicating the number of uniformly distributed frequency ## values at which spectral density is calculated. ## (default = 256) ## @item ## @var{Fs} ## sampling frequency (Hertz) (default=1) ## @end itemize ## ## CONTROL-STRING ARGUMENTS -- each of these arguments is a character string. ## Control-string arguments can be in any order after the other arguments. ## ## Range: ## ## 'half', 'onesided' : frequency range of the spectrum is ## from zero up to but not including sample_f/2. Power ## from negative frequencies is added to the positive ## side of the spectrum. ## 'whole', 'twosided' : frequency range of the spectrum is ## -sample_f/2 to sample_f/2, with negative frequencies ## stored in "wrap around" order after the positive ## frequencies; e.g. frequencies for a 10-point 'twosided' ## spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 ## 'shift', 'centerdc' : same as 'whole' but with the first half ## of the spectrum swapped with second half to put the ## zero-frequency value in the middle. (See "help ## fftshift". If "freq" is vector, 'shift' is ignored. ## If model coefficients "ar_coeffs" are real, the default ## range is 'half', otherwise default range is 'whole'. ## ## Method: ## ## 'fft': use FFT to calculate power spectrum. ## 'poly': calculate power spectrum as a polynomial of 1/z ## N.B. this argument is ignored if the "freq" argument is a ## vector. The default is 'poly' unless the "freq" ## argument is an integer power of 2. ## ## Plot type: ## ## 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': ## specifies the type of plot. The default is 'plot', which ## means linear-linear axes. 'squared' is the same as 'plot'. ## 'dB' plots "10*log10(psd)". This argument is ignored and a ## spectrum is not plotted if the caller requires a returned ## value. ## ## RETURNED VALUES: ## If returned values are not required by the caller, the spectrum ## is plotted and nothing is returned. ## @itemize ## @item ## @var{psd} ## estimate of power-spectral density ## @item ## @var{f_out} ## frequency values ## @end itemize ## ## REFERENCE ## [1] Equation 2.28 from Steven M. Kay and Stanley Lawrence Marple Jr.: ## "Spectrum analysis -- a modern perspective", ## Proceedings of the IEEE, Vol 69, pp 1380-1419, Nov., 1981 ## ## @end deftypefn function varargout = ar_psd(a,v,varargin) ## ## Check fixed arguments if ( nargin < 2 ) error( 'ar_psd: needs at least 2 args. Use help ar_psd.' ); elseif ( ~isvector(a) || length(a)<2 ) error( 'ar_psd: arg 1 (a) must be vector, length>=2.' ); elseif ( ~isscalar(v) ) error( 'ar_psd: arg 2 (v) must be real scalar >0.' ); else real_model = isreal(a); ## ## default values for optional arguments freq = 256; user_freqs = 0; ## boolean: true for user-specified frequencies Fs = 1.0; ## FFT padding factor (is also frequency range divisor): 1=whole, 2=half. pad_fact = 1 + real_model; do_shift = 0; force_FFT = 0; force_poly = 0; plot_type = 1; ## ## decode and check optional arguments ## end_numeric_args is boolean; becomes true at 1st string arg end_numeric_args = 0; for iarg = 1:length(varargin) arg = varargin{iarg}; end_numeric_args = end_numeric_args || ischar(arg); ## skip empty arguments if ( isempty(arg) ) 1; ## numeric optional arguments must be first, cannot follow string args ## N.B. older versions of matlab may not have the function "error" so ## the user writes "function error(msg); disp(msg); end" and we need ## a "return" here. elseif ( ~ischar(arg) ) if ( end_numeric_args ) error( 'ar_psd: control arg must be string.' ); ## ## first optional numeric arg is "freq" elseif ( iarg == 1 ) user_freqs = isvector(arg) && length(arg)>1; if ( ~isscalar(arg) && ~user_freqs ) error( 'ar_psd: arg 3 (freq) must be vector or scalar.' ); elseif ( ~user_freqs && ( ~isreal(arg) || ... fix(arg)~=arg || arg <= 2 || arg >= 1048576 ) ) error('ar_psd: arg 3 (freq) must be integer >=2, <=1048576' ); elseif ( user_freqs && ~isreal(arg) ) error( 'ar_psd: arg 3 (freq) vector must be real.' ); endif freq = arg(:); # -> column vector ## ## second optional numeric arg is "Fs" - sampling frequency elseif ( iarg == 2 ) if ( ~isscalar(arg) || ~isreal(arg) || arg<=0 ) error( 'ar_psd: arg 4 (Fs) must be real positive scalar.' ); endif Fs = arg; ## else error( 'ar_psd: control arg must be string.' ); endif ## ## decode control-string arguments elseif ( strcmp(arg,'plot') || strcmp(arg,'squared') ) plot_type = 1; elseif ( strcmp(arg,'semilogx') ) plot_type = 2; elseif ( strcmp(arg,'semilogy') ) plot_type = 3; elseif ( strcmp(arg,'loglog') ) plot_type = 4; elseif ( strcmp(arg,'dB') ) plot_type = 5; elseif ( strcmp(arg,'fft') ) force_FFT = 1; force_poly = 0; elseif ( strcmp(arg,'poly') ) force_FFT = 0; force_poly = 1; elseif ( strcmp(arg,'half') || strcmp(arg,'onesided') ) pad_fact = 2; # FFT zero-padding factor (pad FFT to double length) do_shift = 0; elseif ( strcmp(arg,'whole') || strcmp(arg,'twosided') ) pad_fact = 1; # FFT zero-padding factor (do not pad) do_shift = 0; elseif ( strcmp(arg,'shift') || strcmp(arg,'centerdc') ) pad_fact = 1; do_shift = 1; else error( 'ar_psd: string arg: illegal value: %s', arg ); endif endfor ## end of decoding and checking args ## if ( user_freqs ) ## user provides (column) vector of frequencies if ( any(abs(freq)>Fs/2) ) error( 'ar_psd: arg 3 (freq) cannot exceed half sampling frequency.' ); elseif ( pad_fact==2 && any(freq<0) ) error( 'ar_psd: arg 3 (freq) must be positive in onesided spectrum' ); endif freq_len = length(freq); fft_len = freq_len; use_FFT = 0; do_shift = 0; else ## internally generated frequencies freq_len = freq; freq = (Fs/pad_fact/freq_len) * [0:freq_len-1]'; ## decide which method to use (poly or FFT) is_power_of_2 = rem(log(freq_len),log(2))<10.*eps; use_FFT = ( ~ force_poly && is_power_of_2 ) || force_FFT; fft_len = freq_len * pad_fact; endif ## ## calculate denominator of Equation 2.28, Kay and Marple, ref [1]Jr.: len_coeffs = length(a); if ( use_FFT ) ## FFT method fft_out = fft( [ a(:); zeros(fft_len-len_coeffs,1) ] ); else ## polynomial method ## complex data on "half" frequency range needs -ve frequency values if ( pad_fact==2 && ~real_model ) freq = [freq; -freq(freq_len:-1:1)]; fft_len = 2*freq_len; endif fft_out = polyval( a(len_coeffs:-1:1), exp( (-i*2*pi/Fs) * freq ) ); endif ## ## The power spectrum (PSD) is the scaled squared reciprocal of amplitude ## of the FFT/polynomial. This is NOT the reciprocal of the periodogram. ## The PSD is a continuous function of frequency. For uniformly ## distributed frequency values, the FFT algorithm might be the most ## efficient way of calculating it. ## psd = ( v / Fs ) ./ ( fft_out .* conj(fft_out) ); ## ## range='half' or 'onesided', ## add PSD at -ve frequencies to PSD at +ve frequencies ## N.B. unlike periodogram, PSD at zero frequency _is_ doubled. if ( pad_fact==2 ) freq = freq(1:freq_len); if ( real_model ) ## real data, double the psd psd = 2 * psd(1:freq_len); elseif ( use_FFT ) ## complex data, FFT method, internally-generated frequencies psd = psd(1:freq_len)+[psd(1); psd(fft_len:-1:freq_len+2)]; else ## complex data, polynomial method ## user-defined and internally-generated frequencies psd = psd(1:freq_len)+psd(fft_len:-1:freq_len+1); endif ## ## range='shift' ## disabled for user-supplied frequencies ## Shift zero-frequency to the middle (pad_fact==1) elseif ( do_shift ) len2 = fix((fft_len+1)/2); psd = [psd(len2+1:fft_len); psd(1:len2)]; freq = [freq(len2+1:fft_len)-Fs; freq(1:len2)]; endif ## ## Plot the spectrum if there are no return variables. if ( nargout >= 2 ) varargout{1} = psd; varargout{2} = freq; elseif ( nargout == 1 ) varargout{1} = psd; else if ( plot_type == 1 ) plot(freq,psd); elseif ( plot_type == 2 ) semilogx(freq,psd); elseif ( plot_type == 3 ) semilogy(freq,psd); elseif ( plot_type == 4 ) loglog(freq,psd); elseif ( plot_type == 5 ) plot(freq,10*log10(psd)); endif endif endif endfunction �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/arburg.m��������������������������������������������������������������������������0000644�0000000�0000000�00000022725�14673270174�012365� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{a}, @var{v}, @var{k}] =} arburg (@var{x}, @var{poles}) ## @deftypefnx {Function File} {[@var{a}, @var{v}, @var{k}] =} arburg (@var{x}, @var{poles}, @var{criterion}) ## ## Calculate coefficients of an autoregressive (AR) model of complex data ## @var{x} using the whitening lattice-filter method of Burg (1968). The ## inverse of the model is a moving-average filter which reduces @var{x} to ## white noise. The power spectrum of the AR model is an estimate of the ## maximum entropy power spectrum of the data. The function @code{ar_psd} ## calculates the power spectrum of the AR model. ## ## ARGUMENTS: ## @itemize ## @item ## @var{x} ## sampled data ## @item ## @var{poles} ## number of poles in the AR model or limit to the number of poles if a ## valid @var{criterion} is provided. ## @item ## @var{criterion} ## model-selection criterion. Limits the number of poles so that spurious ## poles are not added when the whitened data has no more information ## in it (see Kay & Marple, 1981). Recognized values are ## 'AKICc' -- approximate corrected Kullback information criterion (recommended), ## 'KIC' -- Kullback information criterion ## 'AICc' -- corrected Akaike information criterion ## 'AIC' -- Akaike information criterion ## 'FPE' -- final prediction error" criterion ## The default is to NOT use a model-selection criterion ## @end itemize ## ## RETURNED VALUES: ## @itemize ## @item ## @var{a} ## list of (P+1) autoregression coefficients; for data input @math{x(n)} and ## white noise @math{e(n)}, the model is ## ## @example ## @group ## P+1 ## x(n) = sqrt(v).e(n) + SUM a(k).x(n-k) ## k=1 ## @end group ## @end example ## ## @var{v} ## mean square of residual noise from the whitening operation of the Burg ## lattice filter. ## @item ## @var{k} ## reflection coefficients defining the lattice-filter embodiment of the model ## @end itemize ## ## HINTS: ## ## (1) arburg does not remove the mean from the data. You should remove ## the mean from the data if you want a power spectrum. A non-zero mean ## can produce large errors in a power-spectrum estimate. See ## "help detrend". ## (2) If you don't know what the value of "poles" should be, choose the ## largest (reasonable) value you could want and use the recommended ## value, criterion='AKICc', so that arburg can find it. ## E.g. arburg(x,64,'AKICc') ## The AKICc has the least bias and best resolution of the available ## model-selection criteria. ## (3) Autoregressive and moving-average filters are stored as polynomials ## which, in matlab, are row vectors. ## ## NOTE ON SELECTION CRITERION: ## ## AIC, AICc, KIC and AKICc are based on information theory. They attempt ## to balance the complexity (or length) of the model against how well the ## model fits the data. AIC and KIC are biased estimates of the asymmetric ## and the symmetric Kullback-Leibler divergence respectively. AICc and ## AKICc attempt to correct the bias. See reference [4]. ## ## ## REFERENCES: ## ## [1] John Parker Burg (1968) ## "A new analysis technique for time series data", ## NATO advanced study Institute on Signal Processing with Emphasis on ## Underwater Acoustics, Enschede, Netherlands, Aug. 12-23, 1968. ## ## [2] Steven M. Kay and Stanley Lawrence Marple Jr.: ## "Spectrum analysis -- a modern perspective", ## Proceedings of the IEEE, Vol 69, pp 1380-1419, Nov., 1981 ## ## [3] William H. Press and Saul A. Teukolsky and William T. Vetterling and ## Brian P. Flannery ## "Numerical recipes in C, The art of scientific computing", 2nd edition, ## Cambridge University Press, 2002 --- Section 13.7. ## ## [4] Abd-Krim Seghouane and Maiza Bekara ## "A small sample model selection criterion based on Kullback's symmetric ## divergence", IEEE Transactions on Signal Processing, ## Vol. 52(12), pp 3314-3323, Dec. 2004 ## ## @seealso{ar_psd} ## @end deftypefn function varargout = arburg( x, poles, criterion ) ## ## Check arguments if ( nargin < 2 ) error( 'arburg(x,poles): Need at least 2 args.' ); elseif ( ~isvector(x) || length(x) < 3 ) error( 'arburg: arg 1 (x) must be vector of length >2.' ); elseif ( ~isscalar(poles) || ~isreal(poles) || fix(poles)~=poles || poles<=0.5) error( 'arburg: arg 2 (poles) must be positive integer.' ); elseif ( poles >= length(x)-2 ) ## lattice-filter algorithm requires "poles<length(x)" ## AKICc and AICc require "length(x)-poles-2">0 error( 'arburg: arg 2 (poles) must be less than length(x)-2.' ); elseif ( nargin>2 && ~isempty(criterion) && ... (~ischar(criterion) || size(criterion,1)~=1 ) ) error( 'arburg: arg 3 (criterion) must be string.' ); else ## ## Set the model-selection-criterion flags. ## is_AKICc, isa_KIC and is_corrected are short-circuit flags if ( nargin > 2 && ~isempty(criterion) ) is_AKICc = strcmp(criterion,'AKICc'); # AKICc isa_KIC = is_AKICc || strcmp(criterion,'KIC'); # KIC or AKICc is_corrected = is_AKICc || strcmp(criterion,'AICc'); # AKICc or AICc use_inf_crit = is_corrected || isa_KIC || strcmp(criterion,'AIC'); use_FPE = strcmp(criterion,'FPE'); if ( ~use_inf_crit && ~use_FPE ) error( 'arburg: value of arg 3 (criterion) not recognized' ); endif else use_inf_crit = 0; use_FPE = 0; endif ## ## f(n) = forward prediction error ## b(n) = backward prediction error ## Storage of f(n) and b(n) is a little tricky. Because f(n) is always ## combined with b(n-1), f(1) and b(N) are never used, and therefore are ## not stored. Not storing unused data makes the calculation of the ## reflection coefficient look much cleaner :) ## N.B. {initial v} = {error for zero-order model} = ## {zero-lag autocorrelation} = E(x*conj(x)) = x*x'/N ## E = expectation operator N = length(x); k = []; if ( size(x,1) > 1 ) # if x is column vector f = x(2:N); b = x(1:N-1); v = real(x'*x) / N; else # if x is row vector f = x(2:N).'; b = x(1:N-1).'; v = real(x*x') / N; endif ## new_crit/old_crit is the mode-selection criterion new_crit = abs(v); old_crit = 2 * new_crit; for p = 1:poles ## ## new reflection coeff = -2* E(f.conj(b)) / ( E(f^2)+E(b(^2) ) last_k= -2 * (b' * f) / ( f' * f + b' * b); ## Levinson-Durbin recursion for residual new_v = v * ( 1.0 - real(last_k * conj(last_k)) ); if ( p > 1 ) ## ## Apply the model-selection criterion and break out of loop if it ## increases (rather than decreases). ## Do it before we update the old model "a" and "v". ## ## * Information Criterion (AKICc, KIC, AICc, AIC) if ( use_inf_crit ) old_crit = new_crit; ## AKICc = log(new_v)+p/N/(N-p)+(3-(p+2)/N)*(p+1)/(N-p-2); ## KIC = log(new_v)+ 3 *(p+1)/N; ## AICc = log(new_v)+ 2 *(p+1)/(N-p-2); ## AIC = log(new_v)+ 2 *(p+1)/N; ## -- Calculate KIC, AICc & AIC by using is_AKICc, is_KIC and ## is_corrected to "short circuit" the AKICc calculation. ## The extra 4--12 scalar arithmetic ops should be quicker than ## doing if...elseif...elseif...elseif...elseif. new_crit = log(new_v) + is_AKICc*p/N/(N-p) + ... (2+isa_KIC-is_AKICc*(p+2)/N) * (p+1) / (N-is_corrected*(p+2)); if ( new_crit > old_crit ) break; endif ## ## (FPE) Final prediction error elseif ( use_FPE ) old_crit = new_crit; new_crit = new_v * (N+p+1)/(N-p-1); if ( new_crit > old_crit ) break; endif endif ## Update model "a" and "v". ## Use Levinson-Durbin recursion formula (for complex data). a = [ prev_a + last_k .* conj(prev_a(p-1:-1:1)) last_k ]; else # if( p==1 ) a = last_k; endif k = [ k; last_k ]; v = new_v; if ( p < poles ) prev_a = a; ## calculate new prediction errors (by recursion): ## f(p,n) = f(p-1,n) + k * b(p-1,n-1) n=2,3,...n ## b(p,n) = b(p-1,n-1) + conj(k) * f(p-1,n) n=2,3,...n ## remember f(p,1) is not stored, so don't calculate it; make f(p,2) ## the first element in f. b(p,n) isn't calculated either. nn = N-p; new_f = f(2:nn) + last_k * b(2:nn); b = b(1:nn-1) + conj(last_k) * f(1:nn-1); f = new_f; endif endfor varargout{1} = [1 a]; varargout{2} = v; if ( nargout>=3 ) varargout{3} = k; endif endif endfunction �������������������������������������������signal-1.4.6/inst/aryule.m��������������������������������������������������������������������������0000644�0000000�0000000�00000004703�14673270174�012400� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2006 Peter Lanspeary ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{a} =} aryule (@var{x}, @var{p}) ## @deftypefnx {Function File} {[@var{a}, @var{v}, @var{k}] =} aryule (@var{x}, @var{p}) ## Fit an AR (@var{p})-model with Yule-Walker estimates. ## @table @var ## @item x ## data vector to estimate ## @item a ## AR coefficients ## @item v ## variance of white noise ## @item k ## reflection coefficients for use in lattice filter ## @end table ## ## The power spectrum of the resulting filter can be plotted with ## pyulear(x, p), or you can plot it directly with ar_psd(a,v,...). ## ## See also: ## pyulear, power, freqz, impz -- for observing characteristics of the model ## arburg -- for alternative spectral estimators ## ## Example: Use example from arburg, but substitute aryule for arburg. ## ## Note: Orphanidis '85 claims lattice filters are more tolerant of ## truncation errors, which is why you might want to use them. However, ## lacking a lattice filter processor, I haven't tested that the lattice ## filter coefficients are reasonable. ## @end deftypefn function [a, v, k] = aryule (x, p) if ( nargin~=2 ) print_usage; elseif ( ~isvector(x) || length(x)<3 ) error( 'aryule: arg 1 (x) must be vector of length >2' ); elseif ( ~isscalar(p) || fix(p)~=p || p > length(x)-2 ) error( 'aryule: arg 2 (p) must be an integer >0 and <length(x)-1' ); endif c = xcorr(x, p+1, 'biased'); c(1:p+1) = []; # remove negative autocorrelation lags c(1) = real(c(1)); # levinson/toeplitz requires exactly c(1)==conj(c(1)) if nargout <= 1 a = levinson(c, p); elseif nargout == 2 [a, v] = levinson(c, p); else [a, v, k] = levinson(c, p); endif endfunction %!demo %! % use demo('pyulear') �������������������������������������������������������������signal-1.4.6/inst/barthannwin.m���������������������������������������������������������������������0000644�0000000�0000000�00000003016�14673270174�013406� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} barthannwin (@var{m}) ## Return the filter coefficients of a modified Bartlett-Hann window of length ## @var{m}. ## @seealso{rectwin, bartlett} ## @end deftypefn function w = barthannwin (m) if (nargin != 1) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("barthannwin: M must be a positive integer"); endif if (m == 1) w = 1; else N = m - 1; n = 0:N; w = 0.62 -0.48.*abs(n./(m-1) - 0.5)+0.38*cos(2.*pi*(n./(m-1)-0.5)); w = w'; endif endfunction %!assert (barthannwin (1), 1) %!assert (barthannwin (2), zeros (2, 1)) %% Test input validation %!error barthannwin () %!error barthannwin (0.5) %!error barthannwin (-1) %!error barthannwin (ones (1, 4)) %!error barthannwin (1, 2) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/besselap.m������������������������������������������������������������������������0000644�0000000�0000000�00000003137�14673270174�012675� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2009 Thomas Sailer ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{zero}, @var{pole}, @var{gain}] =} besselap (@var{n}) ## Return bessel analog filter prototype. ## ## References: ## ## http://en.wikipedia.org/wiki/Bessel_polynomials ## @end deftypefn function [zero, pole, gain] = besselap (n) if (nargin>1 || nargin<1) print_usage; endif ## interpret the input parameters if (!(length(n)==1 && n == round(n) && n > 0)) error ("besselap: filter order n must be a positive integer"); endif p0=1; p1=[1 1]; for nn=2:n; px=(2*nn-1)*p1; py=[p0 0 0]; px=prepad(px,max(length(px),length(py)),0); py=prepad(py,length(px)); p0=p1; p1=px+py; endfor; ## p1 now contains the reverse bessel polynomial for n ## scale it by replacing s->s/w0 so that the gain becomes 1 p1=p1.*p1(length(p1)).^((length(p1)-1:-1:0)/(length(p1)-1)); zero=[]; pole=roots(p1); gain=1; endfunction ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/besself.m�������������������������������������������������������������������������0000644�0000000�0000000�00000010342�14673270174�012516� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2003 Doug Stewart <dastew@sympatico.ca> ## Copyright (C) 2009 Thomas Sailer <t.sailer@alumni.ethz.ch> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{b}, @var{a}] =} besself (@var{n}, @var{w}) ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} besself (@var{n}, @var{w}, "high") ## @deftypefnx {Function File} {[@var{z}, @var{p}, @var{g}] =} besself (@dots{}) ## @deftypefnx {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} besself (@dots{}) ## @deftypefnx {Function File} {[@dots{}] =} besself (@dots{}, "z") ## Generate a Bessel filter. ## Default is a Laplace space (s) filter. ## ## [b,a] = besself(n, Wc) ## low pass filter with cutoff pi*Wc radians ## ## [b,a] = besself(n, Wc, 'high') ## high pass filter with cutoff pi*Wc radians ## ## [z,p,g] = besself(...) ## return filter as zero-pole-gain rather than coefficients of the ## numerator and denominator polynomials. ## ## [...] = besself(...,'z') ## return a discrete space (Z) filter, W must be less than 1. ## ## [a,b,c,d] = besself(...) ## return state-space matrices ## ## References: ## ## Proakis & Manolakis (1992). Digital Signal Processing. New York: ## Macmillan Publishing Company. ## @end deftypefn function [a, b, c, d] = besself (n, w, varargin) if (nargin > 4 || nargin < 2 || nargout > 4 || nargout < 2) print_usage (); endif ## interpret the input parameters if (! (isscalar (n) && (n == fix (n)) && (n > 0))) error ("besself: filter order N must be a positive integer"); endif stop = false; digital = false; for i = 1:numel (varargin) switch (varargin{i}) case "s" digital = false; case "z" digital = true; case {"high", "stop"} stop = true; case {"low", "pass"} stop = false; otherwise error ("besself: expected [high|stop] or [s|z]"); endswitch endfor ## FIXME: Band-pass and stop-band currently non-functional, remove ## this check once low-pass to band-pass transform is implemented. if (! isscalar (w)) error ("besself: band-pass and stop-band filters not yet implemented"); endif if (! ((numel (w) <= 2) && (rows (w) == 1 || columns (w) == 1))) error ("besself: frequency must be given as WC or [WL, WH]"); elseif ((numel (w) == 2) && (w(2) <= w(1))) error ("besself: W(1) must be less than W(2)"); endif if (digital && ! all ((w >= 0) & (w <= 1))) error ("besself: all elements of W must be in the range [0,1]"); elseif (! digital && ! all (w >= 0)) error ("besself: all elements of W must be in the range [0,inf]"); endif ## Prewarp to the band edges to s plane if (digital) T = 2; # sampling frequency of 2 Hz w = 2 / T * tan (pi * w / T); endif ## Generate splane poles for the prototype Bessel filter [zero, pole, gain] = besselap (n); ## splane frequency transform [zero, pole, gain] = sftrans (zero, pole, gain, w, stop); ## Use bilinear transform to convert poles to the z plane if (digital) [zero, pole, gain] = bilinear (zero, pole, gain, T); endif ## convert to the correct output form if (nargout == 2) a = real (gain * poly (zero)); b = real (poly (pole)); elseif (nargout == 3) a = zero; b = pole; c = gain; else ## output ss results [a, b, c, d] = zp2ss (zero, pole, gain); endif endfunction %% Test input validation %!error [a, b] = besself () %!error [a, b] = besself (1) %!error [a, b] = besself (1, 2, 3, 4, 5) %!error [a, b] = besself (.5, .2) %!error [a, b] = besself (3, .2, "invalid") ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/bilinear.m������������������������������������������������������������������������0000644�0000000�0000000�00000011134�14673270174�012660� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{Zb}, @var{Za}] =} bilinear (@var{Sb}, @var{Sa}, @var{T}) ## @deftypefnx {Function File} {[@var{Zb}, @var{Za}] =} bilinear (@var{Sz}, @var{Sp}, @var{Sg}, @var{T}) ## @deftypefnx {Function File} {[@var{Zz}, @var{Zp}, @var{Zg}] =} bilinear (@dots{}) ## Transform a s-plane filter specification into a z-plane ## specification. Filters can be specified in either zero-pole-gain or ## transfer function form. The input form does not have to match the ## output form. 1/T is the sampling frequency represented in the z plane. ## ## Note: this differs from the bilinear function in the signal processing ## toolbox, which uses 1/T rather than T. ## ## Theory: Given a piecewise flat filter design, you can transform it ## from the s-plane to the z-plane while maintaining the band edges by ## means of the bilinear transform. This maps the left hand side of the ## s-plane into the interior of the unit circle. The mapping is highly ## non-linear, so you must design your filter with band edges in the ## s-plane positioned at 2/T tan(w*T/2) so that they will be positioned ## at w after the bilinear transform is complete. ## ## The following table summarizes the transformation: ## ## @example ## +---------------+-----------------------+----------------------+ ## | Transform | Zero at x | Pole at x | ## | H(S) | H(S) = S-x | H(S)=1/(S-x) | ## +---------------+-----------------------+----------------------+ ## | 2 z-1 | zero: (2+xT)/(2-xT) | zero: -1 | ## | S -> - --- | pole: -1 | pole: (2+xT)/(2-xT) | ## | T z+1 | gain: (2-xT)/T | gain: (2-xT)/T | ## +---------------+-----------------------+----------------------+ ## @end example ## ## With tedious algebra, you can derive the above formulae yourself by ## substituting the transform for S into H(S)=S-x for a zero at x or ## H(S)=1/(S-x) for a pole at x, and converting the result into the ## form: ## ## @example ## H(Z)=g prod(Z-Xi)/prod(Z-Xj) ## @end example ## ## Please note that a pole and a zero at the same place exactly cancel. ## This is significant since the bilinear transform creates numerous ## extra poles and zeros, most of which cancel. Those which do not ## cancel have a "fill-in" effect, extending the shorter of the sets to ## have the same number of as the longer of the sets of poles and zeros ## (or at least split the difference in the case of the band pass ## filter). There may be other opportunistic cancellations but I will ## not check for them. ## ## Also note that any pole on the unit circle or beyond will result in ## an unstable filter. Because of cancellation, this will only happen ## if the number of poles is smaller than the number of zeros. The ## analytic design methods all yield more poles than zeros, so this will ## not be a problem. ## ## References: ## ## Proakis & Manolakis (1992). Digital Signal Processing. New York: ## Macmillan Publishing Company. ## @end deftypefn function [Zz, Zp, Zg] = bilinear(Sz, Sp, Sg, T) if nargin==3 T = Sg; [Sz, Sp, Sg] = tf2zp(Sz, Sp); elseif nargin!=4 print_usage; endif p = length(Sp); z = length(Sz); if z > p || p==0 error("bilinear: must have at least as many poles as zeros in s-plane"); endif ## ---------------- ------------------------- ------------------------ ## Bilinear zero: (2+xT)/(2-xT) pole: (2+xT)/(2-xT) ## 2 z-1 pole: -1 zero: -1 ## S -> - --- gain: (2-xT)/T gain: (2-xT)/T ## T z+1 ## ---------------- ------------------------- ------------------------ Zg = real(Sg * prod((2-Sz*T)/T) / prod((2-Sp*T)/T)); Zp = (2+Sp*T)./(2-Sp*T); if isempty(Sz) Zz = -ones(size(Zp)); else Zz = [(2+Sz*T)./(2-Sz*T)]; Zz = postpad(Zz, p, -1); endif if nargout==2, [Zz, Zp] = zp2tf(Zz, Zp, Zg); endif endfunction ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/bitrevorder.m���������������������������������������������������������������������0000644�0000000�0000000�00000003703�14673270174�013425� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## Copyright (C) 2013-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} bitrevorder (@var{x}) ## @deftypefnx {Function File} {[@var{y} @var{i}] =} bitrevorder (@var{x}) ## Reorder the elements of the vector @var{x} in bit-reversed order. ## Equivalent to calling @code{digitrevorder (@var{x}, 2)}. ## @seealso{digitrevorder, fft, ifft} ## @end deftypefn function [y, i] = bitrevorder (x) if (nargin != 1) print_usage (); elseif (! isvector (x)) error ("bitrevorder: X must be a vector"); elseif (fix (log2 (numel (x))) != log2 (numel (x))) error ("bitrevorder: X must have length equal to an integer power of 2"); endif [y, i] = digitrevorder (x, 2); endfunction %!assert (bitrevorder (0), 0); %!assert (bitrevorder (0:1), 0:1); %!assert (bitrevorder ([0:1]'), [0:1]'); %!assert (bitrevorder (0:7), [0 4 2 6 1 5 3 7]); %!assert (bitrevorder ([0:7]'), [0 4 2 6 1 5 3 7]'); %!assert (bitrevorder ([0:7]*i), [0 4 2 6 1 5 3 7]*i); %!assert (bitrevorder ([0:7]'*i), [0 4 2 6 1 5 3 7]'*i); %!assert (bitrevorder (0:15), [0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15]); %% Test input validation %!error bitrevorder (); %!error bitrevorder (1, 2); %!error bitrevorder ([]); %!error bitrevorder (0:2); �������������������������������������������������������������signal-1.4.6/inst/blackmanharris.m������������������������������������������������������������������0000644�0000000�0000000�00000005167�14673270174�014065� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} blackmanharris (@var{m}) ## @deftypefnx {Function File} {} blackmanharris (@var{m}, "periodic") ## @deftypefnx {Function File} {} blackmanharris (@var{m}, "symmetric") ## Return the filter coefficients of a Blackman-Harris window of length @var{m}. ## ## If the optional argument @code{"periodic"} is given, the periodic form ## of the window is returned. This is equivalent to the window of length ## @var{m}+1 with the last coefficient removed. The optional argument ## @code{"symmetric"} is equivalent to not specifying a second argument. ## ## @seealso{rectwin, bartlett} ## @end deftypefn function w = blackmanharris (m, opt) if (nargin < 1 || nargin > 2) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("blackmanharris: M must be a positive integer"); endif N = m - 1; if (nargin == 2) switch (opt) case "periodic" N = m; case "symmetric" N = m - 1; otherwise error ("blackmanharris: window type must be either \"periodic\" or \"symmetric\""); endswitch endif if (m == 1) w = 1; else a0 = 0.35875; a1 = 0.48829; a2 = 0.14128; a3 = 0.01168; n = [0:m-1]'; w = a0 - a1.*cos(2.*pi.*n./N) + a2.*cos(4.*pi.*n./N) - a3.*cos(6.*pi.*n./N); endif endfunction %!assert (blackmanharris (1), 1); %!assert (blackmanharris (2), 0.00006 * ones (2, 1), eps); %!assert (blackmanharris (15), flipud (blackmanharris (15)), 10*eps); %!assert (blackmanharris (16), flipud (blackmanharris (16)), 10*eps); %!assert (blackmanharris (15), blackmanharris (15, "symmetric")); %!assert (blackmanharris (16)(1:15), blackmanharris (15, "periodic")); %% Test input validation %!error blackmanharris () %!error blackmanharris (0.5) %!error blackmanharris (-1) %!error blackmanharris (ones (1, 4)) %!error blackmanharris (1, 2) %!error blackmanharris (1, "invalid") ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/blackmannuttall.m�����������������������������������������������������������������0000644�0000000�0000000�00000005230�14673270174�014247� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Muthiah Annamalai <muthiah.annamalai@uta.edu> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} blackmannuttall (@var{m}) ## @deftypefnx {Function File} {} blackmannuttall (@var{m}, "periodic") ## @deftypefnx {Function File} {} blackmannuttall (@var{m}, "symmetric") ## Return the filter coefficients of a Blackman-Nuttall window of length ## @var{m}. ## ## If the optional argument @code{"periodic"} is given, the periodic form ## of the window is returned. This is equivalent to the window of length ## @var{m}+1 with the last coefficient removed. The optional argument ## @code{"symmetric"} is equivalent to not specifying a second argument. ## ## @seealso{nuttallwin, kaiser} ## @end deftypefn function w = blackmannuttall (m, opt) if (nargin < 1 || nargin > 2) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("blackmannuttall: M must be a positive integer"); endif N = m - 1; if (nargin == 2) switch (opt) case "periodic" N = m; case "symmetric" N = m - 1; otherwise error ("blackmannuttall: window type must be either \"periodic\" or \"symmetric\""); endswitch endif if (m == 1) w = 1; else a0 = 0.3635819; a1 = 0.4891775; a2 = 0.1365995; a3 = 0.0106411; n = [0:m-1]'; w = a0 - a1.*cos(2.*pi.*n./N) + a2.*cos(4.*pi.*n./N) - a3.*cos(6.*pi.*n./N); endif endfunction %!assert (blackmannuttall (1), 1) %!assert (blackmannuttall (2), 0.0003628 * ones (2, 1), eps) %!assert (blackmannuttall (15), flipud (blackmannuttall (15)), 10*eps); %!assert (blackmannuttall (16), flipud (blackmannuttall (16)), 10*eps); %!assert (blackmannuttall (15), blackmannuttall (15, "symmetric")); %!assert (blackmannuttall (16)(1:15), blackmannuttall (15, "periodic")); %% Test input validation %!error blackmannuttall () %!error blackmannuttall (0.5) %!error blackmannuttall (-1) %!error blackmannuttall (ones (1, 4)) %!error blackmannuttall (1, 2) %!error blackmannuttall (1, "invalid") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/bohmanwin.m�����������������������������������������������������������������������0000644�0000000�0000000�00000003030�14673270174�013051� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} bohmanwin (@var{m}) ## Return the filter coefficients of a Bohman window of length @var{m}. ## @seealso{rectwin, bartlett} ## @end deftypefn function w = bohmanwin (m) if (nargin != 1) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("bohmanwin: M must be a positive integer"); endif if (m == 1) w = 1; else N = m - 1; n = -N/2:N/2; w = (1-2.*abs(n)./N).*cos(2.*pi.*abs(n)./N) + (1./pi).*sin(2.*pi.*abs(n)./N); w(1) = 0; w(length(w))=0; w = w'; endif endfunction %!assert (bohmanwin (1), 1) %!assert (bohmanwin (2), zeros (2, 1)) %% Test input validation %!error bohmanwin () %!error bohmanwin (0.5) %!error bohmanwin (-1) %!error bohmanwin (ones (1, 4)) %!error bohmanwin (1, 2) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/boxcar.m��������������������������������������������������������������������������0000644�0000000�0000000�00000002503�14673270174�012351� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} boxcar (@var{m}) ## Return the filter coefficients of a rectangular window of length @var{m}. ## @end deftypefn function w = boxcar (m) if (nargin != 1) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("boxcar: M must be a positive integer"); endif w = ones(m, 1); endfunction %!assert (boxcar (1), 1) %!assert (boxcar (2), ones (2, 1)) %!assert (boxcar (100), ones (100, 1)) %% Test input validation %!error boxcar () %!error boxcar (0.5) %!error boxcar (-1) %!error boxcar (ones (1, 4)) %!error boxcar (1, 2) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/buffer.m��������������������������������������������������������������������������0000644�0000000�0000000�00000020210�14673270174�012337� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2008-2022 David Bateman <adb014@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} buffer (@var{x}, @var{n}, @var{p}, @var{opt}) ## @deftypefnx {Function File} {[@var{y}, @var{z}, @var{opt}] =} buffer (@dots{}) ## Buffer a signal into a data frame. The arguments to @code{buffer} are ## ## @table @asis ## @item @var{x} ## The data to be buffered. ## ## @item @var{n} ## The number of rows in the produced data buffer. This is an positive ## integer value and must be supplied. ## ## @item @var{p} ## An integer less than @var{n} that specifies the under- or overlap ## between column in the data frame. The default value of @var{p} is 0. ## ## @item @var{opt} ## In the case of an overlap, @var{opt} can be either a vector of length ## @var{p} or the string 'nodelay'. If @var{opt} is a vector, then the ## first @var{p} entries in @var{y} will be filled with these values. If ## @var{opt} is the string 'nodelay', then the first value of @var{y} ## corresponds to the first value of @var{x}. ## ## In the can of an underlap, @var{opt} must be an integer between 0 and ## @code{-@var{p}}. The represents the initial underlap of the first ## column of @var{y}. ## ## The default value for @var{opt} the vector @code{zeros (1, @var{p})} ## in the case of an overlap, or 0 otherwise. ## @end table ## ## In the case of a single output argument, @var{y} will be padded with ## zeros to fill the missing values in the data frame. With two output ## arguments @var{z} is the remaining data that has not been used in the ## current data frame. ## ## Likewise, the output @var{opt} is the overlap, or underlap that might ## be used for a future call to @code{code} to allow continuous buffering. ## @end deftypefn function [y, z, opt] = buffer (x, n, p, opt) if (nargin < 2 || nargin > 4) print_usage (); endif if (!isscalar (n) || n != floor (n)) error ("buffer: n must be an integer"); endif if (nargin < 3) p = 0; elseif (!isscalar (p) || p != floor (p) || p >= n) error ("buffer: p must be an integer less than n"); endif if (nargin < 4) if (p < 0) opt = 0; else opt = zeros (1, p); endif endif if (rows (x) == 1) isrowvec = true; else isrowvec = false; endif if (p < 0) if (isscalar (opt) && opt == floor (opt) && opt >= 0 && opt <= -p) lopt = opt; else error ("buffer: expecting fourth argument to be and integer between 0 and -p"); endif else lopt = 0; endif x = x (:); l = length (x); m = ceil ((l - lopt) / (n - p)); y = zeros (n - p, m); y (1 : l - lopt) = x (lopt + 1 : end); if (p < 0) y (end + p + 1 : end, :) = []; elseif (p > 0) if (ischar (opt)) if (strcmp (opt, "nodelay")) y = [y ; zeros(p, m)]; if (p > n / 2) is = n - p + 1; in = n - p; ie = is + in - 1; off = 1; while (in > 0) y (is : ie, 1 : end - off) = y (1 : in, 1 + off : end); off++; is = ie + 1; ie = ie + in; if (ie > n) ie = n; endif in = ie - is + 1; endwhile [i, j] = ind2sub([n-p, m], l); if (all ([i, j] == [n-p, m])) off--; endif y (:, end - off + 2 : end) = []; else y (end - p + 1 : end, 1 : end - 1) = y (1 : p, 2 : end); if (sub2ind([n-p, m], p, m) >= l) y (:, end) = []; endif endif else error ("buffer: unexpected string argument"); endif elseif (isvector (opt)) if (length (opt) == p) lopt = p; y = [zeros(p, m); y]; in = p; off = 1; out = 1; while (in > 0) y(1:in, off) = opt(out:end); off++; in -= n - p; out += n - p; endwhile if (p > n / 2) in = n - p; ie = p; is = p - in + 1; off = 1; while (ie > 0) y (is : ie, 1 + off : end) = ... y (end - in + 1 : end, 1 : end - off); off++; ie = is - 1; is = is - in; if (is < 1) is = 1; endif in = ie - is + 1; endwhile else y (1 : p, 2 : end) = y (end - p + 1 : end, 1 : end - 1); endif else error ("buffer: opt vector must be of length p"); endif else error ("buffer: unrecognized fourth argument"); endif endif if (nargout > 1) if (p >= 0) [i, j] = ind2sub (size(y), l + lopt + p * (size (y, 2) - 1)); if (any ([i, j] != size (y))) z = y (1 + p : i, end); y (:, end) = []; else z = zeros (0, 1); endif else [i, j] = ind2sub (size (y) + [-p, 0], l - lopt); if (i < size (y, 1)) z = y (1: i, end); y (:, end) = []; else z = zeros (0, 1); endif endif if (isrowvec) z = z.'; endif if (p < 0) opt = max(0, size (y, 2) * (n - p) + opt - l); elseif (p > 0) opt = y(end-p+1:end)(:); else opt = []; endif endif endfunction %!error (buffer(1:10, 4.1)) %!assert (buffer(1:10, 4), reshape([1:10,0,0],[4,3])) %!assert (buffer(1:10, 4, 1), reshape([0:3,3:6,6:9,9,10,0,0],[4,4])) %!assert (buffer(1:10, 4, 2), reshape ([0,0:2,1:4,3:6,5:8,7:10],[4,5])) %!assert (buffer(1:10, 4, 3), [0,0,0:7;0,0:8;0:9;1:10]) %!error (buffer(1:10, 4, 3.1)) %!error (buffer(1:10, 4, 4)) %!assert (buffer(1:10, 4, -1), reshape([1:4,6:9],[4,2])) %!assert (buffer(1:10, 4, -2), reshape([1:4,7:10],[4,2])) %!assert (buffer(1:10, 4, -3), reshape([1:4,8:10,0],[4,2])) %!assert (buffer(1:10, 4, 1, 11), reshape([11,1:3,3:6,6:9,9,10,0,0],[4,4])) %!error (buffer(1:10, 4, 1, [10,11])) %!assert (buffer(1:10, 4, 1, 'nodelay'), reshape([1:4,4:7,7:10],[4,3])) %!error (buffer(1:10, 4, 1, 'badstring')) %!assert (buffer(1:10, 4, 2,'nodelay'), reshape ([1:4,3:6,5:8,7:10],[4,4])) %!assert (buffer(1:10, 4, 3, [11,12,13]),[11,12,13,1:7;12,13,1:8;13,1:9;1:10]) %!assert (buffer(1:10, 4, 3, 'nodelay'),[1:8;2:9;3:10;4:10,0]) %!assert (buffer(1:11,4,-2,1),reshape([2:5,8:11],4,2)) %!test %! [y, z] = buffer(1:12,4); %! assert (y, reshape(1:12,4,3)); %! assert (z, zeros (1,0)); %!test %! [y, z] = buffer(1:11,4); %! assert (y, reshape(1:8,4,2)); %! assert (z, [9, 10, 11]); %!test %! [y, z] = buffer([1:12]',4); %! assert (y, reshape(1:12,4,3)); %! assert (z, zeros (0,1)); %!test %! [y, z] = buffer([1:11]',4); %! assert (y, reshape(1:8,4,2)); %! assert (z, [9; 10; 11]); %!test %! [y,z,opt] = buffer(1:15,4,-2,1); %! assert (y, reshape([2:5,8:11],4,2)); %! assert (z, [14, 15]); %! assert (opt, 0); %!test %! [y,z,opt] = buffer(1:11,4,-2,1); %! assert (y, reshape([2:5,8:11],4,2)); %! assert (z, zeros (1,0)); %! assert (opt, 2); %!test %! [y,z,opt] = buffer([1:15]',4,-2,1); %! assert (y, reshape([2:5,8:11],4,2)); %! assert (z, [14; 15]); %! assert (opt, 0); %!test %! [y,z,opt] = buffer([1:11]',4,-2,1); %! assert (y, reshape([2:5,8:11],4,2)); %! assert (z, zeros (0, 1)); %! assert (opt, 2); %!test %! [y,z,opt] = buffer([1:11],5,2,[-1,0]); %! assert (y, reshape ([-1:3,2:6,5:9],[5,3])); %! assert (z, [10, 11]); %! assert (opt, [8; 9]); %!test %! [y,z,opt] = buffer([1:11]',5,2,[-1,0]); %! assert (y, reshape ([-1:3,2:6,5:9],[5,3])); %! assert (z, [10; 11]); %! assert (opt, [8; 9]); %!test %! [y, z, opt] = buffer (1:10, 6, 4); %! assert (y, [0 0 1:2:5; 0 0 2:2:6; 0 1:2:7; 0 2:2:8; 1:2:9; 2:2:10]) %! assert (z, zeros (1, 0)) %! assert (opt, [7; 8; 9; 10]) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/buttap.m��������������������������������������������������������������������������0000644�0000000�0000000�00000002411�14673270174�012370� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013 CarnĂ« Draug <carandraug+dev@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{z}, @var{p}, @var{g}] =} buttap (@var{n}) ## Design lowpass analog Butterworth filter. ## ## This function exists for @sc{matlab} compatibility only, and is equivalent ## to @code{butter (@var{n}, 1, "s")}. ## ## @seealso{butter} ## @end deftypefn function [z, p, g] = buttap (n) if (nargin != 1) print_usage(); elseif (! isscalar (n) || ! isnumeric (n) || fix (n) != n || n <= 0) error ("buttap: N must be a positive integer") endif [z, p, g] = butter (n, 1, "s"); endfunction �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/butter.m��������������������������������������������������������������������������0000644�0000000�0000000�00000022331�14673270174�012401� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2003 Doug Stewart <dastew@sympatico.ca> ## Copyright (C) 2011 Alexander Klein <alexander.klein@math.uni-giessen.de> ## Copyright (C) 2018 John W. Eaton ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{b}, @var{a}] =} butter (@var{n}, @var{wc}) ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} butter (@var{n}, @var{wc}, @var{filter_type}) ## @deftypefnx {Function File} {[@var{z}, @var{p}, @var{g}] =} butter (@dots{}) ## @deftypefnx {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} butter (@dots{}) ## @deftypefnx {Function File} {[@dots{}] =} butter (@dots{}, "s") ## Generate a Butterworth filter. ## Default is a discrete space (Z) filter. ## ## The cutoff frequency, @var{wc} should be specified in radians for ## analog filters. For digital filters, it must be a value between zero ## and one. For bandpass filters, @var{wc} is a two-element vector ## with @code{w(1) < w(2)}. ## ## The filter type must be one of @qcode{"low"}, @qcode{"high"}, ## @qcode{"bandpass"}, or @qcode{"stop"}. The default is @qcode{"low"} ## if @var{wc} is a scalar and @qcode{"bandpass"} if @var{wc} is a ## two-element vector. ## ## If the final input argument is @qcode{"s"} design an analog Laplace ## space filter. ## ## Low pass filter with cutoff @code{pi*Wc} radians: ## ## @example ## [b, a] = butter (n, Wc) ## @end example ## ## High pass filter with cutoff @code{pi*Wc} radians: ## ## @example ## [b, a] = butter (n, Wc, "high") ## @end example ## ## Band pass filter with edges @code{pi*Wl} and @code{pi*Wh} radians: ## ## @example ## [b, a] = butter (n, [Wl, Wh]) ## @end example ## ## Band reject filter with edges @code{pi*Wl} and @code{pi*Wh} radians: ## ## @example ## [b, a] = butter (n, [Wl, Wh], "stop") ## @end example ## ## Return filter as zero-pole-gain rather than coefficients of the ## numerator and denominator polynomials: ## ## @example ## [z, p, g] = butter (@dots{}) ## @end example ## ## Return a Laplace space filter, @var{Wc} can be larger than 1: ## ## @example ## [@dots{}] = butter (@dots{}, "s") ## @end example ## ## Return state-space matrices: ## ## @example ## [a, b, c, d] = butter (@dots{}) ## @end example ## ## References: ## ## Proakis & Manolakis (1992). Digital Signal Processing. New York: ## Macmillan Publishing Company. ## @end deftypefn function [a, b, c, d] = butter (n, wc, varargin) if (nargin > 4 || nargin < 2 || nargout > 4) print_usage (); endif type = "lowpass"; stop = false; digital = true; if (! (isscalar (n) && (n == fix (n)) && (n > 0))) error ("butter: filter order N must be a positive integer"); endif if (! isvector (wc) || numel (wc) > 2) error ("butter: cutoff frequency must be given as WC or [WL, WH]"); endif if (numel (wc) == 2) if (wc(1) > wc(2)) error ("butter: W(1) must be less than W(2)"); endif type = "bandpass"; stop = false; endif ## Is final argument "s" (or "z")? if (numel (varargin) > 0) switch (varargin{end}) case "s" digital = false; varargin(end) = []; case "z" ## This is the default setting. ## Accept "z" for backward compatibility with older versions ## of Octave's signal processing package. varargin(end) = []; endswitch endif ## Is filter type specified? if (numel (varargin) > 0) switch (varargin{end}) case {"high", "stop"} type = varargin{end}; stop = true; varargin(end) = []; case {"low", "bandpass"} type = varargin{end}; stop = false; varargin(end) = []; case "pass" ## Accept "pass" for backward compatibility with older versions ## of Octave's signal processing package. type = "bandpass"; stop = false; varargin(end) = []; otherwise error ("butter: expected 'high', 'stop', 'low', 'bandpass', or 's'"); endswitch endif if (numel (varargin) > 0) ## Invalid arguments. For example: butter (n, wc, "s", "high"). print_usage (); endif switch (type) case {"stop", "bandpass"} if (numel (wc) != 2) error ("butter: Wc must be two elements for stop and bandpass filters"); endif endswitch if (digital && ! all ((wc >= 0) & (wc <= 1))) error ("butter: all elements of Wc must be in the range [0,1]"); elseif (! digital && ! all (wc >= 0)) error ("butter: all elements of Wc must be in the range [0,inf]"); endif ## Prewarp to the band edges to s plane if (digital) T = 2; # sampling frequency of 2 Hz wc = 2 / T * tan (pi * wc / T); endif ## Generate splane poles for the prototype Butterworth filter ## source: Kuc C = 1; ## default cutoff frequency pole = C * exp (1i * pi * (2 * [1:n] + n - 1) / (2 * n)); if (mod (n, 2) == 1) pole((n + 1) / 2) = -1; ## pure real value at exp(i*pi) endif zero = []; gain = C^n; ## splane frequency transform [zero, pole, gain] = sftrans (zero, pole, gain, wc, stop); ## Use bilinear transform to convert poles to the z plane if (digital) [zero, pole, gain] = bilinear (zero, pole, gain, T); endif ## convert to the correct output form ## note that poly always outputs a row vector if (nargout <= 2) a = real (gain * poly (zero)); b = real (poly (pole)); elseif (nargout == 3) a = zero(:); b = pole(:); c = gain; else ## output ss results [a, b, c, d] = zp2ss (zero, pole, gain); endif endfunction %!shared sf, sf2, off_db %! off_db = 0.5; %! ## Sampling frequency must be that high to make the low pass filters pass. %! sf = 6000; sf2 = sf/2; %! data=[sinetone(5,sf,10,1),sinetone(10,sf,10,1),sinetone(50,sf,10,1),sinetone(200,sf,10,1),sinetone(400,sf,10,1)]; %!test %! ## Test low pass order 1 with 3dB @ 50Hz %! data=[sinetone(5,sf,10,1),sinetone(10,sf,10,1),sinetone(50,sf,10,1),sinetone(200,sf,10,1),sinetone(400,sf,10,1)]; %! [b, a] = butter ( 1, 50 / sf2 ); %! filtered = filter ( b, a, data ); %! damp_db = 20 * log10 ( max ( filtered ( end - sf : end, : ) ) ); %! assert ( [ damp_db( 4 ) - damp_db( 5 ), damp_db( 1 : 3 ) ], [ 6 0 0 -3 ], off_db ) %!test %! ## Test low pass order 4 with 3dB @ 50Hz %! data=[sinetone(5,sf,10,1),sinetone(10,sf,10,1),sinetone(50,sf,10,1),sinetone(200,sf,10,1),sinetone(400,sf,10,1)]; %! [b, a] = butter ( 4, 50 / sf2 ); %! filtered = filter ( b, a, data ); %! damp_db = 20 * log10 ( max ( filtered ( end - sf : end, : ) ) ); %! assert ( [ damp_db( 4 ) - damp_db( 5 ), damp_db( 1 : 3 ) ], [ 24 0 0 -3 ], off_db ) %!test %! ## Test high pass order 1 with 3dB @ 50Hz %! data=[sinetone(5,sf,10,1),sinetone(10,sf,10,1),sinetone(50,sf,10,1),sinetone(200,sf,10,1),sinetone(400,sf,10,1)]; %! [b, a] = butter ( 1, 50 / sf2, "high" ); %! filtered = filter ( b, a, data ); %! damp_db = 20 * log10 ( max ( filtered ( end - sf : end, : ) ) ); %! assert ( [ damp_db( 2 ) - damp_db( 1 ), damp_db( 3 : end ) ], [ 6 -3 0 0 ], off_db ) %!test %! ## Test high pass order 4 with 3dB @ 50Hz %! data=[sinetone(5,sf,10,1),sinetone(10,sf,10,1),sinetone(50,sf,10,1),sinetone(200,sf,10,1),sinetone(400,sf,10,1)]; %! [b, a] = butter ( 4, 50 / sf2, "high" ); %! filtered = filter ( b, a, data ); %! damp_db = 20 * log10 ( max ( filtered ( end - sf : end, : ) ) ); %! assert ( [ damp_db( 2 ) - damp_db( 1 ), damp_db( 3 : end ) ], [ 24 -3 0 0 ], off_db ) %% Test input validation %!error [a, b] = butter () %!error [a, b] = butter (1) %!error [a, b] = butter (1, 2, 3, 4, 5) %!error [a, b] = butter (.5, .2) %!error [a, b] = butter (3, .2, "invalid") %!error [a, b] = butter (9, .6, "stop") %!error [a, b] = butter (9, .6, "bandpass") %!error [a, b] = butter (9, .6, "s", "high") %% Test output orientation %!test %! butter (9, .6); %! assert (isrow (ans)); %!test %! A = butter (9, .6); %! assert (isrow (A)); %!test %! [A, B] = butter (9, .6); %! assert (isrow (A)); %! assert (isrow (B)); %!test %! [z, p, g] = butter (9, .6); %! assert (iscolumn (z)); %! assert (iscolumn (p)); %! assert (isscalar (g)); %!test %! [a, b, c, d] = butter (9, .6); %! assert (ismatrix (a)); %! assert (iscolumn (b)); %! assert (isrow (c)); %! assert (isscalar (d)); %!demo %! sf = 800; sf2 = sf/2; %! data=[[1;zeros(sf-1,1)],sinetone(25,sf,1,1),sinetone(50,sf,1,1),sinetone(100,sf,1,1)]; %! [b,a]=butter ( 1, 50 / sf2 ); %! filtered = filter(b,a,data); %! %! clf %! subplot ( columns ( filtered ), 1, 1) %! plot(filtered(:,1),";Impulse response;") %! subplot ( columns ( filtered ), 1, 2 ) %! plot(filtered(:,2),";25Hz response;") %! subplot ( columns ( filtered ), 1, 3 ) %! plot(filtered(:,3),";50Hz response;") %! subplot ( columns ( filtered ), 1, 4 ) %! plot(filtered(:,4),";100Hz response;") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/buttord.m�������������������������������������������������������������������������0000644�0000000�0000000�00000116106�14673270174�012563� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle ## Copyright (C) 2018 Charles Praplan ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{n} =} buttord (@var{wp}, @var{ws}, @var{rp}, @var{rs}) ## @deftypefnx {Function File} {@var{n} =} buttord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}) ## @deftypefnx {Function File} {@var{n} =} buttord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}, "s") ## @deftypefnx {Function File} {[@var{n}, @var{wc_p}] =} buttord (@dots{}) ## @deftypefnx {Function File} {[@var{n}, @var{wc_p}, @var{wc_s}] =} buttord (@dots{}) ## Compute the minimum filter order of a Butterworth filter with the desired ## response characteristics. The filter frequency band edges are specified by ## the passband frequency @var{wp} and stopband frequency @var{ws}. Frequencies ## are normalized to the Nyquist frequency in the range [0,1]. @var{rp} is the ## allowable passband ripple measured in decibels, and @var{rs} is the minimum ## attenuation in the stop band, also in decibels. ## ## The output arguments @var{n} and @var{wc_p} (or @var{n} and @var{wc_n}) can ## be given as inputs to @code{butter}. ## Using @var{wc_p} makes the filter characteristic touch at least one pass band ## corner and using @var{wc_s} makes the characteristic touch at least one ## stop band corner. ## ## If @var{wp} and @var{ws} are scalars, then @var{wp} is the passband cutoff ## frequency and @var{ws} is the stopband edge frequency. If @var{ws} is ## greater than @var{wp}, the filter is a low-pass filter. If @var{wp} is ## greater than @var{ws}, the filter is a high-pass filter. ## ## If @var{wp} and @var{ws} are vectors of length 2, then @var{wp} defines the ## passband interval and @var{ws} defines the stopband interval. If @var{wp} ## is contained within @var{ws} (@var{ws1} < @var{wp1} < @var{wp2} < @var{ws2}), ## the filter is a band-pass filter. If @var{ws} is contained within @var{wp} ## (@var{wp1} < @var{ws1} < @var{ws2} < @var{wp2}), the filter is a band-stop ## or band-reject filter. ## ## If the optional argument @code{"s"} is given, the minimum order for an analog ## elliptic filter is computed. All frequencies @var{wp} and @var{ws} are ## specified in radians per second. ## ## Theory: For Low pass filters, |H(W)|^2 = 1/[1+(W/Wc)^(2N)] = 10^(-R/10). ## With some algebra, you can solve simultaneously for Wc and N given ## Ws,Rs and Wp,Rp. Rounding N to the next greater integer, one can recalculate ## the allowable range for Wc (filter caracteristic touching the pass band edge ## or the stop band edge). ## ## For other types of filter, before making the above calculation, the ## requirements must be transformed to LP requirements. After calculation, Wc ## must be transformed back to original filter type. ## @seealso{butter, cheb1ord, cheb2ord, ellipord} ## @end deftypefn function [n, Wc_p, Wc_s] = buttord (Wp, Ws, Rp, Rs, opt) if (nargin < 4 || nargin > 5) print_usage (); elseif (nargin == 5 && ! strcmp (opt, "s")) error ("ellipord: OPT must be the string \"s\""); endif if (nargin == 5 && strcmp (opt, "s")) s_domain = true; else s_domain = false; endif if (s_domain) validate_filter_bands ("buttord", Wp, Ws, "s"); else validate_filter_bands ("buttord", Wp, Ws); endif if (s_domain) # No prewarp in case of analog filter Wpw = Wp; Wsw = Ws; else ## sampling frequency of 2 Hz T = 2; Wpw = (2 / T) .* tan (pi .* Wp ./ T); # prewarp Wsw = (2 / T) .* tan (pi .* Ws ./ T); # prewarp endif ## pass/stop band to low pass filter transform: if (length (Wpw) == 2 && length (Wsw) == 2) ## Band-pass filter if (Wpw(1) > Wsw(1)) ## Modify band edges if not symmetrical. For a band-pass filter, ## the lower or upper stopband limit is moved, resulting in a smaller ## stopband than the caller requested. if (Wpw(1) * Wpw(2) < Wsw(1) * Wsw(2)) Wsw(2) = Wpw(1) * Wpw(2) / Wsw(1); else Wsw(1) = Wpw(1) * Wpw(2) / Wsw(2); endif w02 = Wpw(1) * Wpw(2); wp = Wpw(2) - Wpw(1); ws = Wsw(2) - Wsw(1); ## Band-stop / band-reject / notch filter else ## Modify band edges if not symmetrical. For a band-stop filter, ## the lower or upper passband limit is moved, resulting in a smaller ## rejection band than the caller requested. if (Wpw(1) * Wpw(2) > Wsw(1) * Wsw(2)) Wpw(2) = Wsw(1) * Wsw(2) / Wpw(1); else Wpw(1) = Wsw(1) * Wsw(2) / Wpw(2); endif w02 = Wpw(1) * Wpw(2); wp = w02 / (Wpw(2) - Wpw(1)); ws = w02 / (Wsw(2) - Wsw(1)); endif ws = ws / wp; wp = 1; ## High-pass filter elseif (Wpw > Wsw) wp = Wsw; ws = Wpw; ## Low-pass filter else wp = Wpw; ws = Wsw; endif ## compute minimum n which satisfies all band edge conditions qs = log (10 ^ (Rs / 10) - 1); qp = log (10 ^ (Rp / 10) - 1); n = ceil (max (0.5 * (qs - qp) ./ log (ws./wp))); ## compute -3dB cutoff given Wp, Rp and n if (length (Wpw) == 2 && length (Wsw) == 2) ## Band-pass filter if (Wpw(1) > Wsw(1)) w_prime_p = exp (log (Wpw) - qp / 2 / n); # same formula as for LP w_prime_s = exp (log (Wsw) - qs / 2 / n); # " ## Band-stop / band-reject / notch filter else w_prime_p = exp( log (Wpw) + qp / 2 / n); # same formula as for HP w_prime_s = exp( log (Wsw) + qs / 2 / n); # " endif ## Applying LP to BP (respectively HP to notch) transformation to -3dB ## angular frequency : ## s_prime/wc = Q(s/w0+w0/s) or w_prime/wc = Q(w/w0-w0/w) ## Here we need to inverse above equation: ## w = abs(w_prime+-sqrt(w_prime^2+4*Q^2))/(2*Q/w0); ## -3dB cutoff freq to match pass band w0 = sqrt (prod (Wpw)); Q = w0 / diff (Wpw); # BW at -Rp dB not at -3dB wc = Wpw; W_prime = w_prime_p(1) / wc(1); # same with w_prime(2)/wc(2) wa = abs (W_prime + sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); wb = abs (W_prime - sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); Wcw_p = [wb wa]; ## -3dB cutoff freq to match stop band w0 = sqrt (prod (Wsw)); Q = w0 / diff (Wsw); # BW at -Rs dB not at -3dB wc = Wsw; W_prime = w_prime_s(1) / wc(1); # same with w_prime(2)/wc(2) wa =abs (W_prime + sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); wb =abs (W_prime - sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); Wcw_s = [wb wa]; ## High-pass filter elseif (Wpw > Wsw) ## -3dB cutoff freq to match pass band Wcw_p = exp (log (Wpw) + qp / 2 / n); ## -3dB cutoff freq to match stop band Wcw_s = exp (log (Wsw) + qs / 2 / n); ## Low-pass filter else ## -3dB cutoff freq to match pass band Wcw_p = exp (log (Wpw) - qp / 2 / n); ## -3dB cutoff freq to match stop band Wcw_s = exp( log (Wsw) - qs / 2 / n); endif if (s_domain) # No prewarp in case of analog filter Wc_p = Wcw_p; Wc_s = Wcw_s; else # Inverse frequency warping for discrete-time filter Wc_p = atan (Wcw_p .* (T / 2)) .* (T / pi); Wc_s = atan (Wcw_s .* (T / 2)) .* (T / pi); endif endfunction %!demo %! fs = 44100; %! Npts = fs / 2; %! fpass = 4000; %! fstop = 10987; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_p); %! f = 8000:12000; %! W = 2 * pi * f; %! [H, f] = freqz (b, a, Npts, fs); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Butterworth low-pass : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! Npts = fs / 2; %! fpass = 4000; %! fstop = 10987; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_s); %! f = 8000:12000; %! W = 2 * pi * f; %! [H, f] = freqz (b, a, Npts, fs); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Butterworth low-pass : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! Npts = fs / 2; %! fstop = 4000; %! fpass = 10987; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_p, "high"); %! f = 8000:12000; %! W = 2 * pi * f; %! [H, f] = freqz (b, a, Npts, fs); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Butterworth high-pass : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [min(f) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! Npts = fs / 2; %! fstop = 4000; %! fpass = 10987; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_s, "high"); %! f = 8000:12000; %! W = 2 * pi * f; %! [H, f] = freqz (b, a, Npts, fs); %! plot (f, 20 * log10 (abs (H))) %! title ("Digital Butterworth high-pass : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [min(f) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [8500 10051]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_p); %! f = (8000:12000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Butterworth band-pass : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on; %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [8500 10051]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_s); %! f = (8000:12000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Butterworth band-pass : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on; %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [9204 10700]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_p); %! f = (8000:12000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Butterworth band-pass : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on; %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [9204 10700]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_s); %! f = (8000:12000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Butterworth band-pass : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on; %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [8500 10833]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_p, "stop"); %! f = (8000:12000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Butterworth notch : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , ... %! 0 , 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [8500 10833]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_s, "stop"); %! f = (8000:12000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Butterworth notch : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , ... %! 0 , 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [9183 11000]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_p, "stop"); %! f = (8000:12000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Butterworth notch : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , ... %! 0 , 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [9183 11000]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = butter (n, Wn_s, "stop"); %! f = (8000:12000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Butterworth notch : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , ... %! 0 , 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = 4000; %! fstop = 13583; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_p, "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))) %! title ("Analog Butterworth low-pass : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = 4000; %! fstop = 13583; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_s, "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))); %! title ("Analog Butterworth low-pass : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = 4000; %! fpass = 13583; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_p, "high", "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))); %! title ("Analog Butterworth high-pass : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = 4000; %! fpass = 13583; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_s, "high", "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))); %! title ("Analog Butterworth high-pass : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9000, 10436]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_p, "s"); %! f = 8000:12000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Butterworth band-pass : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on; %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9000, 10436]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_s, "s"); %! f = 8000:12000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Butterworth band-pass : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on; %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9582, 11000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_p, "s"); %! f = 8000:12000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Butterworth band-pass : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on; %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9582, 11000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_s, "s"); %! f = 8000:12000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Butterworth band-pass : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on; %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = [9875 10126.5823]; %! fpass = [9000 10436]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_p, "stop", "s"); %! f = 8000:12000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Butterworth notch : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , ... %! 0 , 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = [9875 10126.5823]; %! fpass = [9000 10436]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_s, "stop", "s"); %! f = 8000:12000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Butterworth notch : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , ... %! 0 , 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = [9875 10126.5823]; %! fpass = [9582 11000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_p, "stop", "s"); %! f = 8000:12000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Butterworth notch : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , ... %! 0 , 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = [9875 10126.5823]; %! fpass = [9582 11000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = buttord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = butter (n, Wn_s, "stop", "s"); %! f = 8000:12000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Butterworth notch : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , ... %! 0 , 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!test %! # Analog band-pass %! [n, Wn_p, Wn_s] = buttord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9000, 10436], 1, 26, "s"); %! assert (n, 4); %! assert (round (Wn_p), [61903, 63775]); %! assert (round (Wn_s), [61575, 64114]); %!test %! # Analog band-pass %! [n, Wn_p, Wn_s] = buttord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9582, 11000], 1, 26, "s"); %! assert (n, 4); %! assert (round (Wn_p), [61903, 63775]); %! assert (round (Wn_s), [61575, 64115]); %!test %! # Analog band-pass %! [n, Wn_p, Wn_s] = buttord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9000, 10437], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [61850, 63830]); %! assert (round (Wn_s), [61848, 63831]); %!test %! # Analog band-pass %! [n, Wn_p, Wn_s] = buttord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9581, 11000], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [61850, 63830]); %! assert (round (Wn_s), [61847, 63832]); %!test %! # Analog high-pass %! [n, Wn_p, Wn_s] = buttord (2 * pi * 13583, 2 * pi * 4000, 1, 26, "s"); %! assert (n, 4); %! assert (round (Wn_p), 72081); %! assert (round (Wn_s), 53101); %!test %! # Analog high-pass %! [n, Wn_p, Wn_s] = buttord (2 * pi * 13584, 2 * pi * 4000, 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), 68140); %! assert (round (Wn_s), 68138); %!test %! # Analog low-pass %! [n, Wn_p, Wn_s] = buttord (2 * pi * 4000, 2 * pi * 13583, 1, 26, "s"); %! assert (n, 4); %! assert (round (Wn_p), 29757); %! assert (round (Wn_s), 40394); %!test %! # Analog low-pass %! [n, Wn_p, Wn_s] = buttord (2 * pi * 4000, 2 * pi * 13584, 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), 31481); %! assert (round (Wn_s), 31482); %!test %! # Analog notch (narrow band-stop) %! [n, Wn_p, Wn_s] = buttord (2 * pi * [9000, 10436], ... %! 2 * pi * [9875, 10126.5823], 1, 26, "s"); %! assert (n, 4); %! assert (round (Wn_p), [60607, 65138]); %! assert (round (Wn_s), [61184, 64524]); %!test %! # Analog notch (narrow band-stop) %! [n, Wn_p, Wn_s] = buttord (2 * pi * [9582, 11000], ... %! 2 * pi * [9875, 10126.5823], 1, 26, "s"); %! assert (n, 4); %! assert (round (Wn_p), [60606, 65139]); %! assert (round (Wn_s), [61184, 64524]); %!test %! # Analog notch (narrow band-stop) %! [n, Wn_p, Wn_s] = buttord (2 * pi * [9000, 10437], ... %! 2 * pi * [9875, 10126.5823], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [60722, 65015]); %! assert (round (Wn_s), [60726, 65011]); %!test %! # Analog notch (narrow band-stop) %! [n, Wn_p, Wn_s] = buttord (2 * pi * [9581, 11000], ... %! 2 * pi * [9875, 10126.5823], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [60721, 65016]); %! assert (round (Wn_s), [60726, 65011]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * [9500, 9750], ... %! 2 / fs * [8500, 10051], 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 4); %! assert (round (Wn_p), [9477, 9773]); %! assert (round (Wn_s), [9425, 9826]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * [9500, 9750], ... %! 2 / fs * [9204, 10700], 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 4); %! assert (round (Wn_p), [9477, 9773]); %! assert (round (Wn_s), [9425, 9826]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * [9500, 9750], ... %! 2 / fs * [8500, 10052], 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9469, 9782]); %! assert (round (Wn_s), [9468, 9782]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * [9500, 9750], ... %! 2 / fs * [9203, 10700], 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9469, 9782]); %! assert (round (Wn_s), [9468, 9782]); %!test %! # Digital high-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * 10987, 2 / fs * 4000, 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 4); %! assert (round (Wn_p), 9808); %! assert (round (Wn_s), 7780); %!test %! # Digital high-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * 10988, 2 / fs * 4000, 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), 9421); %! assert (round (Wn_s), 9421); %!test %! # Digital low-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * 4000, 2 / fs * 10987, 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 4); %! assert (round (Wn_p), 4686); %! assert (round (Wn_s), 6176); %!test %! # Digital low-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * 4000, 2 / fs * 10988, 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), 4936); %! assert (round (Wn_s), 4936); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * [8500, 10833], ... %! 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 4); %! assert (round (Wn_p), [9369, 10640]); %! assert (round (Wn_s), [9605, 10400]); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * [9183, 11000], ... %! 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 4); %! assert (round (Wn_p), [9370, 10640]); %! assert (round (Wn_s), [9605, 10400]); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * [8500, 10834], ... %! 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9421, 10587]); %! assert (round (Wn_s), [9422, 10587]); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn_p, Wn_s] = buttord (2 / fs * [9182, 11000], ... %! 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9421, 10587]); %! assert (round (Wn_s), [9422, 10587]); ## Test input validation %!error buttord () %!error buttord (.1) %!error buttord (.1, .2) %!error buttord (.1, .2, 3) %!error buttord ([.1 .1], [.2 .2], 3, 4) %!error buttord ([.1 .2], [.5 .6], 3, 4) %!error buttord ([.1 .5], [.2 .6], 3, 4) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cceps.m���������������������������������������������������������������������������0000644�0000000�0000000�00000004356�14673270174�012200� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1994 Dept of Probability Theory and Statistics TU Wien <Andreas.Weingessel@ci.tuwien.ac.at> ## Copyright (C) 2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} cceps (@var{x}) ## @deftypefnx {Function File} {} cceps (@var{x}, @var{correct}) ## Return the complex cepstrum of the vector @var{x}. ## If the optional argument @var{correct} has the value 1, a correction ## method is applied. The default is not to do this. ## @end deftypefn function cep = cceps (x, c) if (nargin == 1) c = false; elseif (nargin != 2) print_usage (); endif [nr, nc] = size (x); if (nc != 1) if (nr == 1) x = x'; nr = nc; else error ("cceps: X must be a vector"); endif endif bad_signal_message = "cceps: signal X has some zero Fourier coefficients"; F = fft (x); if (min (abs (F)) == 0) error (bad_signal_message); endif ## determine if correction necessary half = fix (nr / 2); cor = false; if (2 * half == nr) cor = (c && (real (F (half + 1)) < 0)); if (cor) F = fft (x(1:nr-1)) if (min (abs (F)) == 0) error (bad_signal_message); endif endif endif cep = fftshift (ifft (log (F))); ## make result real if (c) cep = real (cep); if (cor) ## make cepstrum of same length as input vector cep (nr) = 0; endif endif endfunction %!test %! x = randn (256, 1); %! c = cceps (x); %! assert (size (c), size (x)) ## Test input validation %!error cceps () %!error cceps (1, 2, 3) %!error cceps (ones (4)) %!error cceps (0) %!error cceps (zeros (10, 1)) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cconv.m���������������������������������������������������������������������������0000644�0000000�0000000�00000007012�14673270174�012203� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2018 Leonardo Araujo ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{c} =} cconv (@var{a}, @var{b}, @var{n}) ## @deftypefnx {Function File} {@var{c} =} cconv (@var{a}, @var{b}) ## Compute the modulo-N circular convolution. ## ## @var{a} and @var{b} are input vectors and @var{c} is the modolo-@var{n} ## convolution of @var{a} and @var{b}. If @var{n} is not provided, ## its assumed default value is @code{length(@var{a}) + length(@var{b}) - 1}, ## which provides the same result as a linear convolution. ## ## Examples: ## ## @example ## @group ## cconv (1:2, 1:4) ## @result{} 1 4 7 10 8 ## @end group ## @end example ## ## @example ## @group ## cconv (1:2, 1:4, 2) ## @result{} 16 14 ## @end group ## @end example ## ## @example ## @group ## cconv (1:2, 1:4, 4) ## @result{} 9 4 7 10 ## @end group ## @end example ## ## @seealso{conv, circshift} ## @end deftypefn function c = cconv (a, b, n) if (nargin < 2 || nargin > 3) print_usage (); endif la = length (a); lb = length (b); if (nargin == 3) if (! isscalar (n)) error ("cconv: N must be a scalar"); elseif (any (n != fix (n))) error ("cconv: N must be an integer"); endif else n = la + lb - 1; endif if (! isvector (a) || ! isvector (b)) error ("cconv: both arguments A and B must be vectors"); endif flgcolumn = false; if ((la > 1 && iscolumn (a)) || (lb > 1 && iscolumn (b))) flgcolumn = true; endif a = a(:); b = b(:); if (la < lb) a = [a; zeros(lb - la, 1)]; elseif (lb < la) b = [b; zeros(la - lb, 1)]; end N = length (a); if (n < N) an = zeros (n, 1); bn = zeros (n, 1); for i = 0 : N - 1, an(mod (i, n) + 1) += a(i + 1); bn(mod (i, n) + 1) += b(i + 1); endfor a = an; b = bn; elseif (n > N) a = [a; zeros(n - N, 1)]; b = [b; zeros(n - N, 1)]; endif c = ifft (fft (a) .* fft (b)) ; if (!flgcolumn) c = c.'; endif endfunction %!shared x %! x = [1, 2, 3, 4, 5]; %!assert (cconv (x, 1), [1, 2, 3, 4, 5], 2*eps) %!assert (cconv (x', 1), [1; 2; 3; 4; 5], 2*eps) %!assert (real (cconv (x, [1 1])), [1, 3, 5, 7, 9, 5], 2*eps) %!assert (cconv (x, [1 1], 3), [8, 12, 10]) %!assert (cconv ([2 1 2 1], [1 2 3 4]), [2 5 10 16 12 11 4], 1e-14) %!assert (cconv ([2 1 2 1], [1 2 3 4], 4), [14 16 14 16]) %!assert (cconv ([2 1 2 1], [1 2 3 4], 3), [22 17 21]) %!assert (cconv ([2 1 2 1], [1 2 3 4], 2), [28 32]) %!assert (cconv ([2 1 2 1], [1 2 3 4], 1), 60) %!assert (cconv (x*j, 1), [1j, 2j, 3j, 4j, 5j]) %!assert (cconv (x'*j, 1), [1j; 2j; 3j; 4j; 5j]) ## Test input validation %!error cconv () %!error cconv (1) %!error <N must be a scalar> cconv (1, 1, [1 1]) %!error <both arguments A and B must be vectors> cconv (ones (2, 2), 1) %!error <both arguments A and B must be vectors> cconv (1, ones (2, 2)) %!error <N must be an integer> cconv (1, 1, 3.5) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cheb.m����������������������������������������������������������������������������0000644�0000000�0000000�00000003276�14673270174�012004� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2002 AndrĂ© Carezia <acarezia@uol.com.br> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} cheb (@var{n}, @var{x}) ## Returns the value of the nth-order Chebyshev polynomial calculated at ## the point x. The Chebyshev polynomials are defined by the equations: ## ## @example ## @group ## / cos(n acos(x), |x| <= 1 ## Tn(x) = | ## \ cosh(n acosh(x), |x| > 1 ## @end group ## @end example ## ## If x is a vector, the output is a vector of the same size, where each ## element is calculated as y(i) = Tn(x(i)). ## @end deftypefn function T = cheb (n, x) if (nargin != 2) print_usage; elseif !(isscalar (n) && (n == round(n)) && (n >= 0)) error ("cheb: n has to be a positive integer"); endif if (max(size(x)) == 0) T = []; endif ## avoid resizing latencies T = zeros(size(x)); ind = abs (x) <= 1; if (max(size(ind))) T(ind) = cos(n*acos(x(ind))); endif ind = abs (x) > 1; if (max(size(ind))) T(ind) = cosh(n*acosh(x(ind))); endif T = real(T); endfunction ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cheb1ap.m�������������������������������������������������������������������������0000644�0000000�0000000�00000004617�14673270174�012406� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2021 The Octave Project Developers ## Copyright (C) 2013 CarnĂ« Draug <carandraug+dev@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{z}, @var{p}, @var{g}] =} cheb1ap (@var{n}, @var{Rp}) ## Design lowpass analog Chebyshev type I filter. ## ## This function exists for @sc{matlab} compatibility only, and is equivalent ## to @code{cheby1 (@var{n}, @var{Rp}, 1, "s")}. ## ## Input: ## @itemize ## @item @var{N} Order of the filter must be a positive integer ## @item @var{RP} Ripple in the passband in dB ## @end itemize ## ## Output: ## @itemize ## @item @var{z} The zero vector ## @item @var{p} The pole vectorAngle ## @item @var{g} The gain factor ## @end itemize ## ## Example ## @example ## [z, p, g] = cheb1ap (2, 1) ## z = [](0x1) ## p = ## ## -0.54887 - 0.89513i ## -0.54887 + 0.89513i ## ## g = 0.98261 ## @end example ## @seealso{buttap, cheby1, cheb2ap, ellipap} ## @end deftypefn function [z, p, g] = cheb1ap (n, Rp) if (nargin != 2) print_usage (); elseif (! isscalar (n) || ! isnumeric (n) || fix (n) != n || n <= 0) error ("cheb1ap: N must be a positive integer") elseif (! isscalar (Rp) || ! isnumeric (Rp) || Rp < 0) error ("cheb1ap: RP must be a non-negative scalar") endif [z, p, g] = cheby1 (n, Rp, 1, "s"); g = real (g); %Gain should only be the real component endfunction %!error <N must> cheb1ap (-1, 4) %!error <N must> cheb1ap (1.5, 4) %!error <RP must> cheb1ap (2, -1) # From https://ewh.ieee.org/r1/ct/sps/PDF/MATLAB/chapter5.pdf %!test %! [z,p,k]=cheb1ap(4,2); %! assert (isempty(z), 1, 0) %! assert (p, [ -0.10489 - 0.95795i; %! -0.25322 - 0.39680i; %! -0.25322 + 0.39680i; %! -0.10489 + 0.95795i], e-6) %! assert (k, 0.1634, e-6) �����������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cheb1ord.m������������������������������������������������������������������������0000644�0000000�0000000�00000107045�14673270174�012571� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle ## Copyright (C) 2000 Laurent S. Mazet ## Copyright (C) 2018 Charles Praplan ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{n} =} cheb1ord (@var{wp}, @var{ws}, @var{rp}, @var{rs}) ## @deftypefnx {Function File} {@var{n} =} cheb1ord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}) ## @deftypefnx {Function File} {@var{n} =} cheb1ord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}, "s") ## @deftypefnx {Function File} {[@var{n}, @var{wc}] =} cheb1ord (@dots{}) ## @deftypefnx {Function File} {[@var{n}, @var{wc_p}, @var{wc_s}] =} cheb1ord (@dots{}) ## Compute the minimum filter order of a Chebyshev type I filter with the ## desired response characteristics. The filter frequency band edges are ## specified by the passband frequency @var{wp} and stopband frequency @var{ws}. ## Frequencies are normalized to the Nyquist frequency in the range [0,1]. ## @var{rp} is the allowable passband ripple measured in decibels, and @var{rs} ## is the minimum attenuation in the stop band, also in decibels. ## ## The output arguments @var{n} and @var{wc_p} (or @var{n} and @var{wc_s}) can ## be given as inputs to @code{cheby1}. ## Using @var{wc_p} makes the filter characteristic touch at least one pass band ## corner and using @var{wc_s} makes the characteristic touch at least one ## stop band corner. ## ## If @var{wp} and @var{ws} are scalars, then @var{wp} is the passband cutoff ## frequency and @var{ws} is the stopband edge frequency. If @var{ws} is ## greater than @var{wp}, the filter is a low-pass filter. If @var{wp} is ## greater than @var{ws}, the filter is a high-pass filter. ## ## If @var{wp} and @var{ws} are vectors of length 2, then @var{wp} defines the ## passband interval and @var{ws} defines the stopband interval. If @var{wp} ## is contained within @var{ws} (@var{ws1} < @var{wp1} < @var{wp2} < @var{ws2}), ## the filter is a band-pass filter. If @var{ws} is contained within @var{wp} ## (@var{wp1} < @var{ws1} < @var{ws2} < @var{wp2}), the filter is a band-stop ## or band-reject filter. ## ## If the optional argument @code{"s"} is given, the minimum order for an analog ## elliptic filter is computed. All frequencies @var{wp} and @var{ws} are ## specified in radians per second. ## @seealso{buttord, cheby1, cheb2ord, ellipord} ## @end deftypefn function [n, Wc_p, Wc_s] = cheb1ord (Wp, Ws, Rp, Rs, opt) if (nargin < 4 || nargin > 5) print_usage (); elseif (nargin == 5 && ! strcmp (opt, "s")) error ("ellipord: OPT must be the string \"s\""); endif if (nargin == 5 && strcmp (opt, "s")) s_domain = true; else s_domain = false; endif if (s_domain) validate_filter_bands ("cheb1ord", Wp, Ws, "s"); else validate_filter_bands ("cheb1ord", Wp, Ws); endif if (s_domain) # No prewarp in case of analog filter Wpw = Wp; Wsw = Ws; else ## sampling frequency of 2 Hz T = 2; Wpw = (2 / T) .* tan (pi .* Wp ./ T); # prewarp Wsw = (2 / T) .* tan (pi .* Ws ./ T); # prewarp endif ## pass/stop band to low pass filter transform: if (length (Wpw) == 2 && length (Wsw) == 2) ## Band-pass filter if (Wpw(1) > Wsw(1)) ## Modify band edges if not symmetrical. For a band-pass filter, ## the lower or upper stopband limit is moved, resulting in a smaller ## stopband than the caller requested. if (Wpw(1) * Wpw(2) < Wsw(1) * Wsw(2)) Wsw(2) = Wpw(1) * Wpw(2) / Wsw(1); else Wsw(1) = Wpw(1) * Wpw(2) / Wsw(2); endif w02 = Wpw(1) * Wpw(2); wp = Wpw(2) - Wpw(1); ws = Wsw(2) - Wsw(1); ## Band-stop / band-reject / notch filter else ## Modify band edges if not symmetrical. For a band-stop filter, ## the lower or upper passband limit is moved, resulting in a smaller ## rejection band than the caller requested. if (Wpw(1) * Wpw(2) > Wsw(1) * Wsw(2)) Wpw(2) = Wsw(1) * Wsw(2) / Wpw(1); else Wpw(1) = Wsw(1) * Wsw(2) / Wpw(2); endif w02 = Wpw(1) * Wpw(2); wp = w02 / (Wpw(2) - Wpw(1)); ws = w02 / (Wsw(2) - Wsw(1)); endif ws = ws / wp; wp = 1; ## High-pass filter elseif (Wpw > Wsw) wp = Wsw; ws = Wpw; ## Low-pass filter else wp = Wpw; ws = Wsw; endif Wa = ws ./ wp; ## compute minimum n which satisfies all band edge conditions stop_atten = 10 ^ (abs (Rs) / 10); pass_atten = 10 ^ (abs (Rp) / 10); n = ceil (acosh (sqrt ((stop_atten - 1) / (pass_atten - 1))) / acosh (Wa)); ## compute stopband frequency limits to make the the filter characteristic ## touch either at least one stop band corner or one pass band corner. epsilon = 1 / sqrt (10 ^ (.1 * abs (Rs)) - 1); k = cosh (1 / n * acosh (sqrt (1 / (10 ^ (.1 * abs (Rp)) - 1)) / epsilon)); # or k = fstop / fpass if (length (Wpw) == 2 && length (Wsw) == 2) ## Band-pass filter if (Wpw(1) > Wsw(1)) w_prime_p = Wpw; # same formula as for LP w_prime_s = Wsw / k; # " ## Band-stop / band-reject / notch filter else w_prime_p = Wpw; # same formula as for HP w_prime_s = k * Wsw; # " endif ## Applying LP to BP (respectively HP to notch) transformation to ## angular frequency to be returned: ## s_prime/wc = Q(s/w0+w0/s) or w_prime/wc = Q(w/w0-w0/w) ## Here we need to inverse above equation: ## w = abs(w_prime+-sqrt(w_prime^2+4*Q^2))/(2*Q/w0); ## freq to be returned to match pass band w0 = sqrt (prod (Wpw)); Q = w0 / diff (Wpw); # BW at -Rp dB not at -3dB wc = Wpw; W_prime = w_prime_p(1) / wc(1); # same with w_prime(2)/wc(2) wa = abs (W_prime + sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); wb = abs (W_prime - sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); Wcw_p = [wb wa]; ## freq to be returned to match stop band w0 = sqrt (prod (Wsw)); Q = w0 / diff (Wsw); # BW at -Rs dB not at -3dB wc = Wsw; W_prime = w_prime_s(1) / wc(1); # same with w_prime(2)/wc(2) wa = abs (W_prime + sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); wb = abs (W_prime - sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); Wcw_s = [wb wa]; ## High-pass filter elseif (Wpw > Wsw) Wcw_p = Wpw; # to match pass band Wcw_s = Wsw * k; # to match stop band ## Low-pass filter else Wcw_p = Wpw; # to match pass band Wcw_s = Wsw / k; # to match stop band endif if (s_domain) # No prewarp in case of analog filter Wc_p = Wcw_p; Wc_s = Wcw_s; else # Inverse frequency warping for discrete-time filter Wc_p = atan (Wcw_p .* (T / 2)) .* (T / pi); Wc_s = atan (Wcw_s .* (T / 2)) .* (T / pi); endif endfunction %!demo %! fs = 44100; %! fpass = 4000; %! fstop = 10988; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_p); %! SYS = tf (b, a, 1 / fs); %! f = (0:fs/2)'; %! W = f * (2 * pi / fs); %! [H, P] = bode (SYS, 2 * pi * f); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev low-pass Typ I : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = 4000; %! fstop = 10988; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_s); %! SYS = tf (b, a, 1 / fs); %! f = (0:fs/2)'; %! W = f * (2 * pi / fs); %! [H, P] = bode (SYS, 2 * pi * f); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev low-pass Typ I : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = 4000; %! fpass = 10988; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_p, "high"); %! f = (0:fs/2)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev high-pass Typ I : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [min(f) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = 4000; %! fpass = 10988; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_s, "high"); %! f = (0:fs/2)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev high-pass Typ I : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [min(f) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [8500, 10052]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_p); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev band-pass Typ I : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [8500, 10052]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_s); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev band-pass Typ I : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [9182 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_p); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev band-pass Typ I : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [9182 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_s); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev band-pass Typ I : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [8500, 10834]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_p, "stop"); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! Ampl = abs (H); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev notch Typ I : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [8500, 10834]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_s, "stop"); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! Ampl = abs (H); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev notch Typ I : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [9182, 12000]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_p, "stop"); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! Ampl = abs (H); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev notch Typ I : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [9182, 12000]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby1 (n, Rpass, Wn_s, "stop"); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! Ampl = abs (H); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev notch Typ I : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = 4000; %! fstop = 13584; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_p, "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev low-pass Typ I : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = 4000; %! fstop = 13584; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_s, "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev low-pass Typ I : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = 4000; %! fpass = 13584; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_p, "high", "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev high-pass Typ I : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = 4000; %! fpass = 13584; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_s, "high", "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev high-pass Typ I : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9000, 10437]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_p, "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev band-pass Typ I : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9000, 10437]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_s, "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev band-pass Typ I : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9581, 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_p, "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev band-pass Typ I : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9581, 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_s, "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev band-pass Typ I : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fstop = [9875, 10126.5823]; %! fpass = [9000, 10437]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_p, "stop", "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev notch Typ I : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = [9875, 10126.5823]; %! fpass = [9000, 10437]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_s, "stop", "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev notch Typ I : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = [9875, 10126.5823]; %! fpass = [9581 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_p, "stop", "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev notch Typ I : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = [9875, 10126.5823]; %! fpass = [9581 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb1ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby1 (n, Rpass, Wn_s, "stop", "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev notch Typ I : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!test %! # Analog band-pass %! [n, Wn_p, Wn_s] = cheb1ord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9000, 10437], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [62046, 63627]); %! assert (round (Wn_s), [61652, 64035]); %!test %! # Analog band-pass %! [n, Wn_p, Wn_s] = cheb1ord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9581 12000], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [62046, 63627]); %! assert (round (Wn_s), [61651, 64036]); %!test %! # Analog high-pass %! [n, Wn_p, Wn_s] = cheb1ord (2 * pi * 13584, 2 * pi * 4000, 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), 85351); %! assert (round (Wn_s), 56700); %!test %! # Analog low-pass %! [n, Wn_p, Wn_s] = cheb1ord (2 * pi * 4000, 2 * pi * 13584, 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), 25133); %! assert (round (Wn_s), 37832); %!test %! # Analog notch (narrow band-stop) %! [n, Wn_p, Wn_s] = cheb1ord (2 * pi * [9000, 10437], ... %! 2 * pi * [9875, 10126.5823], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [60201, 65578]); %! assert (round (Wn_s), [61074, 64640]); %!test %! # Analog notch (narrow band-stop) %! [n, Wn_p, Wn_s] = cheb1ord (2 * pi * [9581, 12000], ... %! 2 * pi * [9875, 10126.5823], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [60199, 65580]); %! assert (round (Wn_s), [61074, 64640]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb1ord (2 / fs * [9500, 9750], ... %! 2 / fs * [8500, 10052], 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9500, 9750]); %! assert (round (Wn_s), [9437, 9814]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb1ord (2 / fs * [9500, 9750], ... %! 2 / fs * [9182, 12000], 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9500, 9750]); %! assert (round (Wn_s), [9428, 9823]); %!test %! # Digital high-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb1ord (2 / fs * 10988, 2 / fs * 4000, 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), 10988); %! assert (round (Wn_s), 8197); %!test %! # Digital low-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb1ord (2 / fs * 4000, 2 / fs * 10988, 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), 4000); %! assert (round (Wn_s), 5829); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb1ord (2 / fs * [8500, 10834], ... %! 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9182, 10834]); %! assert (round (Wn_s), [9475, 10532]); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb1ord (2 / fs * [9182 12000], ... %! 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9182, 10834]); %! assert (round (Wn_s), [9475, 10532]); ## Test input validation %!error cheb1ord () %!error cheb1ord (.1) %!error cheb1ord (.1, .2) %!error cheb1ord (.1, .2, 3) %!error cheb1ord ([.1 .1], [.2 .2], 3, 4) %!error cheb1ord ([.1 .2], [.5 .6], 3, 4) %!error cheb1ord ([.1 .5], [.2 .6], 3, 4) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cheb2ap.m�������������������������������������������������������������������������0000644�0000000�0000000�00000003602�14673270174�012400� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013 CarnĂ« Draug <carandraug+dev@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{z}, @var{p}, @var{g}] =} cheb2ap (@var{n}, @var{Rs}) ## Design lowpass analog Chebyshev type II filter. ## ## This function exists for @sc{matlab} compatibility only, and is equivalent ## to @code{cheby2 (@var{n}, @var{Rs}, 1, "s")}. ## ## Demo ## @example ## demo cheb2ap ## @end example ## ## @seealso{cheby2} ## @end deftypefn function [z, p, g] = cheb2ap (n, Rs) if (nargin != 2) print_usage(); elseif (! isscalar (n) || ! isnumeric (n) || fix (n) != n || n <= 0) error ("cheb2ap: N must be a positive integer") elseif (! isscalar (Rs) || ! isnumeric (Rs) || Rs < 0) error ("cheb2ap: RS must be a non-negative scalar") endif [z, p, g] = cheby2 (n, Rs, 1, "s"); endfunction %!error <N must> cheb2ap (-1, 3) %!error <RS must> cheb2ap (3, -1) #From Steven T. Karris "Signals and Systems Second Edition" [pg. 11-36] %!demo %! w=0:0.01:1000; %! [z, p, k] = cheb2ap (3, 3); %! [b, a] = zp2tf (z, p, k); %! Gs = freqs (b, a, w); %! semilogx (w, abs (Gs)); %! xlabel('Frequency in rad/sec') %! ylabel('Magnitude of G(s)'); %! title('Type 2 Chebyshev Low-Pass Filter, k=3, 3 dB ripple in stop band') %! grid;������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cheb2ord.m������������������������������������������������������������������������0000644�0000000�0000000�00000107033�14673270174�012567� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle ## Copyright (C) 2018 Charles Praplan ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{n} =} cheb2ord (@var{wp}, @var{ws}, @var{rp}, @var{rs}) ## @deftypefnx {Function File} {@var{n} =} cheb2ord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}) ## @deftypefnx {Function File} {@var{n} =} cheb2ord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}, "s") ## @deftypefnx {Function File} {[@var{n}, @var{wc_s}] =} cheb2ord (@dots{}) ## @deftypefnx {Function File} {[@var{n}, @var{wc_s}, @var{wc_p}] =} cheb2ord (@dots{}) ## Compute the minimum filter order of a Chebyshev type II filter with the ## desired response characteristics. The filter frequency band edges are ## specified by the passband frequency @var{wp} and stopband frequency @var{ws}. ## Frequencies are normalized to the Nyquist frequency in the range [0,1]. ## @var{rp} is the allowable passband ripple measured in decibels, and @var{rs} ## is the minimum attenuation in the stop band, also in decibels. ## ## The output arguments @var{n} and @var{wc_p} (or @var{n} and @var{wc_s}) can ## be given as inputs to @code{cheby2}. ## Using @var{wc_p} makes the filter characteristic touch at least one pass band ## corner and using @var{wc_s} makes the characteristic touch at least one ## stop band corner. ## ## If @var{wp} and @var{ws} are scalars, then @var{wp} is the passband cutoff ## frequency and @var{ws} is the stopband edge frequency. If @var{ws} is ## greater than @var{wp}, the filter is a low-pass filter. If @var{wp} is ## greater than @var{ws}, the filter is a high-pass filter. ## ## If @var{wp} and @var{ws} are vectors of length 2, then @var{wp} defines the ## passband interval and @var{ws} defines the stopband interval. If @var{wp} ## is contained within @var{ws} (@var{ws1} < @var{wp1} < @var{wp2} < @var{ws2}), ## the filter is a band-pass filter. If @var{ws} is contained within @var{wp} ## (@var{wp1} < @var{ws1} < @var{ws2} < @var{wp2}), the filter is a band-stop ## or band-reject filter. ## ## If the optional argument @code{"s"} is given, the minimum order for an analog ## elliptic filter is computed. All frequencies @var{wp} and @var{ws} are ## specified in radians per second. ## @seealso{buttord, cheb1ord, cheby2, ellipord} ## @end deftypefn function [n, Wc_p, Wc_s] = cheb2ord (Wp, Ws, Rp, Rs, opt) if (nargin < 4 || nargin > 5) print_usage (); elseif (nargin == 5 && ! strcmp (opt, "s")) error ("ellipord: OPT must be the string \"s\""); endif if (nargin == 5 && strcmp (opt, "s")) s_domain = true; else s_domain = false; endif if (s_domain) validate_filter_bands ("cheb2ord", Wp, Ws, "s"); else validate_filter_bands ("cheb2ord", Wp, Ws); endif if (s_domain) # No prewarp in case of analog filter Wpw = Wp; Wsw = Ws; else ## sampling frequency of 2 Hz T = 2; Wpw = (2 / T) .* tan (pi .* Wp ./ T); # prewarp Wsw = (2 / T) .* tan (pi .* Ws ./ T); # prewarp endif ## pass/stop band to low pass filter transform: if (length (Wpw) == 2 && length (Wsw) == 2) ## Band-pass filter if (Wpw(1) > Wsw(1)) ## Modify band edges if not symmetrical. For a band-pass filter, ## the lower or upper stopband limit is moved, resulting in a smaller ## stopband than the caller requested. if (Wpw(1) * Wpw(2) < Wsw(1) * Wsw(2)) Wsw(2) = Wpw(1) * Wpw(2) / Wsw(1); else Wsw(1) = Wpw(1) * Wpw(2) / Wsw(2); endif w02 = Wpw(1) * Wpw(2); wp = Wpw(2) - Wpw(1); ws = Wsw(2) - Wsw(1); ## Band-stop / band-reject / notch filter else ## Modify band edges if not symmetrical. For a band-stop filter, ## the lower or upper passband limit is moved, resulting in a smaller ## rejection band than the caller requested. if (Wpw(1) * Wpw(2) > Wsw(1) * Wsw(2)) Wpw(2) = Wsw(1) * Wsw(2) / Wpw(1); else Wpw(1) = Wsw(1) * Wsw(2) / Wpw(2); endif w02 = Wpw(1) * Wpw(2); wp = w02 / (Wpw(2) - Wpw(1)); ws = w02 / (Wsw(2) - Wsw(1)); endif ws = ws / wp; wp = 1; ## High-pass filter elseif (Wpw > Wsw) wp = Wsw; ws = Wpw; ## Low-pass filter else wp = Wpw; ws = Wsw; endif Wa = ws ./ wp; ## compute minimum n which satisfies all band edge conditions stop_atten = 10 ^ (abs (Rs) / 10); pass_atten = 10 ^ (abs (Rp) / 10); n = ceil (acosh (sqrt ((stop_atten - 1) / (pass_atten - 1))) / acosh (Wa)); ## compute stopband frequency limits to make the the filter characteristic ## touch either at least one stop band corner or one pass band corner. epsilon = 1 / sqrt (10 ^ (.1 * abs (Rs)) - 1); k = cosh (1 / n * acosh (sqrt (1 / (10 ^ (.1 * abs (Rp)) - 1)) / epsilon)); # or k = fstop / fpass if (length (Wpw) == 2 && length (Wsw) == 2) ## Band-pass filter if (Wpw(1) > Wsw(1)) w_prime_s = Wsw; # same formula as for LP w_prime_p = k * Wpw; # " ## Band-stop / band-reject / notch filter else w_prime_s = Wsw; # same formula as for HP w_prime_p = Wpw / k; # " endif ## Applying LP to BP (respectively HP to notch) transformation to ## angular frequency to be returned: ## s_prime/wc = Q(s/w0+w0/s) or w_prime/wc = Q(w/w0-w0/w) ## Here we need to inverse above equation: ## w = abs(w_prime+-sqrt(w_prime^2+4*Q^2))/(2*Q/w0); ## freq to be returned to match pass band w0 = sqrt (prod (Wpw)); Q = w0 / diff (Wpw); # BW at -Rp dB not at -3dB wc = Wpw; W_prime = w_prime_p(1) / wc(1); # same with w_prime(2)/wc(2) wa = abs (W_prime + sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); wb = abs (W_prime - sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); Wcw_p = [wb wa]; ## freq to be returned to match stop band w0 = sqrt (prod (Wsw)); Q = w0 / diff (Wsw); # BW at -Rs dB not at -3dB wc = Wsw; W_prime = w_prime_s(1) / wc(1); # same with w_prime(2)/wc(2) wa = abs (W_prime + sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); wb = abs (W_prime - sqrt (W_prime ^ 2 + 4 * Q ^ 2)) / (2 * Q / w0); Wcw_s = [wb wa]; ## High-pass filter elseif (Wpw > Wsw) Wcw_s = Wsw; # to match stop band Wcw_p = Wpw / k; # to match pass band ## Low-pass filter else Wcw_s = Wsw; # to match stop band Wcw_p = k * Wpw; # to match pass band endif if (s_domain) # No prewarp in case of analog filter Wc_s = Wcw_s; Wc_p = Wcw_p; else # Inverse frequency warping for discrete-time filter Wc_s = atan (Wcw_s .* (T / 2)) .* (T / pi); Wc_p = atan (Wcw_p .* (T / 2)) .* (T / pi); endif endfunction %!demo %! fs = 44100; %! fpass = 4000; %! fstop = 10988; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_p); %! SYS = tf (b, a, 1 / fs); %! f = (0:fs/2)'; %! W = f * (2 * pi / fs); %! [H, P] = bode (SYS, 2 * pi * f); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev low-pass Typ II : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = 4000; %! fstop = 10988; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_s); %! SYS = tf (b, a, 1 / fs); %! f = (0:fs/2)'; %! W = f * (2 * pi / fs); %! [H, P] = bode (SYS, 2 * pi * f); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev low-pass Typ II : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = 4000; %! fpass = 10988; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_p, "high"); %! f = (0:fs/2)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev high-pass Typ II : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [min(f) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = 4000; %! fpass = 10988; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_s, "high"); %! f = (0:fs/2)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev high-pass Typ II : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [min(f) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [8500, 10052]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_p); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev band-pass Typ II : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [8500, 10052]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_s); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev band-pass Typ II : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [9182 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_p); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev band-pass Typ II : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fpass = [9500 9750]; %! fstop = [9182 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_s); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev band-pass Typ II : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [8500, 10834]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_p, "stop"); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! Ampl = abs (H); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev notch Typ II : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [8500, 10834]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_s, "stop"); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! Ampl = abs (H); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev notch Typ II : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [9182, 12000]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_p, "stop"); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! Ampl = abs (H); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev notch Typ II : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fs = 44100; %! fstop = [9875, 10126.5823]; %! fpass = [9182, 12000]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2 / fs * fpass; %! Wstop = 2 / fs * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = cheby2 (n, Rstop, Wn_s, "stop"); %! f = (6000:14000)'; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! Ampl = abs (H); %! plot (f, 20 * log10 (abs (H))); %! title ("Digital Chebyshev notch Typ II : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on; %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = 4000; %! fstop = 13584; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_p, "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev low-pass Typ II : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = 4000; %! fstop = 13584; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_s, "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev low-pass Typ II : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on; %! plot (outline_lp_pass_x, outline_lp_pass_y, "m"); %! plot (outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = 4000; %! fpass = 13584; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_p, "high", "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev high-pass Typ II : matching pass band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = 4000; %! fpass = 13584; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_s, "high", "s"); %! f = 1000:10:100000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev high-pass Typ II : matching stop band"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on; %! plot (outline_hp_pass_x, outline_hp_pass_y, "m"); %! plot (outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9000, 10437]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_p, "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev band-pass Typ II : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9000, 10437]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_s, "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev band-pass Typ II : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9581, 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_p, "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev band-pass Typ II : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fpass = [9875, 10126.5823]; %! fstop = [9581, 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_s, "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev band-pass Typ II : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , ... %! -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m"); %! plot (outline_bp_stop_x, outline_bp_stop_y, "m"); %! grid on; %! ylim ([-80, 0]); %!demo %! fstop = [9875, 10126.5823]; %! fpass = [9000, 10437]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_p, "stop", "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev notch Typ II : matching pass band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = [9875, 10126.5823]; %! fpass = [9000, 10437]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_s, "stop", "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev notch Typ II : matching stop band, limit on upper freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = [9875, 10126.5823]; %! fpass = [9581 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_p, "stop", "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev notch Typ II : matching pass band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!demo %! fstop = [9875, 10126.5823]; %! fpass = [9581 12000]; %! Rpass = 1; %! Rstop = 26; %! Wpass = 2 * pi * fpass; %! Wstop = 2 * pi * fstop; %! [n, Wn_p, Wn_s] = cheb2ord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = cheby2 (n, Rstop, Wn_s, "stop", "s"); %! f = 6000:14000; %! W = 2 * pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! title ("Analog Chebyshev notch Typ II : matching stop band, limit on lower freq"); %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! grid on; %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), ... %! fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0, 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m"); %! plot (outline_notch_pass_x_b, outline_notch_pass_y_b, "m"); %! plot (outline_notch_stop_x, outline_notch_stop_y, "m"); %! ylim ([-80, 0]); %!test %! # Analog band-pass %! [n, Wn_p, Wn_s] = cheb2ord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9000, 10437], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [61074, 64640]); %! assert (round (Wn_s), [60201, 65578]); %!test %! # Analog band-pass %! [n, Wn_p, Wn_s] = cheb2ord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9581 12000], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [61074, 64640]); %! assert (round (Wn_s), [60199, 65580]); %!test %! # Analog high-pass %! [n, Wn_p, Wn_s] = cheb2ord (2 * pi * 13584, 2 * pi * 4000, 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), 37832); %! assert (round (Wn_s), 25133); %!test %! # Analog low-pass %! [n, Wn_p, Wn_s] = cheb2ord (2 * pi * 4000, 2 * pi * 13584, 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), 56700); %! assert (round (Wn_s), 85351); %!test %! # Analog notch (narrow band-stop) %! [n, Wn_p, Wn_s] = cheb2ord (2 * pi * [9000, 10437], ... %! 2 * pi * [9875, 10126.5823], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [61652, 64035]); %! assert (round (Wn_s), [62046, 63627]); %!test %! # Analog notch (narrow band-stop) %! [n, Wn_p, Wn_s] = cheb2ord (2 * pi * [9581, 12000], ... %! 2 * pi * [9875, 10126.5823], 1, 26, "s"); %! assert (n, 3); %! assert (round (Wn_p), [61651, 64036]); %! assert (round (Wn_s), [62046, 63627]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb2ord (2 / fs * [9500, 9750], ... %! 2 / fs * [8500, 10052], 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9344, 9908]); %! assert (round (Wn_s), [9203, 10052]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb2ord (2 / fs * [9500, 9750], ... %! 2 / fs * [9182, 12000], 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9344, 9908]); %! assert (round (Wn_s), [9182, 10073]); %!test %! # Digital high-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb2ord (2 / fs * 10988, 2 / fs * 4000, 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), 5829); %! assert (round (Wn_s), 4000); %!test %! # Digital low-pass %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb2ord (2 / fs * 4000, 2 / fs * 10988, 1, 26); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), 8197); %! assert (round (Wn_s), 10988); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb2ord (2 / fs * [8500, 10834], ... %! 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9804, 10198]); %! assert (round (Wn_s), [9875, 10127]); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn_p, Wn_s] = cheb2ord (2 / fs * [9182 12000], ... %! 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn_p = Wn_p * fs / 2; %! Wn_s = Wn_s * fs / 2; %! assert (n, 3); %! assert (round (Wn_p), [9804, 10198]); %! assert (round (Wn_s), [9875, 10127]); ## Test input validation %!error cheb2ord () %!error cheb2ord (.1) %!error cheb2ord (.1, .2) %!error cheb2ord (.1, .2, 3) %!error cheb2ord ([.1 .1], [.2 .2], 3, 4) %!error cheb2ord ([.1 .2], [.5 .6], 3, 4) %!error cheb2ord ([.1 .5], [.2 .6], 3, 4) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/chebwin.m�������������������������������������������������������������������������0000644�0000000�0000000�00000006403�14673270174�012515� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2002 AndrĂ© Carezia <acarezia@uol.com.br> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} chebwin (@var{m}) ## @deftypefnx {Function File} {} chebwin (@var{m}, @var{at}) ## ## Return the filter coefficients of a Dolph-Chebyshev window of length @var{m}. ## The Fourier transform of the window has a stop-band attenuation of @var{at} ## dB. The default attenuation value is 100 dB. ## ## For the definition of the Chebyshev window, see ## ## * Peter Lynch, "The Dolph-Chebyshev Window: A Simple Optimal Filter", ## Monthly Weather Review, Vol. 125, pp. 655-660, April 1997. ## (http://www.maths.tcd.ie/~plynch/Publications/Dolph.pdf) ## ## * C. Dolph, "A current distribution for broadside arrays which ## optimizes the relationship between beam width and side-lobe level", ## Proc. IEEE, 34, pp. 335-348. ## ## The window is described in frequency domain by the expression: ## ## @example ## @group ## Cheb(m-1, beta * cos(pi * k/m)) ## W(k) = ------------------------------- ## Cheb(m-1, beta) ## @end group ## @end example ## ## with ## ## @example ## @group ## beta = cosh(1/(m-1) * acosh(10^(at/20)) ## @end group ## @end example ## ## and Cheb(m,x) denoting the m-th order Chebyshev polynomial calculated ## at the point x. ## ## Note that the denominator in W(k) above is not computed, and after ## the inverse Fourier transform the window is scaled by making its ## maximum value unitary. ## ## @seealso{kaiser} ## @end deftypefn function w = chebwin (m, at) if (nargin < 1 || nargin > 2) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("chebwin: M must be a positive integer"); elseif (nargin == 1) at = 100; elseif (! (isscalar (at) && isreal (at))) error ("chebwin: AT must be a real scalar"); endif if (m == 1) w = 1; else ## beta calculation gamma = 10^(-at/20); beta = cosh(1/(m-1) * acosh(1/gamma)); ## freq. scale k = (0:m-1); x = beta*cos(pi*k/m); ## Chebyshev window (freq. domain) p = cheb(m-1, x); ## inverse Fourier transform if (rem(m,2)) w = real(fft(p)); M = (m+1)/2; w = w(1:M)/w(1); w = [w(M:-1:2) w]'; else ## half-sample delay (even order) p = p.*exp(j*pi/m * (0:m-1)); w = real(fft(p)); M = m/2+1; w = w/w(2); w = [w(M:-1:2) w(2:M)]'; endif endif w = w ./ max (w (:)); endfunction %!assert (chebwin (1), 1) %!assert (chebwin (2), ones (2, 1)) %% Test input validation %!error chebwin () %!error chebwin (0.5) %!error chebwin (-1) %!error chebwin (ones (1, 4)) %!error chebwin (1, 2, 3) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cheby1.m��������������������������������������������������������������������������0000644�0000000�0000000�00000012740�14673270174�012252� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2003 Doug Stewart <dastew@sympatico.ca> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{b}, @var{a}] =} cheby1 (@var{n}, @var{rp}, @var{w}) ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby1 (@var{n}, @var{rp}, @var{w}, "high") ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby1 (@var{n}, @var{rp}, [@var{wl}, @var{wh}]) ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby1 (@var{n}, @var{rp}, [@var{wl}, @var{wh}], "stop") ## @deftypefnx {Function File} {[@var{z}, @var{p}, @var{g}] =} cheby1 (@dots{}) ## @deftypefnx {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} cheby1 (@dots{}) ## @deftypefnx {Function File} {[@dots{}] =} cheby1 (@dots{}, "s") ## Generate a Chebyshev type I filter with @var{rp} dB of passband ripple. ## ## [b, a] = cheby1(n, Rp, Wc) ## low pass filter with cutoff pi*Wc radians ## ## [b, a] = cheby1(n, Rp, Wc, 'high') ## high pass filter with cutoff pi*Wc radians ## ## [b, a] = cheby1(n, Rp, [Wl, Wh]) ## band pass filter with edges pi*Wl and pi*Wh radians ## ## [b, a] = cheby1(n, Rp, [Wl, Wh], 'stop') ## band reject filter with edges pi*Wl and pi*Wh radians ## ## [z, p, g] = cheby1(...) ## return filter as zero-pole-gain rather than coefficients of the ## numerator and denominator polynomials. ## ## [...] = cheby1(...,'s') ## return a Laplace space filter, W can be larger than 1. ## ## [a,b,c,d] = cheby1(...) ## return state-space matrices ## ## References: ## ## Parks & Burrus (1987). Digital Filter Design. New York: ## John Wiley & Sons, Inc. ## @end deftypefn function [a, b, c, d] = cheby1 (n, rp, w, varargin) if (nargin > 5 || nargin < 3 || nargout > 4) print_usage (); endif ## interpret the input parameters if (! (isscalar (n) && (n == fix (n)) && (n > 0))) error ("cheby1: filter order N must be a positive integer"); endif stop = false; digital = true; for i = 1:numel (varargin) switch (varargin{i}) case "s" digital = false; case "z" digital = true; case {"high", "stop"} stop = true; case {"low", "pass"} stop = false; otherwise error ("cheby1: expected [high|stop] or [s|z]"); endswitch endfor if (! ((numel (w) <= 2) && (rows (w) == 1 || columns (w) == 1))) error ("cheby1: frequency must be given as WC or [WL, WH]"); elseif ((numel (w) == 2) && (w(2) <= w(1))) error ("cheby1: W(1) must be less than W(2)"); endif if (digital && ! all ((w >= 0) & (w <= 1))) error ("cheby1: all elements of W must be in the range [0,1]"); elseif (! digital && ! all (w >= 0)) error ("cheby1: all elements of W must be in the range [0,inf]"); endif if (! (isscalar (rp) && isnumeric (rp) && (rp >= 0))) error ("cheby1: passband ripple RP must be a non-negative scalar"); endif ## Prewarp to the band edges to s plane if (digital) T = 2; # sampling frequency of 2 Hz w = 2 / T * tan (pi * w / T); endif ## Generate splane poles and zeros for the Chebyshev type 1 filter C = 1; ## default cutoff frequency epsilon = sqrt (10^(rp / 10) - 1); v0 = asinh (1 / epsilon) / n; pole = exp (1i * pi * [-(n - 1):2:(n - 1)] / (2 * n)); pole = -sinh (v0) * real (pole) + 1i * cosh (v0) * imag (pole); zero = []; ## compensate for amplitude at s=0 gain = prod (-pole); ## if n is even, the ripple starts low, but if n is odd the ripple ## starts high. We must adjust the s=0 amplitude to compensate. if (rem (n, 2) == 0) gain = gain / 10^(rp / 20); endif ## splane frequency transform [zero, pole, gain] = sftrans (zero, pole, gain, w, stop); ## Use bilinear transform to convert poles to the z plane if (digital) [zero, pole, gain] = bilinear (zero, pole, gain, T); endif ## convert to the correct output form ## note that poly always outputs a row vector if (nargout <= 2) a = real (gain * poly (zero)); b = real (poly (pole)); elseif (nargout == 3) a = zero(:); b = pole(:); c = gain; else ## output ss results [a, b, c, d] = zp2ss (zero, pole, gain); endif endfunction %% Test input validation %!error [a, b] = cheby1 () %!error [a, b] = cheby1 (1) %!error [a, b] = cheby1 (1, 2) %!error [a, b] = cheby1 (1, 2, 3, 4, 5, 6) %!error [a, b] = cheby1 (.5, 2, .2) %!error [a, b] = cheby1 (3, 2, .2, "invalid") %% Test output orientation %!test %! cheby1 (3, 4, .5); %! assert (isrow (ans)); %!test %! A = cheby1 (3, 4, .5); %! assert (isrow (A)); %!test %! [A, B] = cheby1 (3, 4, .5); %! assert (isrow (A)); %! assert (isrow (B)); %!test %! [z, p, g] = cheby1 (3, 4, .5); %! assert (iscolumn (z)); %! assert (iscolumn (p)); %! assert (isscalar (g)); %!test %! [a, b, c, d] = cheby1 (3, 4, .5); %! assert (ismatrix (a)); %! assert (iscolumn (b)); %! assert (isrow (c)); %! assert (isscalar (d)); ��������������������������������signal-1.4.6/inst/cheby2.m��������������������������������������������������������������������������0000644�0000000�0000000�00000013627�14673270174�012260� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2003 Doug Stewart <dastew@sympatico.ca> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{b}, @var{a}] =} cheby2 (@var{n}, @var{rs}, @var{wc}) ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby2 (@var{n}, @var{rs}, @var{wc}, "high") ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby2 (@var{n}, @var{rs}, [@var{wl}, @var{wh}]) ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} cheby2 (@var{n}, @var{rs}, [@var{wl}, @var{wh}], "stop") ## @deftypefnx {Function File} {[@var{z}, @var{p}, @var{g}] =} cheby2 (@dots{}) ## @deftypefnx {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} cheby2 (@dots{}) ## @deftypefnx {Function File} {[@dots{}] =} cheby2 (@dots{}, "s") ## Generate a Chebyshev type II filter with @var{rs} dB of stopband attenuation. ## ## [b, a] = cheby2(n, Rs, Wc) ## low pass filter with cutoff pi*Wc radians ## ## [b, a] = cheby2(n, Rs, Wc, 'high') ## high pass filter with cutoff pi*Wc radians ## ## [b, a] = cheby2(n, Rs, [Wl, Wh]) ## band pass filter with edges pi*Wl and pi*Wh radians ## ## [b, a] = cheby2(n, Rs, [Wl, Wh], 'stop') ## band reject filter with edges pi*Wl and pi*Wh radians ## ## [z, p, g] = cheby2(...) ## return filter as zero-pole-gain rather than coefficients of the ## numerator and denominator polynomials. ## ## [...] = cheby2(...,'s') ## return a Laplace space filter, W can be larger than 1. ## ## [a,b,c,d] = cheby2(...) ## return state-space matrices ## ## References: ## ## Parks & Burrus (1987). Digital Filter Design. New York: ## John Wiley & Sons, Inc. ## @end deftypefn function [a, b, c, d] = cheby2 (n, rs, w, varargin) if (nargin > 5 || nargin < 3 || nargout > 4) print_usage (); endif ## interpret the input parameters if (! (isscalar (n) && (n == fix (n)) && (n > 0))) error ("cheby2: filter order N must be a positive integer"); endif stop = false; digital = true; for i = 1:numel (varargin) switch (varargin{i}) case "s" digital = false; case "z" digital = true; case {"high", "stop"} stop = true; case {"low", "pass"} stop = false; otherwise error ("cheby2: expected [high|stop] or [s|z]"); endswitch endfor if (! ((numel (w) <= 2) && (rows (w) == 1 || columns (w) == 1))) error ("cheby2: frequency must be given as WC or [WL, WH]"); elseif ((numel (w) == 2) && (w(2) <= w(1))) error ("cheby2: W(1) must be less than W(2)"); endif if (digital && ! all ((w >= 0) & (w <= 1))) error ("cheby2: all elements of W must be in the range [0,1]"); elseif (! digital && ! all (w >= 0)) error ("cheby2: all elements of W must be in the range [0,inf]"); endif if (! (isscalar (rs) && isnumeric (rs) && (rs >= 0))) error ("cheby2: stopband attenuation RS must be a non-negative scalar"); endif ## Prewarp to the band edges to s plane if (digital) T = 2; # sampling frequency of 2 Hz w = 2 / T * tan (pi * w / T); endif ## Generate splane poles and zeros for the Chebyshev type 2 filter ## From: Stearns, SD; David, RA; (1988). Signal Processing Algorithms. ## New Jersey: Prentice-Hall. C = 1; ## default cutoff frequency lambda = 10^(rs / 20); phi = log (lambda + sqrt (lambda^2 - 1)) / n; theta = pi * ([1:n] - 0.5) / n; alpha = -sinh (phi) * sin (theta); beta = cosh (phi) * cos (theta); if (rem (n, 2)) ## drop theta==pi/2 since it results in a zero at infinity zero = 1i * C ./ cos (theta([1:(n - 1) / 2, (n + 3) / 2:n])); else zero = 1i * C ./ cos (theta); endif pole = C ./ (alpha.^2 + beta.^2) .* (alpha - 1i * beta); ## Compensate for amplitude at s=0 ## Because of the vagaries of floating point computations, the ## prod(pole)/prod(zero) sometimes comes out as negative and ## with a small imaginary component even though analytically ## the gain will always be positive, hence the abs(real(...)) gain = abs (real (prod (pole) / prod (zero))); ## splane frequency transform [zero, pole, gain] = sftrans (zero, pole, gain, w, stop); ## Use bilinear transform to convert poles to the z plane if (digital) [zero, pole, gain] = bilinear (zero, pole, gain, T); endif ## convert to the correct output form ## note that poly always outputs a row vector if (nargout <= 2) a = real (gain * poly (zero)); b = real (poly (pole)); elseif (nargout == 3) a = zero(:); b = pole(:); c = gain; else ## output ss results [a, b, c, d] = zp2ss (zero, pole, gain); endif endfunction %% Test input validation %!error [a, b] = cheby2 () %!error [a, b] = cheby2 (1) %!error [a, b] = cheby2 (1, 2) %!error [a, b] = cheby2 (1, 2, 3, 4, 5, 6) %!error [a, b] = cheby2 (.5, 40, .2) %!error [a, b] = cheby2 (3, 40, .2, "invalid") % %% Test output orientation %!test %! cheby2 (3, 4, .5); %! assert (isrow (ans)); %!test %! A = cheby2 (3, 4, .5); %! assert (isrow (A)); %!test %! [A, B] = cheby2 (3, 4, .5); %! assert (isrow (A)); %! assert (isrow (B)); %!test %! [z, p, g] = cheby2 (3, 4, .5); %! assert (iscolumn (z)); %! assert (iscolumn (p)); %! assert (isscalar (g)); %!test %! [a, b, c, d] = cheby2 (3, 4, .5); %! assert (ismatrix (a)); %! assert (iscolumn (b)); %! assert (isrow (c)); %! assert (isscalar (d)); ���������������������������������������������������������������������������������������������������������signal-1.4.6/inst/chirp.m���������������������������������������������������������������������������0000644�0000000�0000000�00000012307�14673270174�012203� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999-2000 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2018-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} chirp (@var{t}) ## @deftypefnx {Function File} {} chirp (@var{t}, @var{f0}) ## @deftypefnx {Function File} {} chirp (@var{t}, @var{f0}, @var{t1}) ## @deftypefnx {Function File} {} chirp (@var{t}, @var{f0}, @var{t1}, @var{f1}) ## @deftypefnx {Function File} {} chirp (@var{t}, @var{f0}, @var{t1}, @var{f1}, @var{shape}) ## @deftypefnx {Function File} {} chirp (@var{t}, @var{f0}, @var{t1}, @var{f1}, @var{shape}, @var{phase}) ## ## Evaluate a chirp signal at time @var{t}. A chirp signal is a frequency ## swept cosine wave. ## ## @table @var ## @item t ## vector of times to evaluate the chirp signal ## @item f0 ## frequency at time t=0 [ 0 Hz ] ## @item t1 ## time t1 [ 1 sec ] ## @item f1 ## frequency at time t=t1 [ 100 Hz ] ## @item shape ## shape of frequency sweep ## 'linear' f(t) = (f1-f0)*(t/t1) + f0 ## 'quadratic' f(t) = (f1-f0)*(t/t1)^2 + f0 ## 'logarithmic' f(t) = (f1/f0)^(t/t1) * f0 ## @item phase ## phase shift at t=0 ## @end table ## ## For example: ## ## @example ## @group ## @c doctest: +SKIP ## specgram (chirp ([0:0.001:5])); # default linear chirp of 0-100Hz in 1 sec ## specgram (chirp ([-2:0.001:15], 400, 10, 100, "quadratic")); ## soundsc (chirp ([0:1/8000:5], 200, 2, 500, "logarithmic"), 8000); ## @end group ## @end example ## ## If you want a different sweep shape f(t), use the following: ## ## @verbatim ## y = cos (2 * pi * integral (f(t)) + phase); ## @end verbatim ## @end deftypefn function y = chirp (t, f0, t1, f1, shape, phase) if (nargin < 1 || nargin > 6) print_usage (); endif if ((nargin < 2) || (isempty (f0))) ## The default value for f0 depends on the shape if ((nargin >= 5) && (ischar (shape)) && (numel (shape) >= 2) ... && (strncmpi (shape, "logarithmic", numel (shape)))) f0 = 1e-6; else f0 = 0; endif endif if ((nargin < 3) || (isempty (t1))) t1 = 1; endif if ((nargin < 4) || (isempty (f1))) f1 = 100; endif if ((nargin < 5) || (isempty (shape))) shape = "linear"; endif if ((nargin < 6) || (isempty (phase))) phase = 0; endif phase = 2 * pi * phase / 360; if ((numel (shape) >= 2) && (strncmpi (shape, "linear", numel (shape)))) a = pi * (f1 - f0) / t1; b = 2 * pi * f0; y = cos (a * t.^2 + b * t + phase); elseif ((numel (shape) >= 1) ... && (strncmpi (shape, "quadratic", numel (shape)))) a = (2/3 * pi * (f1 - f0) / t1 / t1); b = 2 * pi * f0; y = cos (a * t.^3 + b * t + phase); elseif ((numel (shape) >= 2) ... && (strncmpi (shape, "logarithmic", numel (shape)))) a = 2 * pi * f0 * t1 / log (f1 / f0); x = (f1 / f0) .^ (1 / t1); y = cos (a * x.^t + phase); else error ("chirp: invalid frequency sweep shape '%s'", shape); endif endfunction %!demo %! t = 0:0.001:5; %! y = chirp (t); %! specgram (y, 256, 1000); %! %------------------------------------------------------------ %! % Shows linear sweep of 100 Hz/sec starting at zero for 5 sec %! % since the sample rate is 1000 Hz, this should be a diagonal %! % from bottom left to top right. %!demo %! t = -2:0.001:15; %! y = chirp (t, 400, 10, 100, "quadratic"); %! [S, f, t] = specgram (y, 256, 1000); %! t = t - 2; %! imagesc(t, f, 20 * log10 (abs (S))); %! set (gca (), "ydir", "normal"); %! xlabel ("Time"); %! ylabel ("Frequency"); %! %------------------------------------------------------------ %! % Shows a quadratic chirp of 400 Hz at t=0 and 100 Hz at t=10 %! % Time goes from -2 to 15 seconds. %!demo %! t = 0:1/8000:5; %! y = chirp (t, 200, 2, 500, "logarithmic"); %! specgram (y, 256, 8000); %! %------------------------------------------------------------- %! % Shows a logarithmic chirp of 200 Hz at t=0 and 500 Hz at t=2 %! % Time goes from 0 to 5 seconds at 8000 Hz. ## Test shape defaults and abbreviations %!shared t %! t = (0:5000) ./ 1000; %!test %! y1 = chirp (t); %! y2 = chirp (t, 0, 1, 100, "linear", 0); %! assert (y2, y1) %!test %! y1 = chirp (t, [], [], [], "li"); %! y2 = chirp (t, 0, 1, 100, "linear", 0); %! assert (y2, y1) %!test %! y1 = chirp (t, [], [], [], "q"); %! y2 = chirp (t, 0, 1, 100, "quadratic", 0); %! assert (y2, y1) %!test %! y1 = chirp (t, [], [], [], "lo"); %! y2 = chirp (t, 1e-6, 1, 100, "logarithmic", 0); %! assert (y2, y1) ## Test input validation %!error chirp () %!error chirp (1, 2, 3, 4, 5, 6, 7) %!error <invalid frequency sweep shape> chirp (0, [], [], [], "l") %!error <invalid frequency sweep shape> chirp (0, [], [], [], "foo") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/clustersegment.m������������������������������������������������������������������0000644�0000000�0000000�00000005133�14673270174�014141� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2021 Juan Pablo Carbajal ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{clusteridx} =} clustersegment (@var{unos}) ## Calculate boundary indexes of clusters of 1's. ## ## The function calculates the initial index and end index of the sequences of ## 1's in the rows of @var{unos}. The clusters are sought in the rows of the ## array @var{unos}. ## ## The result is returned in a cell array of size 1-by-@var{Np}, where @var{Np} ## is the number of rows in @var{unos}. Each element of the cell has two rows. ## The first row is the initial index of a sequence of 1's and the second row ## is the end index of that sequence. ## ## If @var{Np} == 1 the output is a matrix with two rows. ## ## The function works by finding the indexes of jumps between consecutive ## values in the rows of @var{unos}. ## ## @end deftypefn function contRange = clustersegment(xhi) ## Find discontinuities bool_discon = diff (xhi, 1, 2); [Np Na] = size (xhi); contRange = cell (1, Np); for i = 1:Np idxUp = find (bool_discon(i,:) > 0) + 1; idxDwn = find (bool_discon(i,:) < 0); tLen = length (idxUp) + length (idxDwn); if xhi(i,1) == 1 ## first event was down contRange{i}(1) = 1; contRange{i}(2:2:tLen+1) = idxDwn; contRange{i}(3:2:tLen+1) = idxUp; else ## first event was up contRange{i}(1:2:tLen) = idxUp; contRange{i}(2:2:tLen) = idxDwn; endif if xhi(i,end) == 1 ## last event was up contRange{i}(end+1) = Na; endif tLen = length (contRange{i}); if tLen ~= 0 contRange{i} = reshape (contRange{i}, 2, tLen / 2); endif endfor if Np == 1 contRange = cell2mat (contRange); endif endfunction %!demo %! xhi = [0 0 1 1 1 0 0 1 0 0 0 1 1]; %! ranges = clustersegment (xhi) %! %! % The first sequence of 1's in xhi lies in the interval %! ranges(1,1):ranges(2,1) %!demo %! xhi = rand(3,10)>0.4 %! ranges = clustersegment(xhi) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cmorwavf.m������������������������������������������������������������������������0000644�0000000�0000000�00000002270�14673270174�012720� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{psi}, @var{x}] =} cmorwavf (@var{lb}, @var{ub}, @var{n}, @var{fb}, @var{fc}) ## Compute the Complex Morlet wavelet. ## @end deftypefn function [psi,x] = cmorwavf (lb,ub,n,fb,fc) if (nargin ~= 5) print_usage; elseif (n <= 0 || floor(n) ~= n) error("n must be an integer strictly positive"); endif x = linspace(lb,ub,n); psi =((pi*fb)^(-0.5))*exp(2*i*pi*fc.*x).*exp(-x.^2/fb); endfunction ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cohere.m��������������������������������������������������������������������������0000644�0000000�0000000�00000004104�14673270174�012337� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{Pxx}, @var{freq}]} = cohere(@var{x},@var{y},@var{Nfft},@var{Fs},@var{window},@var{overlap},@var{range},@var{plot_type},@var{detrend}) ## Estimate (mean square) coherence of signals "x" and "y". ## ## Use the Welch (1967) periodogram/FFT method. ## ## Compatible with Matlab R11 cohere and earlier. ## ## See "help pwelch" for description of arguments, hints and references ## --- especially hint (7) for Matlab R11 defaults. ## @end deftypefn function varargout = cohere(varargin) ## if ( nargin<2 ) error( 'cohere: Need at least 2 args. Use help cohere.' ); endif nvarargin = length(varargin); ## remove any pwelch RESULT args and add 'trans' for iarg=1:nvarargin arg = varargin{iarg}; if ( ~isempty(arg) && ischar(arg) && ( strcmp(arg,'power') || ... strcmp(arg,'cross') || strcmp(arg,'trans') || ... strcmp(arg,'coher') || strcmp(arg,'ypower') )) varargin{iarg} = []; endif endfor varargin{nvarargin+1} = 'coher'; ## saved_compatib = pwelch('R11-'); if ( nargout==0 ) pwelch(varargin{:}); elseif ( nargout==1 ) Pxx = pwelch(varargin{:}); varargout{1} = Pxx; elseif ( nargout>=2 ) [Pxx,f] = pwelch(varargin{:}); varargout{1} = Pxx; varargout{2} = f; endif pwelch(saved_compatib); saved_compatib = 0; endfunction ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/convmtx.m�������������������������������������������������������������������������0000644�0000000�0000000�00000003456�14673270174�012601� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2003 David Bateman <adb014@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} convmtx (@var{a}, @var{n}) ## If @var{a} is a column vector and @var{x} is a column vector ## of length @var{n}, then ## ## @code{convmtx(@var{a}, @var{n}) * @var{x}} ## ## gives the convolution of of @var{a} and @var{x} and is the ## same as @code{conv(@var{a}, @var{x})}. The difference is if ## many vectors are to be convolved with the same vector, then ## this technique is possibly faster. ## ## Similarly, if @var{a} is a row vector and @var{x} is a row ## vector of length @var{n}, then ## ## @code{@var{x} * convmtx(@var{a}, @var{n})} ## ## is the same as @code{conv(@var{x}, @var{a})}. ## @end deftypefn ## @seealso{conv} function b = convmtx (a, n) if (nargin != 2) print_usage; endif [r, c] = size(a); if ((r != 1) && (c != 1)) || (r*c == 0) error("convmtx: expecting vector argument"); endif b = toeplitz([a(:); zeros(n-1,1)],[a(1); zeros(n-1,1)]); if (c > r) b = b.'; endif endfunction %!assert(convmtx([3,4,5],3),[3,4,5,0,0;0,3,4,5,0;0,0,3,4,5]) %!assert(convmtx([3;4;5],3),[3,0,0;4,3,0;5,4,3;0,5,4;0,0,5]) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cplxreal.m������������������������������������������������������������������������0000644�0000000�0000000�00000007250�14673270174�012711� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2005 Julius O. Smith III ## Copyright (C) 2018-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{zc}, @var{zr}] =} cplxreal (@var{z}) ## @deftypefnx {Function File} {[@var{zc}, @var{zr}] =} cplxreal (@var{z}, @var{tol}) ## @deftypefnx {Function File} {[@var{zc}, @var{zr}] =} cplxreal (@var{z}, @var{tol}, @var{dim}) ## Sort the numbers @var{z} into complex-conjugate-valued and real-valued ## elements. The positive imaginary complex numbers of each complex conjugate ## pair are returned in @var{zc} and the real numbers are returned in @var{zr}. ## ## @var{tol} is a weighting factor in the range [0, 1) which determines the ## tolerance of the matching. The default value is @code{100 * eps} and the ## resulting tolerance for a given complex pair is ## @code{@var{tol} * abs (@var{z}(i)))}. ## ## By default the complex pairs are sorted along the first non-singleton ## dimension of @var{z}. If @var{dim} is specified, then the complex pairs are ## sorted along this dimension. ## ## Signal an error if some complex numbers could not be paired. Signal an ## error if all complex numbers are not exact conjugates (to within @var{tol}). ## Note that there is no defined order for pairs with identical real parts but ## differing imaginary parts. ## @seealso{cplxpair} ## @end deftypefn function [zc, zr] = cplxreal (z, tol, dim) if (nargin < 1 || nargin > 3) print_usage (); endif if (isempty (z)) zc = zeros (size (z)); zr = zeros (size (z)); return; endif cls = ifelse (isa (z, "single"), "single", "double"); if (nargin < 2 || isempty (tol)) tol = 100 * eps (cls); endif args = cell (1, nargin); args{1} = z; args{2} = tol; if (nargin >= 3) args{3} = dim; endif zcp = cplxpair (args{:}); nz = length (z); idx = nz; while ((idx > 0) && (zcp(idx) == 0 || (abs (imag (zcp(idx))) ./ abs (zcp(idx))) <= tol)) zcp(idx) = real (zcp(idx)); idx--; endwhile if (mod (idx, 2) != 0) error ("cplxreal: odd number of complex values was returned from cplxpair"); endif zc = zcp(2:2:idx); zr = zcp(idx+1:nz); endfunction %!test %! [zc, zr] = cplxreal ([]); %! assert (isempty (zc)) %! assert (isempty (zr)) %!test %! [zc, zr] = cplxreal (1); %! assert (isempty (zc)) %! assert (zr, 1) %!test %! [zc, zr] = cplxreal ([1+1i, 1-1i]); %! assert (zc, 1+1i) %! assert (isempty (zr)) %!test %! [zc, zr] = cplxreal (roots ([1, 0, 0, 1])); %! assert (zc, complex (0.5, sin (pi/3)), 10*eps) %! assert (zr, -1, 2*eps) ## Test with 2 real zeros, one of them equal to 0 %!test %! [zc, zr] = cplxreal (roots ([1, 0, 0, 1, 0])); %! assert (zc, complex (0.5, sin (pi/3)), 10*eps) %! assert (zr, [-1; 0], 2*eps) ## Test with 3 real zeros, two of them equal to 0 %!test %! [zc, zr] = cplxreal (roots ([1, 0, 0, 1, 0, 0])); %! assert (zc, complex (0.5, sin (pi/3)), 10*eps) %! assert (zr, [-1; 0; 0], 2*eps) ## Test input validation %!error cplxreal () %!error cplxreal (1, 2, 3, 4) %!error cplxreal (1, ones (2, 3)) %!error cplxreal (1, -1) %!error cplxreal (1, [], 3) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/cpsd.m����������������������������������������������������������������������������0000644�0000000�0000000�00000004502�14673270174�012025� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{Pxx}, @var{freq}] =} cpsd (@var{x}, @var{y}) ## @deftypefnx {Function File} {[@dots{}] =} cpsd (@var{x}, @var{y}, @var{window}) ## @deftypefnx {Function File} {[@dots{}] =} cpsd (@var{x}, @var{y}, @var{window}, @var{overlap}) ## @deftypefnx {Function File} {[@dots{}] =} cpsd (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}) ## @deftypefnx {Function File} {[@dots{}] =} cpsd (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}) ## @deftypefnx {Function File} {[@dots{}] =} cpsd (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}, @var{range}) ## @deftypefnx {Function File} {} cpsd (@dots{}) ## ## Estimate cross power spectrum of data @var{x} and @var{y} by the Welch (1967) ## periodogram/FFT method. ## @seealso{pwelch} ## @end deftypefn function varargout = cpsd(varargin) ## Check fixed argument if (nargin < 2 || nargin > 7) print_usage (); endif nvarargin = length(varargin); ## remove any pwelch RESULT args and add 'cross' for iarg=1:nvarargin arg = varargin{iarg}; if ( ~isempty(arg) && ischar(arg) && ( strcmp(arg,'power') || ... strcmp(arg,'cross') || strcmp(arg,'trans') || ... strcmp(arg,'coher') || strcmp(arg,'ypower') )) varargin{iarg} = []; endif endfor varargin{nvarargin+1} = 'cross'; ## if ( nargout==0 ) pwelch(varargin{:}); elseif ( nargout==1 ) Pxx = pwelch(varargin{:}); varargout{1} = Pxx; elseif ( nargout>=2 ) [Pxx,f] = pwelch(varargin{:}); varargout{1} = Pxx; varargout{2} = f; endif endfunction ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/csd.m�����������������������������������������������������������������������������0000644�0000000�0000000�00000004062�14673270174�011646� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{Pxx},@var{freq}]} = csd(@var{x}, @var{y}, @var{Nfft}, @var{Fs}, @var{window}, @var{overlap}, @var{range}, @var{plot_type}, @var{detrend}) ## Estimate cross power spectrum of data "x" and "y" by the Welch (1967) ## periodogram/FFT method. ## ## Compatible with Matlab R11 csd and earlier. ## ## See "help pwelch" for description of arguments, hints and references ## --- especially hint (7) for Matlab R11 defaults. ## @end deftypefn function varargout = csd(varargin) ## Check fixed argument if ( nargin<2 ) error( 'csd: Need at least 2 args. Use help csd.' ); endif nvarargin = length(varargin); ## remove any pwelch RESULT args and add 'cross' for iarg=1:nvarargin arg = varargin{iarg}; if ( ~isempty(arg) && ischar(arg) && ( strcmp(arg,'power') || ... strcmp(arg,'cross') || strcmp(arg,'trans') || ... strcmp(arg,'coher') || strcmp(arg,'ypower') )) varargin{iarg} = []; endif endfor varargin{nvarargin+1} = 'cross'; ## saved_compatib = pwelch('R11-'); if ( nargout==0 ) pwelch(varargin{:}); elseif ( nargout==1 ) Pxx = pwelch(varargin{:}); varargout{1} = Pxx; elseif ( nargout>=2 ) [Pxx,f] = pwelch(varargin{:}); varargout{1} = Pxx; varargout{2} = f; endif pwelch(saved_compatib); endfunction ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/czt.m�����������������������������������������������������������������������������0000644�0000000�0000000�00000006600�14673270174�011675� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2004 Daniel Gunyan ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} czt (@var{x}) ## @deftypefnx {Function File} {} czt (@var{x}, @var{m}) ## @deftypefnx {Function File} {} czt (@var{x}, @var{m}, @var{w}) ## @deftypefnx {Function File} {} czt (@var{x}, @var{m}, @var{w}, @var{a}) ## Chirp z-transform. Compute the frequency response starting at a and ## stepping by w for m steps. a is a point in the complex plane, and ## w is the ratio between points in each step (i.e., radius increases ## exponentially, and angle increases linearly). ## ## To evaluate the frequency response for the range f1 to f2 in a signal ## with sampling frequency Fs, use the following: ## ## @example ## @group ## m = 32; ## number of points desired ## w = exp(-j*2*pi*(f2-f1)/((m-1)*Fs)); ## freq. step of f2-f1/m ## a = exp(j*2*pi*f1/Fs); ## starting at frequency f1 ## y = czt(x, m, w, a); ## @end group ## @end example ## ## If you don't specify them, then the parameters default to a Fourier ## transform: ## m=length(x), w=exp(-j*2*pi/m), a=1 ## ## If x is a matrix, the transform will be performed column-by-column. ## @end deftypefn ## Algorithm (based on Oppenheim and Schafer, "Discrete-Time Signal ## Processing", pp. 623-628): ## make chirp of length -N+1 to max(N-1,M-1) ## chirp => w^([-N+1:max(N-1,M-1)]^2/2) ## multiply x by chirped a and by N-elements of chirp, and call it g ## convolve g with inverse chirp, and call it gg ## pad ffts so that multiplication works ## ifft(fft(g)*fft(1/chirp)) ## multiply gg by M-elements of chirp and call it done function y = czt(x, m, w, a) if nargin < 1 || nargin > 4, print_usage; endif [row, col] = size(x); if row == 1, x = x(:); col = 1; endif if nargin < 2 || isempty(m), m = length(x(:,1)); endif if length(m) > 1, error("czt: m must be a single element\n"); endif if nargin < 3 || isempty(w), w = exp(-2*j*pi/m); endif if nargin < 4 || isempty(a), a = 1; endif if length(w) > 1, error("czt: w must be a single element\n"); endif if length(a) > 1, error("czt: a must be a single element\n"); endif ## indexing to make the statements a little more compact n = length(x(:,1)); N = [0:n-1]'+n; NM = [-(n-1):(m-1)]'+n; M = [0:m-1]'+n; nfft = 2^nextpow2(n+m-1); # fft pad W2 = w.^(([-(n-1):max(m-1,n-1)]'.^2)/2); # chirp for idx = 1:col fg = fft(x(:,idx).*(a.^-(N-n)).*W2(N), nfft); fw = fft(1./W2(NM), nfft); gg = ifft(fg.*fw, nfft); y(:,idx) = gg(M).*W2(M); endfor if row == 1, y = y.'; endif endfunction %!shared x %! x = [1,2,4,1,2,3,5,2,3,5,6,7,8,4,3,6,3,2,5,1]; %!assert(fft(x),czt(x),10000*eps); %!assert(fft(x'),czt(x'),10000*eps); %!assert(fft([x',x']),czt([x',x']),10000*eps); ��������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/data2fun.m������������������������������������������������������������������������0000644�0000000�0000000�00000013027�14673270174�012602� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2020 Juan Pablo Carbajal ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{fhandle}, @var{fullname}] =} data2fun (@var{ti}, @var{yi}) ## @deftypefnx {Function File} {[@dots{}] =} data2fun (@dots{}, @var{property}, @var{value}) ## Create a vectorized function based on data samples using interpolation. ## ## The values given in @var{yi} (N-by-k matrix) correspond to evaluations of the ## function y(t) at the points @var{ti} (N-by-1 matrix). ## The data is interpolated and the function handle to the generated interpolant ## is returned. ## ## The function accepts @var{property}-@var{value} pairs described below. ## ## @table @samp ## @item file ## Code is generated and .m file is created. The @var{value} contains the name ## of the function. The returned function handle is a handle to that file. If ## @var{value} is empty, then a name is automatically generated using ## @code{tempname} and the file is created in the current directory. @var{value} ## must not have an extension, since .m will be appended. ## Numerical values used in the function are stored in a .mat file with the same ## name as the function. ## ## @item interp ## Type of interpolation. See @code{interp1}. ## @end table ## ## @seealso{interp1} ## @end deftypefn function [fhandle, fullfname] = data2fun (t, y, varargin) if (nargin < 2 || mod (nargin, 2) != 0) print_usage (); endif ## Check input arguments interp_args = {"spline"}; given = struct ("file", false); if (! isempty (varargin)) ## Arguments interp_args = varargin; opt_args = fieldnames (given); [tf, idx] = ismember (opt_args, varargin); for i=1:numel (opt_args) given.(opt_args{i}) = tf(i); endfor if (given.file) ## FIXME: check that file will be in the path. Otherwise fhandle(0) fails. if (! isempty (varargin{idx(1)+1})) [dir, fname] = fileparts (varargin{idx(1)+1}); else [dir, fname] = fileparts (tempname (pwd (), "agen_")); endif interp_args(idx(1) + [0, 1]) = []; endif if (isempty (interp_args)) interp_args = {"spline"}; endif endif pp = interp1 (t, y, interp_args{end}, "pp"); if (given.file) fullfname = fullfile (dir, [fname, ".m"]); save ("-binary", [fullfname(1:end-2), ".mat"], "pp"); bodystr = [" persistent pp\n" ... " if (isempty (pp))\n" ... " pp = load ([mfilename(), \".mat\"]).pp;\n" ... " endif\n\n" ... " z = ppval (pp, x);"]; strfunc = generate_function_str (fname, {"z"}, {"x"}, bodystr); fid = fopen (fullfile (dir, [fname, ".m"]), "w"); fprintf (fid, "%s", strfunc); fclose (fid); fhandle = eval (["@", fname]); else fullfname = ""; fhandle = @(t_) ppval (pp, t_); endif endfunction function str = generate_function_str (name, oargs, iargs, bodystr) striargs = cell2mat (cellfun (@(x) [x ", "], iargs, "UniformOutput", false)); striargs = striargs(1:end-2); stroargs = cell2mat (cellfun (@(x) [x ", "], oargs, "UniformOutput", false)); stroargs = stroargs(1:end-2); if (! isempty (stroargs)) str = ["function [" stroargs "] = " name " (" striargs ")\n\n" ... bodystr "\n\nendfunction"]; else str = ["function " name " (" striargs ")\n\n" ... bodystr "\n\nendfunction"]; endif endfunction %!shared t, y %! t = linspace (0, 1, 10); %! y = t.^2 - 2*t + 1; %!test %! fhandle = data2fun (t, y); %! assert (y, fhandle (t)); %!test %! unwind_protect %! # Change to temporary folder in case tester cannot write current folder %! olddir = pwd(); %! cd(tempdir()); %! %! [fhandle fname] = data2fun (t, y, "file", "testdata2fun"); %! yt = testdata2fun (t); %! assert (y, yt); %! assert (y, fhandle (t)); %! unwind_protect_cleanup %! unlink (fname); %! unlink ([fname(1:end-2) ".mat"]); %! cd(olddir) %! end_unwind_protect %!test %! unwind_protect %! # Change to temporary folder in case tester cannot write current folder %! olddir = pwd(); %! cd(tempdir()); %! %! [fhandle fname] = data2fun (t, y, "file", ""); %! # generate commmand to execute using random file name %! cmd = sprintf ("yt = %s(t);", nthargout (2, @fileparts, fname)); %! eval (cmd); %! assert (y, yt); %! assert (y, fhandle (t)); %! unwind_protect_cleanup %! unlink (fname); %! unlink ([fname(1:end-2) ".mat"]); %! cd(olddir) %! end_unwind_protect %!test %! unwind_protect %! # Change to temporary folder in case tester cannot write current folder %! olddir = pwd(); %! cd(tempdir()); %! [fhandle fname] = data2fun (t, y, "file", "testdata2fun", "interp", "linear"); %! yt = testdata2fun (t); %! assert (y, yt); %! assert (y, fhandle (t)); %! unwind_protect_cleanup %! unlink (fname); %! unlink ([fname(1:end-2) ".mat"]); %! cd(olddir) %! end_unwind_protect ## Test input validation %!error data2fun () %!error data2fun (1) %!error data2fun (1, 2, "file") ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/db2pow.m��������������������������������������������������������������������������0000644�0000000�0000000�00000003136�14673270174�012273� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2018 P Sudeepam ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} db2pow (@var{x}) ## Convert decibels (dB) to power. ## ## The power of @var{x} is defined as ## @tex ## $p = 10^{x/10}$. ## @end tex ## @ifnottex ## @var{p} = @code{10 ^ (x/10)}. ## @end ifnottex ## ## If @var{x} is a vector, matrix, or N-dimensional array, the power is ## computed over the elements of @var{x}. ## ## Example: ## ## @example ## @group ## db2pow ([-10, 0, 10]) ## @result{} 0.1000 1.0000 10.0000 ## @end group ## @end example ## @seealso{pow2db} ## @end deftypefn function y = db2pow (x) if (nargin != 1) print_usage (); endif y = 10 .^ (x ./ 10); endfunction %!shared db %! db = [-10, 0, 10, 20, 25]; %!assert (db2pow (db), [0.10000, 1.00000, 10.00000, 100.00000, 316.22777], 0.00001) %!assert (db2pow (db'), [0.10000; 1.00000; 10.00000; 100.00000; 316.22777], 0.00001) ## Test input validation %!error db2pow () %!error db2pow (1, 2) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/dct.m�����������������������������������������������������������������������������0000644�0000000�0000000�00000005643�14673270174�011655� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} dct (@var{x}) ## @deftypefnx {Function File} {} dct (@var{x}, @var{n}) ## Compute the discrete cosine transform of @var{x}. If @var{n} is given, ## then @var{x} is padded or trimmed to length @var{n} before computing the ## transform. If @var{x} is a matrix, compute the transform along the columns ## of the the matrix. The transform is faster if @var{x} is real-valued and ## has even length. ## ## The discrete cosine transform @var{x} can be defined as follows: ## ## @example ## @group ## N-1 ## X[k] = w(k) sum x[n] cos (pi (2n+1) k / 2N ), k = 0, ..., N-1 ## n=0 ## @end group ## @end example ## ## with w(0) = sqrt(1/N) and w(k) = sqrt(2/N), k = 1, ..., N-1. There ## are other definitions with different scaling of X[k], but this form ## is common in image processing. ## ## @seealso{idct, dct2, idct2, dctmtx} ## @end deftypefn ## From Discrete Cosine Transform notes by Brian Evans at UT Austin, ## http://www.ece.utexas.edu/~bevans/courses/ee381k/lectures/09_DCT/lecture9/ ## the discrete cosine transform of x at k is as follows: ## ## N-1 ## X[k] = sum 2 x[n] cos (pi (2n+1) k / 2N ) ## n=0 ## ## which can be computed using: ## ## y = [ x ; flipud (x) ] ## Y = fft(y) ## X = exp( -j pi [0:N-1] / 2N ) .* Y ## ## or for real, even length x ## ## y = [ even(x) ; flipud(odd(x)) ] ## Y = fft(y) ## X = 2 real { exp( -j pi [0:N-1] / 2N ) .* Y } ## ## Scaling the result by w(k)/2 will give us the desired output. function y = dct (x, n) if (nargin < 1 || nargin > 2) print_usage; endif realx = isreal(x); transpose = (rows (x) == 1); if transpose, x = x (:); endif [nr, nc] = size (x); if nargin == 1 n = nr; elseif n > nr x = [ x ; zeros(n-nr,nc) ]; elseif n < nr x (nr-n+1 : n, :) = []; endif if n == 1 w = 1/2; else w = [ sqrt(1/4/n); sqrt(1/2/n)*exp((-1i*pi/2/n)*[1:n-1]') ] * ones (1, nc); endif if ( realx && rem (n, 2) == 0 ) y = fft ([ x(1:2:n,:) ; x(n:-2:1,:) ]); y = 2 * real( w .* y ); else y = fft ([ x ; flipud(x) ]); y = w .* y (1:n, :); if (realx) y = real (y); endif endif if transpose, y = y.'; endif endfunction ���������������������������������������������������������������������������������������������signal-1.4.6/inst/dct2.m����������������������������������������������������������������������������0000644�0000000�0000000�00000002672�14673270174�011736� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} dct2 (@var{x}) ## @deftypefnx {Function File} {} dct2 (@var{x}, @var{m}, @var{n}) ## @deftypefnx {Function File} {} dct2 (@var{x}, [@var{m}, @var{n}]) ## Compute the 2-D discrete cosine transform of matrix @var{x}. If ## @var{m} and @var{n} are specified, the input is padded or trimmed ## to the desired size. ## @seealso{dct, idct, idct2} ## @end deftypefn function y = dct2 (x, m, n) if (nargin < 1 || nargin > 3) print_usage; endif if nargin == 1 [m, n] = size(x); elseif (nargin == 2) n = m(2); m = m(1); endif if m == 1 y = dct (x.', n).'; elseif n == 1 y = dct (x, m); else y = dct (dct (x, m).', n).'; endif endfunction ����������������������������������������������������������������������signal-1.4.6/inst/dctmtx.m��������������������������������������������������������������������������0000644�0000000�0000000�00000003370�14673270174�012401� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} dctmtx (@var{n}) ## Return the DCT transformation matrix of size @var{n}-by-@var{n}. ## ## If A is an @var{n}-by-@var{n} matrix, then the following are true: ## ## @example ## @group ## T*A == dct(A), T'*A == idct(A) ## T*A*T' == dct2(A), T'*A*T == idct2(A) ## @end group ## @end example ## ## A DCT transformation matrix is useful for doing things like jpeg ## image compression, in which an 8x8 DCT matrix is applied to ## non-overlapping blocks throughout an image and only a subblock on the ## top left of each block is kept. During restoration, the remainder of ## the block is filled with zeros and the inverse transform is applied ## to the block. ## ## @seealso{dct, idct, dct2, idct2} ## @end deftypefn function T = dctmtx(n) if nargin != 1 print_usage; endif if n > 1 T = [ sqrt(1/n)*ones(1,n) ; ... sqrt(2/n)*cos((pi/2/n)*([1:n-1]'*[1:2:2*n])) ]; elseif n == 1 T = 1; else error ("dctmtx: n must be at least 1"); endif endfunction ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/decimate.m������������������������������������������������������������������������0000644�0000000�0000000�00000010024�14673270174�012643� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} decimate (@var{x}, @var{q}) ## @deftypefnx {Function File} {@var{y} =} decimate (@var{x}, @var{q}, @var{n}) ## @deftypefnx {Function File} {@var{y} =} decimate (@dots{}, "fir") ## ## Downsample the signal @var{x} by a reduction factor of @var{q}. A lowpass ## antialiasing filter is applied to the signal prior to reducing the input ## sequence. By default, an order @var{n} Chebyshev type I filter is used. ## If @var{n} is not specified, the default is 8. ## ## If the optional argument @code{"fir"} is given, an order @var{n} FIR filter ## is used, with a default order of 30 if @var{n} is not given. ## ## Note that @var{q} must be an integer for this rate change method. ## ## Example: ## @example ## ## Generate a signal that starts away from zero, is slowly varying ## ## at the start and quickly varying at the end, decimate and plot. ## ## Since it starts away from zero, you will see the boundary ## ## effects of the antialiasing filter clearly. Next you will see ## ## how it follows the curve nicely in the slowly varying early ## ## part of the signal, but averages the curve in the quickly ## ## varying late part of the signal. ## t = 0:0.01:2; ## x = chirp (t, 2, .5, 10, "quadratic") + sin (2*pi*t*0.4); ## y = decimate (x, 4); ## stem (t(1:121) * 1000, x(1:121), "-g;Original;"); hold on; # original ## stem (t(1:4:121) * 1000, y(1:31), "-r;Decimated;"); hold off; # decimated ## @end example ## @end deftypefn function y = decimate(x, q, n, ftype) if (nargin < 2 || nargin > 4) print_usage (); elseif (! (isscalar (q) && (q == fix (q)) && (q > 0))) error ("decimate: Q must be a positive integer"); endif if (nargin < 3) ftype = "iir"; n = []; elseif (nargin < 4) if (ischar (n)) ftype = n; n = []; else ftype = "iir"; endif endif if (! any (strcmp (ftype, {"fir", "iir"}))) error ('decimate: filter type must be either "fir" or "iir"'); endif fir = strcmp (ftype, "fir"); if (isempty (n)) if (fir) n = 30; else n = 8; endif endif if (! (isscalar (n) && (n == fix (n)) && (n > 0))) error ("decimate: N must be a positive integer"); endif if (fir) b = fir1 (n, 1/q); y = filtfilt (b, 1, x); else [b, a] = cheby1 (n, 0.05, 0.8/q); y = filtfilt (b, a, x); endif y = y(1:q:length(x)); endfunction %!demo %! t=0:0.01:2; x=chirp(t,2,.5,10,'quadratic')+sin(2*pi*t*0.4); %! y = decimate(x,4); # factor of 4 decimation %! stem(t(1:121)*1000,x(1:121),"-g;Original;"); hold on; # plot original %! stem(t(1:4:121)*1000,y(1:31),"-r;Decimated;"); hold off; # decimated %! %------------------------------------------------------------------ %! % The signal to decimate starts away from zero, is slowly varying %! % at the start and quickly varying at the end, decimate and plot. %! % Since it starts away from zero, you will see the boundary %! % effects of the antialiasing filter clearly. You will also see %! % how it follows the curve nicely in the slowly varying early %! % part of the signal, but averages the curve in the quickly %! % varying late part of the signal. %% Test input validation %!error decimate () %!error decimate (1) %!error decimate (1, 2, 3, 4, 5) %!error decimate (1, -1) %!test %! s = decimate(1:100, 2, 'fir'); %! assert(s, 1:2:100, 1e3*eps); ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/dftmtx.m��������������������������������������������������������������������������0000644�0000000�0000000�00000002625�14673270174�012406� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2003 David Bateman <adb014@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{d} =} dftmtx (@var{n}) ## Compute the @var{n}-by-@var{n} Fourier transformation matrix. This is ## the matrix @var{d} such that the Fourier transform of a column vector of ## length @var{n} is given by @code{dftmtx(@var{n}) * @var{x}} and the ## inverse Fourier transform is given by @code{inv(dftmtx(@var{n})) * @var{x}}. ## ## In general this is less efficient than calling the @code{fft} and ## @code{ifft} functions directly. ## @seealso{fft, ifft} ## @end deftypefn function d = dftmtx(n) if (nargin != 1) print_usage; elseif (!isscalar(n)) error ("dftmtx: argument must be scalar"); endif d = fft(eye(n)); endfunction �����������������������������������������������������������������������������������������������������������signal-1.4.6/inst/digitrevorder.m�������������������������������������������������������������������0000644�0000000�0000000�00000005057�14673270174�013753� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} digitrevorder (@var{x}, @var{r}) ## @deftypefnx {Function File} {[@var{y}, @var{i}] =} digitrevorder (@var{x}, @var{r}) ## Reorder the elements of the vector @var{x} in digit-reversed order. ## The elements of @var{x} are converted to radix @var{r} and reversed. ## The reordered indices of the elements of @var{x} are returned in @var{i}. ## @seealso{bitrevorder, fft, ifft} ## @end deftypefn function [y, i] = digitrevorder (x, r) if (nargin < 1 || nargin > 2) print_usage (); elseif (! isvector (x)) error ("digitrevorder: X must be a vector"); elseif (!(isscalar (r) && r == fix (r) && r >= 2 && r <= 36)) error ("digitrevorder: R must be an integer between 2 and 36"); else tmp = log (numel (x)) / log (r); if (fix (tmp) != tmp) error ("digitrevorder: X must have length equal to an integer power of %d", r); endif endif old_ind = 0:numel (x) - 1; new_ind = base2dec (fliplr (dec2base (old_ind, r)), r); i = new_ind + 1; y(old_ind + 1) = x(i); if (iscolumn (x)) y = y(:); else i = i.'; endif endfunction %!assert (digitrevorder (0, 2), 0); %!assert (digitrevorder (0, 36), 0); %!assert (digitrevorder (0:3, 4), 0:3); %!assert (digitrevorder ([0:3]', 4), [0:3]'); %!assert (digitrevorder (0:7, 2), [0 4 2 6 1 5 3 7]); %!assert (digitrevorder ([0:7]', 2), [0 4 2 6 1 5 3 7]'); %!assert (digitrevorder ([0:7]*i, 2), [0 4 2 6 1 5 3 7]*i); %!assert (digitrevorder ([0:7]'*i, 2), [0 4 2 6 1 5 3 7]'*i); %!assert (digitrevorder (0:15, 2), [0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15]); %!assert (digitrevorder (0:15, 4), [0 4 8 12 1 5 9 13 2 6 10 14 3 7 11 15]); %% Test input validation %!error digitrevorder (); %!error digitrevorder (1); %!error digitrevorder (1, 2, 3); %!error digitrevorder ([], 1); %!error digitrevorder ([], 37); %!error digitrevorder (0:3, 8); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/diric.m���������������������������������������������������������������������������0000644�0000000�0000000�00000002250�14673270174�012164� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} diric (@var{x},@var{n}) ## Compute the dirichlet function. ## @seealso{sinc, gauspuls, sawtooth} ## @end deftypefn function y = diric(x,n) if (nargin < 2) print_usage; elseif (n <= 0 || floor(n) ~= n) error("n must be an integer strictly positive"); endif y = sin(n.*x./2)./(n.*sin(x./2)); y(mod(x,2*pi)==0) = (-1).^((n-1).*x(mod(x,2*pi)==0)./(2.*pi)); endfunction ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/downsample.m����������������������������������������������������������������������0000644�0000000�0000000�00000002504�14673270174�013245� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Author: Paul Kienzle <pkienzle@users.sf.net> (2007) ## This program is granted to the public domain. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} downsample (@var{x}, @var{n}) ## @deftypefnx {Function File} {@var{y} =} downsample (@var{x}, @var{n}, @var{offset}) ## Downsample the signal, selecting every @var{n}th element. If @var{x} ## is a matrix, downsample every column. ## ## For most signals you will want to use @code{decimate} instead since ## it prefilters the high frequency components of the signal and ## avoids aliasing effects. ## ## If @var{offset} is defined, select every @var{n}th element starting at ## sample @var{offset}. ## @seealso{decimate, interp, resample, upfirdn, upsample} ## @end deftypefn function y = downsample (x, n, phase = 0) if nargin<2 || nargin>3, print_usage; endif if phase > n - 1 warning("This is incompatible with Matlab (phase = 0:n-1). See octave-forge signal package release notes for details.") endif if isvector(x) y = x(phase + 1:n:end); else y = x(phase + 1:n:end,:); endif endfunction %!assert(downsample([1,2,3,4,5],2),[1,3,5]); %!assert(downsample([1;2;3;4;5],2),[1;3;5]); %!assert(downsample([1,2;3,4;5,6;7,8;9,10],2),[1,2;5,6;9,10]); %!assert(downsample([1,2,3,4,5],2,1),[2,4]); %!assert(downsample([1,2;3,4;5,6;7,8;9,10],2,1),[3,4;7,8]); ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/dst.m�����������������������������������������������������������������������������0000644�0000000�0000000�00000002664�14673270174�011675� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Author: Paul Kienzle <pkienzle@users.sf.net> (2006) ## This program is granted to the public domain. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} dst (@var{x}) ## @deftypefnx {Function File} {@var{y} =} dst (@var{x}, @var{n}) ## Computes the type I discrete sine transform of @var{x}. If @var{n} is given, ## then @var{x} is padded or trimmed to length @var{n} before computing the transform. ## If @var{x} is a matrix, compute the transform along the columns of the ## the matrix. ## ## The discrete sine transform X of x can be defined as follows: ## ## @verbatim ## N ## X[k] = sum x[n] sin (pi n k / (N+1) ), k = 1, ..., N ## n=1 ## @end verbatim ## ## @seealso{idst} ## @end deftypefn function y = dst (x, n) if (nargin < 1 || nargin > 2) print_usage; endif transpose = (rows (x) == 1); if transpose, x = x (:); endif [nr, nc] = size (x); if nargin == 1 n = nr; elseif n > nr x = [ x ; zeros(n-nr,nc) ]; elseif n < nr x (nr-n+1 : n, :) = []; endif y = fft ([ zeros(1,nc); x ; zeros(1,nc); -flipud(x) ])/-2j; y = y(2:nr+1,:); if isreal(x), y = real (y); endif ## Compare directly against the slow transform ## y2 = x; ## w = pi*[1:n]'/(n+1); ## for k = 1:n, y2(k) = sum(x(:).*sin(k*w)); endfor ## y = [y,y2]; if transpose, y = y.'; endif endfunction %!test %! x = log(linspace(0.1,1,32)); %! y = dst(x); %! assert(y(3), sum(x.*sin(3*pi*[1:32]/33)), 100*eps) ����������������������������������������������������������������������������signal-1.4.6/inst/dwt.m�����������������������������������������������������������������������������0000644�0000000�0000000�00000003577�14673270174�011705� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013 Lukas F. Reichlin ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{u}, @var{v}] =} dwt (@var{x}, @var{wname}) ## @deftypefnx {Function File} {[@var{u}, @var{v}] =} dwt (@var{x}, @var{Hp}, @var{Gp}) ## @deftypefnx {Function File} {[@var{u}, @var{v}] =} dwt (@var{x}, @var{Hp}, @var{Gp}, @dots{}) ## Discrete wavelet transform (1D). ## ## @strong{Inputs} ## @table @var ## @item x ## Signal vector. ## @item wname ## Wavelet name. ## @item Hp ## Coefficients of low-pass decomposition @acronym{FIR} filter. ## @item Gp ## Coefficients of high-pass decomposition @acronym{FIR} filter. ## @end table ## ## @strong{Outputs} ## @table @var ## @item u ## Signal vector of average, approximation. ## @item v ## Signal vector of difference, detail. ## @end table ## @end deftypefn ## Author: Lukas Reichlin <lukas.reichlin@gmail.com> ## Created: April 2013 ## Version: 0.1 function [u, v] = dwt (x, varargin) if (nargin == 2) wname = varargin{1}; [Hp, Gp] = wfilters (wname, "d"); elseif (nargin == 3) Hp = varargin{1}; Gp = varargin{2}; else print_usage (); endif tmp = wconv (1, x, Hp, "valid"); u = tmp(1:2:end); tmp = wconv (1, x, Gp, "valid"); v = tmp(1:2:end); endfunction ���������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/ellip.m���������������������������������������������������������������������������0000644�0000000�0000000�00000013356�14673270174�012210� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paulo Neis <p_neis@yahoo.com.br> ## Copyright (C) 2003 Doug Stewart <dastew@sympatico.ca> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{b}, @var{a}] =} ellip (@var{n}, @var{rp}, @var{rs}, @var{wp}) ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} ellip (@var{n}, @var{rp}, @var{rs}, @var{wp}, "high") ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} ellip (@var{n}, @var{rp}, @var{rs}, [@var{wl}, @var{wh}]) ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} ellip (@var{n}, @var{rp}, @var{rs}, [@var{wl}, @var{wh}], "stop") ## @deftypefnx {Function File} {[@var{z}, @var{p}, @var{g}] =} ellip (@dots{}) ## @deftypefnx {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} ellip (@dots{}) ## @deftypefnx {Function File} {[@dots{}] =} ellip (@dots{}, "s") ## ## Generate an elliptic or Cauer filter with @var{rp} dB of passband ripple and ## @var{rs} dB of stopband attenuation. ## ## [b,a] = ellip(n, Rp, Rs, Wp) ## low pass filter with order n, cutoff pi*Wp radians, Rp decibels ## of ripple in the passband and a stopband Rs decibels down. ## ## [b,a] = ellip(n, Rp, Rs, Wp, 'high') ## high pass filter with cutoff pi*Wp... ## ## [b,a] = ellip(n, Rp, Rs, [Wl, Wh]) ## band pass filter with band pass edges pi*Wl and pi*Wh ... ## ## [b,a] = ellip(n, Rp, Rs, [Wl, Wh], 'stop') ## band reject filter with edges pi*Wl and pi*Wh, ... ## ## [z,p,g] = ellip(...) ## return filter as zero-pole-gain. ## ## [...] = ellip(...,'s') ## return a Laplace space filter, W can be larger than 1. ## ## [a,b,c,d] = ellip(...) ## return state-space matrices ## ## References: ## ## - Oppenheim, Alan V., Discrete Time Signal Processing, Hardcover, 1999. ## - Parente Ribeiro, E., Notas de aula da disciplina TE498 - Processamento ## Digital de Sinais, UFPR, 2001/2002. ## @end deftypefn function [a, b, c, d] = ellip (n, rp, rs, w, varargin) if (nargin > 6 || nargin < 4 || nargout > 4) print_usage (); endif ## interpret the input parameters if (! (isscalar (n) && (n == fix (n)) && (n > 0))) error ("ellip: filter order N must be a positive integer"); endif stop = false; digital = true; for i = 1:numel (varargin) switch (varargin{i}) case "s" digital = false; case "z" digital = true; case {"high", "stop"} stop = true; case {"low", "pass"} stop = false; otherwise error ("ellip: expected [high|stop] or [s|z]"); endswitch endfor if (! ((numel (w) <= 2) && (rows (w) == 1 || columns (w) == 1))) error ("ellip: frequency must be given as WC or [WL, WH]"); elseif ((numel (w) == 2) && (w(2) <= w(1))) error ("ellip: W(1) must be less than W(2)"); endif if (digital && ! all ((w >= 0) & (w <= 1))) error ("ellip: all elements of W must be in the range [0,1]"); elseif (! digital && ! all (w >= 0)) error ("ellip: all elements of W must be in the range [0,inf]"); endif if (! (isscalar (rp) && isnumeric (rp) && (rp >= 0))) error ("ellip: passband ripple RP must be a non-negative scalar"); endif if (! (isscalar (rs) && isnumeric (rs) && (rs >= 0))) error ("ellip: stopband attenuation RS must be a non-negative scalar"); endif ## Prewarp the digital frequencies if (digital) T = 2; # sampling frequency of 2 Hz w = 2 / T * tan (pi * w / T); endif ## Generate s-plane poles, zeros and gain [zero, pole, gain] = ncauer (rp, rs, n); ## splane frequency transform [zero, pole, gain] = sftrans (zero, pole, gain, w, stop); ## Use bilinear transform to convert poles to the z plane if (digital) [zero, pole, gain] = bilinear (zero, pole, gain, T); endif ## convert to the correct output form ## note that poly always outputs a row vector if (nargout <= 2) a = real (gain * poly (zero)); b = real (poly (pole)); elseif (nargout == 3) a = zero(:); b = pole(:); c = gain; else ## output ss results [a, b, c, d] = zp2ss (zero, pole, gain); endif endfunction %!demo %! [n, Ws] = ellipord ([.1 .2], [.01 .4], 1, 90); %! [b, a] = ellip (5, 1, 90, [.1 .2]); %! [h, w] = freqz (b, a); %! %! plot (w./pi, 20*log10 (abs (h)), ";;") %! xlabel ("Frequency"); %! ylabel ("abs(H[w])[dB]"); %! axis ([0, 1, -100, 0]); %! %! hold ("on"); %! x=ones (1, length (h)); %! plot (w./pi, x.*-1, ";-1 dB;") %! plot (w./pi, x.*-90, ";-90 dB;") %! hold ("off"); %% Test input validation %!error [a, b] = ellip () %!error [a, b] = ellip (1) %!error [a, b] = ellip (1, 2) %!error [a, b] = ellip (1, 2, 3) %!error [a, b] = ellip (1, 2, 3, 4, 5, 6, 7) %!error [a, b] = ellip (.5, 2, 40, .2) %!error [a, b] = ellip (3, 2, 40, .2, "invalid") %% Test output orientation %!test %! ellip (6, 3, 50, .6); %! assert (isrow (ans)); %!test %! A = ellip (6, 3, 50, .6); %! assert (isrow (A)); %!test %! [A, B] = ellip (6, 3, 50, .6); %! assert (isrow (A)); %! assert (isrow (B)); %!test %! [z, p, g] = ellip (6, 3, 50, .6); %! assert (iscolumn (z)); %! assert (iscolumn (p)); %! assert (isscalar (g)); %!test %! [a, b, c, d] = ellip (6, 3, 50, .6); %! assert (ismatrix (a)); %! assert (iscolumn (b)); %! assert (isrow (c)); %! assert (isscalar (d)); ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/ellipap.m�������������������������������������������������������������������������0000644�0000000�0000000�00000003141�14673270174�012520� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013 CarnĂ« Draug <carandraug+dev@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{z}, @var{p}, @var{g}] =} ellipap (@var{n}, @var{Rp}, @var{Rs}) ## Design lowpass analog elliptic filter. ## ## This function exists for @sc{matlab} compatibility only, and is equivalent ## to @code{ellip (@var{n}, @var{Rp}, @var{Rs}, 1, "s")}. ## ## @seealso{ellip} ## @end deftypefn function [z, p, g] = ellipap (n, Rp, Rs) if (nargin != 3) print_usage(); elseif (! isscalar (n) || ! isnumeric (n) || fix (n) != n || n <= 0) error ("ellipap: N must be a positive integer"); elseif (! isscalar (Rp) || ! isnumeric (Rp) || Rp <= 0) error ("ellipap: RP must be a positive scalar"); elseif (! isscalar (Rs) || ! isnumeric (Rs) || Rs < 0) error ("ellipap: RS must be a positive scalar"); elseif (Rp > Rs) error ("ellipap: RS must be larger than RP"); endif [z, p, g] = ellip (n, Rp, Rs, 1, "s"); endfunction �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/ellipord.m������������������������������������������������������������������������0000644�0000000�0000000�00000102733�14673270174�012713� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paulo Neis ## Copyright (C) 2018 Charles Praplan ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{n} =} ellipord (@var{wp}, @var{ws}, @var{rp}, @var{rs}) ## @deftypefnx {Function File} {@var{n} =} ellipord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}) ## @deftypefnx {Function File} {@var{n} =} ellipord ([@var{wp1}, @var{wp2}], [@var{ws1}, @var{ws2}], @var{rp}, @var{rs}, "s") ## @deftypefnx {Function File} {[@var{n}, @var{wc}] =} ellipord (@dots{}) ## Compute the minimum filter order of an elliptic filter with the desired ## response characteristics. The filter frequency band edges are specified ## by the passband frequency @var{wp} and stopband frequency @var{ws}. ## Frequencies are normalized to the Nyquist frequency in the range [0,1]. ## @var{rp} is the allowable passband ripple measured in decibels, and @var{rs} ## is the minimum attenuation in the stop band, also in decibels. The output ## arguments @var{n} and @var{wc} can be given as inputs to @code{ellip}. ## ## If @var{wp} and @var{ws} are scalars, then @var{wp} is the passband cutoff ## frequency and @var{ws} is the stopband edge frequency. If @var{ws} is ## greater than @var{wp}, the filter is a low-pass filter. If @var{wp} is ## greater than @var{ws}, the filter is a high-pass filter. ## ## If @var{wp} and @var{ws} are vectors of length 2, then @var{wp} defines the ## passband interval and @var{ws} defines the stopband interval. If @var{wp} ## is contained within @var{ws} (@var{ws1} < @var{wp1} < @var{wp2} < @var{ws2}), ## the filter is a band-pass filter. If @var{ws} is contained within @var{wp} ## (@var{wp1} < @var{ws1} < @var{ws2} < @var{wp2}), the filter is a band-stop ## or band-reject filter. ## ## If the optional argument @code{"s"} is given, the minimum order for an analog ## elliptic filter is computed. All frequencies @var{wp} and @var{ws} are ## specified in radians per second. ## ## Reference: Lamar, Marcus Vinicius, @cite{Notas de aula da disciplina TE 456 - ## Circuitos Analogicos II}, UFPR, 2001/2002. ## @seealso{buttord, cheb1ord, cheb2ord, ellip} ## @end deftypefn function [n, Wp] = ellipord (Wp, Ws, Rp, Rs, opt) if (nargin < 4 || nargin > 5) print_usage (); elseif (nargin == 5 && ! strcmp (opt, "s")) error ("ellipord: OPT must be the string \"s\""); endif if (nargin == 5 && strcmp (opt, "s")) s_domain = true; else s_domain = false; endif if (s_domain) validate_filter_bands ("ellipord", Wp, Ws, "s"); else validate_filter_bands ("ellipord", Wp, Ws); endif if (s_domain) # No prewarp in case of analog filter Wpw = Wp; Wsw = Ws; else ## sampling frequency of 2 Hz T = 2; Wpw = (2 / T) .* tan (pi .* Wp ./ T); # prewarp Wsw = (2 / T) .* tan (pi .* Ws ./ T); # prewarp endif ## pass/stop band to low pass filter transform: if (length (Wpw) == 2 && length (Wsw) == 2) ## Band-pass filter if (Wpw(1) > Wsw(1)) ## Modify band edges if not symmetrical. For a band-pass filter, ## the lower or upper stopband limit is moved, resulting in a smaller ## stopband than the caller requested. if ((Wpw(1) * Wpw(2)) < (Wsw(1) * Wsw(2))) Wsw(2) = Wpw(1) * Wpw(2) / Wsw(1); else Wsw(1) = Wpw(1) * Wpw(2) / Wsw(2); endif wp = Wpw(2) - Wpw(1); ws = Wsw(2) - Wsw(1); ## Band-stop / band-reject / notch filter else ## Modify band edges if not symmetrical. For a band-stop filter, ## the lower or upper passband limit is moved, resulting in a smaller ## rejection band than the caller requested. if ((Wpw(1) * Wpw(2)) > (Wsw(1) * Wsw(2))) Wpw(2) = Wsw(1) * Wsw(2) / Wpw(1); else Wpw(1) = Wsw(1) * Wsw(2) / Wpw(2); endif w02 = Wpw(1) * Wpw(2); wp = w02 / (Wpw(2) - Wpw(1)); ws = w02 / (Wsw(2) - Wsw(1)); endif ws = ws / wp; wp = 1; ## High-pass filter elseif (Wpw > Wsw) wp = Wsw; ws = Wpw; ## Low-pass filter else wp = Wpw; ws = Wsw; endif k = wp / ws; k1 = sqrt (1 - k^2); q0 = (1/2) * ((1 - sqrt (k1)) / (1 + sqrt (k1))); q = q0 + 2 * q0^5 + 15 * q0^9 + 150 * q0^13; #(....) D = (10 ^ (0.1 * Rs) - 1) / (10 ^ (0.1 * Rp) - 1); n = ceil (log10 (16 * D) / log10 (1 / q)); if (s_domain) # No prewarp in case of analog filter Wp = Wpw; else # Inverse frequency warping for discrete-time filter Wp = atan (Wpw .* (T / 2)) .* (T / pi); endif endfunction %!demo %! fs = 44100; %! Npts = fs; %! fpass = 4000; %! fstop = 13713; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn); %! f = 0:fs/2; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_lp_pass_x, outline_lp_pass_y, "m", outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("2nd order digital elliptical low-pass (without margin)"); %!demo %! fs = 44100; %! Npts = fs; %! fpass = 4000; %! fstop = 13712; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn); %! f = 0:fs/2; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_lp_pass_x, outline_lp_pass_y, "m", outline_lp_stop_x, outline_lp_stop_y, "m"); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("3rd order digital elliptical low-pass (just exceeds 2nd order i.e. large margin)"); %!demo %! fs = 44100; %! Npts = fs; %! fstop = 4000; %! fpass = 13713; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn, "high"); %! f = 0:fs/2; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [min(f) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_hp_pass_x, outline_hp_pass_y, "m", outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("2nd order digital elliptical high-pass (without margin)"); %!demo %! fs = 44100; %! Npts = fs; %! fstop = 4000; %! fpass = 13712; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn, "high"); %! f = 0:fs/2; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))); %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [min(f) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_hp_pass_x, outline_hp_pass_y, "m", outline_hp_stop_x, outline_hp_stop_y, "m"); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("3rd order digital elliptical high-pass (just exceeds 2nd order i.e. large margin)"); %!demo %! fs = 44100; %! Npts = fs; %! fpass = [9500 9750]; %! fstop = [8500 10261]; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn); %! f = 5000:15000; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m", outline_bp_stop_x, outline_bp_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("4th order digital elliptical band-pass (without margin) limitation on upper freq"); %!demo %! fs = 44100; %! Npts = fs; %! fpass = [9500 9750]; %! fstop = [9000 10700]; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn); %! f = 5000:15000; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m", outline_bp_stop_x, outline_bp_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("4th order digital elliptical band-pass (without margin) limitation on lower freq"); %!demo %! fs = 44100; %! Npts = fs; %! fpass = [9500 9750]; %! fstop = [8500 10260]; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn); %! f = 5000:15000; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m", outline_bp_stop_x, outline_bp_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("6th order digital elliptical band-pass (just exceeds 4th order i.e. large margin) limitation on upper freq"); %!demo %! fs = 44100; %! Npts = fs; %! fpass = [9500 9750]; %! fstop = [9001 10700]; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn); %! f = 5000:15000; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m", outline_bp_stop_x, outline_bp_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("6th order digital elliptical band-pass (just exceeds 4th order i.e. large margin) limitation on lower freq"); %!demo %! fs = 44100; %! Npts = fs; %! fstop = [9875 10126.5823]; %! fpass = [8500 11073]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn, "stop"); %! f = 5000:15000; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m", outline_notch_pass_x_b, outline_notch_pass_y_b, "m", outline_notch_stop_x, outline_notch_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("4th order digital elliptical notch (without margin) limit on upper freq"); %!demo %! fs = 44100; %! Npts = fs; %! fstop = [9875 10126.5823]; %! fpass = [8952 12000]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn, "stop"); %! f = 5000:15000; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m", outline_notch_pass_x_b, outline_notch_pass_y_b, "m", outline_notch_stop_x, outline_notch_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("4th order digital elliptical notch (without margin) limit on lower freq"); %!demo %! fs = 44100; %! Npts = fs; %! fstop = [9875 10126.5823]; %! fpass = [8500 11072]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn, "stop"); %! f = 5000:15000; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m", outline_notch_pass_x_b, outline_notch_pass_y_b, "m", outline_notch_stop_x, outline_notch_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("6th order digital elliptical notch (just exceeds 4th order) limit on upper freq"); %!demo %! fs = 44100; %! Npts = fs; %! fstop = [9875 10126.5823]; %! fpass = [8953 12000]; %! Rpass = 0.5; %! Rstop = 40; %! Wpass = 2/fs * fpass; %! Wstop = 2/fs * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop) %! [b, a] = ellip (n, Rpass, Rstop, Wn, "stop"); %! f = 5000:15000; %! W = f * (2 * pi / fs); %! H = freqz (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_notch_pass_x_a = [min(f) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [min(f) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m", outline_notch_pass_x_b, outline_notch_pass_y_b, "m", outline_notch_stop_x, outline_notch_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("6th order digital elliptical notch (just exceeds 4th order) limit on lower freq"); %!demo %! fpass = 4000; %! fstop = 20224; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "s"); %! f = 1000:10:100000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! semilogx(f, 20 * log10 (abs (H))) %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_lp_pass_x, outline_lp_pass_y, "m", outline_lp_stop_x, outline_lp_stop_y, "m") %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("2nd order analog elliptical low-pass (without margin)"); %!demo %! fpass = 4000; %! fstop = 20223; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "s"); %! f = 1000:10:100000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))) %! outline_lp_pass_x = [f(2) , fpass(1), fpass(1)]; %! outline_lp_pass_y = [-Rpass, -Rpass , -80]; %! outline_lp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_lp_stop_y = [0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_lp_pass_x, outline_lp_pass_y, "m", outline_lp_stop_x, outline_lp_stop_y, "m") %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("3rd order analog elliptical low-pass (just exceeds 2nd order i.e. large margin)"); %!demo %! fstop = 4000; %! fpass = 20224; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "high", "s"); %! f = 1000:10:100000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))) %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_hp_pass_x, outline_hp_pass_y, "m", outline_hp_stop_x, outline_hp_stop_y, "m") %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("2nd order analog elliptical high-pass (without margin)"); %!demo %! fstop = 4000; %! fpass = 20223; %! Rpass = 3; %! Rstop = 40; %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "high", "s"); %! f = 1000:10:100000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! semilogx (f, 20 * log10 (abs (H))) %! outline_hp_pass_x = [fpass(1), fpass(1), max(f)]; %! outline_hp_pass_y = [-80 , -Rpass , -Rpass]; %! outline_hp_stop_x = [f(2) , fstop(1), fstop(1), max(f)]; %! outline_hp_stop_y = [-Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_hp_pass_x, outline_hp_pass_y, "m", outline_hp_stop_x, outline_hp_stop_y, "m") %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("3rd order analog elliptical high-pass (just exceeds 2nd order i.e. large margin)"); %!demo %! fpass = [9875 10126.5823]; %! fstop = [9000 10657]; %! Rpass = 3; %! Rstop = 40; %! fcenter = sqrt (fpass(1) * fpass(2)); %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "s"); %! f = 5000:15000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m", outline_bp_stop_x, outline_bp_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("4th order analog elliptical band-pass (without margin) limitation on upper freq"); %!demo %! fpass = [9875 10126.5823]; %! fstop = [9384 12000]; %! Rpass = 3; %! Rstop = 40; %! fcenter = sqrt (fpass(1) * fpass(2)); %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "s"); %! f = 5000:15000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m", outline_bp_stop_x, outline_bp_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("4th order analog elliptical band-pass (without margin) limitation on lower freq"); %!demo %! fpass = [9875 10126.5823]; %! fstop = [9000 10656]; %! Rpass = 3; %! Rstop = 40; %! fcenter = sqrt (fpass(1) * fpass(2)); %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "s"); %! f = 5000:15000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m", outline_bp_stop_x, outline_bp_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("6th order analog elliptical band-pass (just exceeds 4th order i.e. large margin) limitation on upper freq"); %!demo %! fpass = [9875 10126.5823]; %! fstop = [9385 12000]; %! Rpass = 3; %! Rstop = 40; %! fcenter = sqrt (fpass(1) * fpass(2)); %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "s"); %! f = 5000:15000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_bp_pass_x = [fpass(1), fpass(1), fpass(2), fpass(2)]; %! outline_bp_pass_y = [-80 , -Rpass , -Rpass , -80]; %! outline_bp_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_bp_stop_y = [-Rstop , -Rstop , 0 , 0 , -Rstop , -Rstop]; %! hold on %! plot (outline_bp_pass_x, outline_bp_pass_y, "m", outline_bp_stop_x, outline_bp_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("6th order analog elliptical band-pass (just exceeds 4th order i.e. large margin) limitation on lower freq"); %!demo %! fstop = [9875 10126.5823]; %! fpass = [9000 10657]; %! Rpass = 3; %! Rstop = 40; %! fcenter = sqrt (fpass(1) * fpass(2)); %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "stop", "s"); %! f = 5000:15000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m", outline_notch_pass_x_b, outline_notch_pass_y_b, "m", outline_notch_stop_x, outline_notch_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("4th order analog elliptical notch (without margin) limit on upper freq"); %!demo %! fstop = [9875 10126.5823]; %! fpass = [9384 12000]; %! Rpass = 3; %! Rstop = 40; %! fcenter = sqrt (fpass(1) * fpass(2)); %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "stop", "s"); %! f = 5000:15000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m", outline_notch_pass_x_b, outline_notch_pass_y_b, "m", outline_notch_stop_x, outline_notch_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("4th order analog elliptical notch (without margin) limit on lower freq"); %!demo %! fstop = [9875 10126.5823]; %! fpass = [9000 10656]; %! Rpass = 3; %! Rstop = 40; %! fcenter = sqrt (fpass(1) * fpass(2)); %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "stop", "s"); %! f = 5000:15000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m", outline_notch_pass_x_b, outline_notch_pass_y_b, "m", outline_notch_stop_x, outline_notch_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("6th order analog elliptical notch (just exceeds 4th order) limit on upper freq"); %!demo %! fstop = [9875 10126.5823]; %! fpass = [9385 12000]; %! Rpass = 3; %! Rstop = 40; %! fcenter = sqrt (fpass(1) * fpass(2)); %! Wpass = 2*pi * fpass; %! Wstop = 2*pi * fstop; %! [n, Wn] = ellipord (Wpass, Wstop, Rpass, Rstop, "s") %! [b, a] = ellip (n, Rpass, Rstop, Wn, "stop", "s"); %! f = 5000:15000; %! W = 2*pi * f; %! H = freqs (b, a, W); %! plot (f, 20 * log10 (abs (H))) %! outline_notch_pass_x_a = [f(2) , fpass(1), fpass(1)]; %! outline_notch_pass_x_b = [fpass(2), fpass(2), max(f)]; %! outline_notch_pass_y_a = [-Rpass , -Rpass , -80]; %! outline_notch_pass_y_b = [-80 , -Rpass , -Rpass]; %! outline_notch_stop_x = [f(2) , fstop(1), fstop(1), fstop(2), fstop(2), max(f)]; %! outline_notch_stop_y = [0 , 0 , -Rstop , -Rstop , 0 , 0 ]; %! hold on %! plot (outline_notch_pass_x_a, outline_notch_pass_y_a, "m", outline_notch_pass_x_b, outline_notch_pass_y_b, "m", outline_notch_stop_x, outline_notch_stop_y, "m") %! xlim ([f(1), f(end)]); %! ylim ([-80, 0]); %! grid on %! xlabel ("Frequency (Hz)"); %! ylabel ("Attenuation (dB)"); %! title ("6th order analog elliptical notch (just exceeds 4th order) limit on lower freq"); %!test %! # Analog band-pass %! [n, Wn] = ellipord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9000, 10657], 3, 40, "s"); %! assert (n, 2); %! assert (round (Wn), [62046, 63627]); %!test %! # Analog band-pass %! [n, Wn] = ellipord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9384, 12000], 3, 40, "s"); %! assert (n, 2); %! assert (round (Wn), [62046, 63627]); %!test %! # Analog band-pass %! [n, Wn] = ellipord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9000, 10656], 3, 40, "s"); %! assert (n, 3); %! assert (round (Wn), [62046, 63627]); %!test %! # Analog band-pass %! [n, Wn] = ellipord (2 * pi * [9875, 10126.5823], ... %! 2 * pi * [9385, 12000], 3, 40, "s"); %! assert (n, 3); %! assert (round (Wn), [62046, 63627]); %!test %! # Analog high-pass %! [n, Wn] = ellipord (2 * pi * 20224, 2 * pi * 4000, 3, 40, "s"); %! assert (n, 2); %! assert (round (Wn), 127071); %!test %! # Analog high-pass %! [n, Wn] = ellipord (2 * pi * 20223, 2 * pi * 4000, 3, 40, "s"); %! assert (n, 3); %! assert (round (Wn), 127065); %!test %! # Analog low-pass %! [n, Wn] = ellipord (2 * pi * 4000, 2 * pi * 20224, 3, 40, "s"); %! assert (n, 2); %! assert (round (Wn), 25133); %!test %! # Analog low-pass %! [n, Wn] = ellipord (2 * pi * 4000, 2 * pi * 20223, 3, 40, "s"); %! assert (n, 3); %! assert (round (Wn), 25133); %!test %! # Analog notch (narrow band-stop) %! [n, Wn] = ellipord (2 * pi * [9000, 10657], ... %! 2 * pi * [9875, 10126.5823], 3, 40, "s"); %! assert (n, 2); %! assert (round (Wn), [58958, 66960]); %!test %! # Analog notch (narrow band-stop) %! [n, Wn] = ellipord (2 * pi * [9384, 12000], ... %! 2 * pi * [9875, 10126.5823], 3, 40, "s"); %! assert (n, 2); %! assert (round (Wn), [58961 , 66956]); %!test %! # Analog notch (narrow band-stop) %! [n, Wn] = ellipord (2 * pi * [9000, 10656], ... %! 2 * pi * [9875, 10126.5823], 3, 40, "s"); %! assert (n, 3); %! assert (round (Wn), [58964, 66954]); %!test %! # Analog notch (narrow band-stop) %! [n, Wn] = ellipord (2 * pi * [9385, 12000], ... %! 2 * pi * [9875, 10126.5823], 3, 40, "s"); %! assert (n, 3); %! assert (round (Wn), [58968, 66949]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * [9500, 9750], 2 / fs * [8500, 10261], 3, 40); %! Wn = Wn * fs / 2; %! assert (n, 2); %! assert (round (Wn), [9500, 9750]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * [9500, 9750], 2 / fs * [9000, 10700], 3, 40); %! Wn = Wn * fs / 2; %! assert (n, 2); %! assert (round (Wn), [9500, 9750]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * [9500, 9750], 2 / fs * [8500, 10260], 3, 40); %! Wn = Wn * fs / 2; %! assert (n, 3); %! assert (round (Wn), [9500, 9750]); %!test %! # Digital band-pass %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * [9500, 9750], 2 / fs * [9001, 10700], 3, 40); %! Wn = Wn * fs / 2; %! assert (n, 3); %! assert (round (Wn), [9500, 9750]); %!test %! # Digital high-pass %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * 13713, 2 / fs * 4000, 3, 40); %! Wn = Wn * fs / 2; %! assert (n, 2); %! assert (round (Wn), 13713); %!test %! # Digital high-pass %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * 13712, 2 / fs * 4000, 3, 40); %! Wn = Wn * fs / 2; %! assert (n, 3); %! assert (round (Wn), 13712); %!test %! # Digital low-pass %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * 4000, 2 / fs * 13713, 3, 40); %! Wn = Wn * fs / 2; %! assert (n, 2); %! assert (round (Wn), 4000); %!test %! # Digital low-pass %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * 4000, 2 / fs * 13712, 3, 40); %! Wn = Wn * fs / 2; %! assert (n, 3); %! assert (round (Wn), 4000); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * [8500, 11073], 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn = Wn * fs / 2; %! assert (n, 2); %! assert (round (Wn), [8952, 11073]); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * [8952, 12000], 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn = Wn * fs / 2; %! assert (n, 2); %! assert (round (Wn), [8952, 11073]); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * [8500, 11072], 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn = Wn * fs / 2; %! assert (n, 3); %! assert (round (Wn), [8953, 11072]); %!test %! # Digital notch (narrow band-stop) %! fs = 44100; %! [n, Wn] = ellipord (2 / fs * [8953, 12000], 2 / fs * [9875, 10126.5823], 0.5, 40); %! Wn = Wn * fs / 2; %! assert (n, 3); %! assert (round (Wn), [8953, 11072]); ## Test input validation %!error ellipord () %!error ellipord (.1) %!error ellipord (.1, .2) %!error ellipord (.1, .2, 3) %!error ellipord ([.1 .1], [.2 .2], 3, 4) %!error ellipord ([.1 .2], [.5 .6], 3, 4) %!error ellipord ([.1 .5], [.2 .6], 3, 4) �������������������������������������signal-1.4.6/inst/expwin.m��������������������������������������������������������������������������0000644�0000000�0000000�00000006344�14673270174�012414� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2023 The Octave Project Developers ## ## See the file COPYRIGHT.md in the top-level directory of this ## distribution or <https://octave.org/copyright/>. ## ## This file is part of Octave. ## ## Octave 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. ## ## Octave 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 Octave; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} expwin (@var{m}, @var{alpha}) ## @deftypefnx {Function File} expwin (@var{m}, @var{sll}) ## @deftypefnx {Function File} expwin (@dots{}, "canonical") ## Return the coefficients of an exponential window@footnote{K. Avci & A. ## Nacaroglu, `Exponential Window Family', SIPIJ Vol.@: 4 No.@: 4, August ## 2013.} of length @var{m}. ## ## The window's adjustable parameter can be set directly as ## @var{alpha} (@geq{}0) or indirectly with ## @var{sll} (<0), the latter being the desired side-lobe level in dBc. ## ## By default, the returned window is both symmetric and periodic. With the ## optional argument @qcode{"canonical"}, the canonical form of the window is ## returned, which is symmetric but not periodic. ## ## @seealso{kaiser, poisswin} ## @end deftypefn function W = expwin (m, a, opt) if nargin<2 || nargin>3 || (nargin==3 && !strcmp (opt,'canonical')) print_usage (); elseif !isscalar (m) || imag (m) || mod (m,1) || m<0 error ('expwin: M must be a positive integer'); elseif !isscalar (a) || imag (a) error ('expwin: ALPHA/SLL must be a real scalar'); endif if m<3 W = ones (m,1); return endif % If given SLL then estimate alpha: if a<=-50 a = -1.085e-4*a*a-0.1506*a-0.304; elseif a<=-13.26 a = -1.513e-3*a*a-0.2809*a-3.398; elseif a<0 a = 0; endif T = [1-m:2:0]/(m-(nargin==3)); T = sqrt (1-T.^2)-1; W = exp (a*T); W = [W W(m-length (W):-1:1)]'; endfunction %!test % even M; odd alpha: %! w=[0.0321 0.09385 0.184 0.3011 0.4386 0.5858 0.7289 0.8532 0.945 0.9938]; %! assert (expwin (20, 5), [w flip(w)]', 51e-6); %!test % odd M; even alpha: %! w=[0.06202 0.1437 0.2443 0.3611 0.488 0.6172 0.7396 0.8464 0.9294 0.982]; %! assert (expwin (21, 4), [w 1 flip(w)]', 51e-6); %!test % even M; odd alpha; canonical: %! w=[0.006738 0.06285 0.145 0.2583 0.3973 0.5507 0.7035 0.8384 0.9392 0.9931]; %! assert (expwin (20, 5, 'canonical'), [w flip(w)]', 51e-6); %!test % odd M; even alpha; canonical: %! w=[0.01832 0.1047 0.2019 0.3187 0.4493 0.5851 0.7161 0.8317 0.9224 0.9801]; %! assert (expwin (21, 4, 'canonical'), [w 1 flip(w)]', 51e-6); %% Test input validation: %!error expwin %!error expwin (21.5,1) %!error expwin (21i,1) %!error expwin (21:22,1) %!error expwin ({21},1) %!error expwin (21, 4i) %!error expwin (21, 2:3) %!error expwin (21, {4}) %!error expwin (21, 4, 1) %!error expwin (21, 4, 'canonical', 1) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/fht.m�����������������������������������������������������������������������������0000644�0000000�0000000�00000004172�14673270174�011660� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2008 Muthiah Annamalai <muthiah.annamalai@uta.edu> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{m} =} fht (@var{d}) ## @deftypefnx {Function File} {@var{m} =} fht (@var{d}, @var{n}) ## @deftypefnx {Function File} {@var{m} =} fht (@var{d}, @var{n}, @var{dim}) ## Calculate the Fast Hartley Transform of real input @var{d}. If @var{d} is ## a matrix, the Hartley transform is calculated along the columns by default. ## The options @var{n} and @var{dim} are similar to the options of FFT ## function. ## ## The forward and inverse Hartley transforms are the same (except for a ## scale factor of 1/N for the inverse Hartley transform), but ## implemented using different functions. ## ## The definition of the forward hartley transform for vector d, ## @math{ ## m[K] = \sum_{i=0}^{N-1} d[i]*(cos[K*2*pi*i/N] + sin[K*2*pi*i/N]), for 0 <= K < N. ## m[K] = \sum_{i=0}^{N-1} d[i]*CAS[K*i], for 0 <= K < N. } ## ## @example ## fht(1:4) ## @end example ## @seealso{ifht, fft} ## @end deftypefn function m = fht( d, n, dim ) if ( nargin < 1 ) print_usage(); endif if ( nargin == 3 ) Y = fft(d,n,dim); elseif ( nargin == 2 ) Y = fft(d,n); else Y = fft(d); endif m = real(Y) - imag(Y); ## -- Traditional -- ## N = length(d); ## for K = 1:N ## i = 0:N-1; ## t = 2*pi*(K-1).*i/N; ## ker = (cos(t) + sin(t)); ## val = dot(d,ker); ## m(K) = val; ## endfor endfunction %! %!assert( fht([1 2 3 4]),[10 -4 -2 0] ) %! ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/filternorm.m����������������������������������������������������������������������0000644�0000000�0000000�00000005655�14673270174�013267� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2023 Leonardo Araujo <leolca@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{L} = } filternorm (@var{b}, @var{a}) ## @deftypefnx {Function File} {@var{L} = } filternorm (@var{b}, @var{a}, @var{pnorm}) ## @deftypefnx {Function File} {@var{L} = } filternorm (@var{b}, @var{a}, 2, @var{tol}) ## ## Compute the 2-norm of a digital filter defined by the numerator coefficients, ## @var{b}, and the denominator coefficients, @var{a}. It is also possible to ## compute the infinity-norm by passing inf in the @var{pnorm} parameter. ## @var{pnorm} only accepts 2 or inf. ## ## Example: ## @example ## [b, a] = butter (8, 0.5); ## filternorm (b, a) ## @end example ## @end deftypefn function L = filternorm (b, a, pnorm, tol) if (nargin < 2 || nargin > 4 || ! isrow (b) || ! isrow (a)) print_usage; endif if nargin < 3 pnorm = 2; endif if pnorm != 2 && pnorm != Inf error ("pnorm should be either 2 or Inf") endif if nargin == 2 || pnorm == 2 # Parseval's theorem states that the L2-norm of a filter with frequency # response H(e^{j\omega}) is the square-root of the sum of the squares # of its filter impulse response (the energy of the impulse response). [h, _] = impz (b,a); L = sqrt (sum (h.^2)); % L = normp (h, pnorm); elseif pnorm == Inf # the norm in L-infinity is simply the maximum of the frequency response: # ||H||_{\infty} = \max_{0 \leq \omega \leq \pi} { |H(e^{j\omega})|} [H, W] = freqz (b, a, 1024); L = max (abs (H)); else error( "filternorm: pnorm must be either 2 or Inf" ); endif endfunction %!demo %! b = [1 0]; %! a = [1 1]; %! L = filternorm (b, a) %!demo %! [b, a] = butter(5, .5); %! L = filternorm (b, a) %! ## test input validation %!error n = filternorm () %!error n = filternorm (1) %!error n = filternorm (1, 1, 1) %!error n = filternorm (1, 1, 1, 1) %!error n = filternorm (1, 1, 1, 1, 1) %!error n = filternorm ([1:10]', 1) %!error n = filternorm (1, [1:10]') %!error n = filternorm ([1:10]', [1:10]') %!error n = filternorm (1:10, 1:10, 1:10) %!error n = filternorm (ones(3), ones(3)) %!test %! [b, a] = butter (5, .5); %! L = filternorm (b, a); %! assert (L, sqrt(2)/2, 1e-8) %!test %! [b, a] = butter (5, .5); %! Linf = filternorm (b, a, Inf); %! assert (Linf, 1, 1e-8); �����������������������������������������������������������������������������������signal-1.4.6/inst/filtfilt.m������������������������������������������������������������������������0000644�0000000�0000000�00000010566�14673270174�012720� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2007 Francesco Potortì <pot@gnu.org> ## Copyright (C) 2008 Luca Citi <lciti@essex.ac.uk> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} filtfilt (@var{b}, @var{a}, @var{x}) ## ## Forward and reverse filter the signal. This corrects for phase ## distortion introduced by a one-pass filter, though it does square the ## magnitude response in the process. That's the theory at least. In ## practice the phase correction is not perfect, and magnitude response ## is distorted, particularly in the stop band. ## ## Example ## @example ## @group ## [b, a]=butter(3, 0.1); # 5 Hz low-pass filter ## t = 0:0.01:1.0; # 1 second sample ## x=sin(2*pi*t*2.3)+0.25*randn(size(t)); # 2.3 Hz sinusoid+noise ## y = filtfilt(b,a,x); z = filter(b,a,x); # apply filter ## plot(t,x,';data;',t,y,';filtfilt;',t,z,';filter;') ## @end group ## @end example ## @end deftypefn ## FIXME: My version seems to have similar quality to matlab, ## but both are pretty bad. They do remove gross lag errors, though. function y = filtfilt(b, a, x) if (nargin != 3) print_usage; endif rotate = (size(x,1)==1); if rotate, # a row vector x = x(:); # make it a column vector endif lx = size(x,1); a = a(:).'; b = b(:).'; lb = length(b); la = length(a); n = max(lb, la); lrefl = 3 * (n - 1); if la < n, a(n) = 0; endif if lb < n, b(n) = 0; endif if (rows (x) <= lrefl) error ("filtfilt: X must be a vector or matrix with length greater than %d", lrefl); endif ## Compute a the initial state taking inspiration from ## Likhterov & Kopeika, 2003. "Hardware-efficient technique for ## minimizing startup transients in Direct Form II digital filters" kdc = sum(b) / sum(a); if (abs(kdc) < inf) # neither NaN nor +/- Inf si = fliplr(cumsum(fliplr(b - kdc * a))); else si = zeros(size(a)); # fall back to zero initialization endif si(1) = []; for (c = 1:size(x,2)) # filter all columns, one by one v = [2*x(1,c)-x((lrefl+1):-1:2,c); x(:,c); 2*x(end,c)-x((end-1):-1:end-lrefl,c)]; # a column vector ## Do forward and reverse filtering v = filter(b,a,v,si*v(1)); # forward filter v = flipud(filter(b,a,flipud(v),si*v(end))); # reverse filter y(:,c) = v((lrefl+1):(lx+lrefl)); endfor if (rotate) # x was a row vector y = rot90(y); # rotate it back endif endfunction %!error filtfilt (); %!error filtfilt (1, 2, 3, 4); %!error filtfilt ([0.28, 0.71, 0.28], 1, rand ()) %!error filtfilt ([0.28, 0.71, 0.28], 1, rand (6, 1)) %!test %! randn('state',0); %! r = randn(1,200); %! [b,a] = butter(10, [.2, .25]); %! yfb = filtfilt(b, a, r); %! assert (size(r), size(yfb)); %! assert (mean(abs(yfb)) < 1e3); %! assert (mean(abs(yfb)) < mean(abs(r))); %! ybf = fliplr(filtfilt(b, a, fliplr(r))); %! assert (mean(abs(ybf)) < 1e3); %! assert (mean(abs(ybf)) < mean(abs(r))); %!test %! randn('state',0); %! r = randn(1,1000); %! s = 10 * sin(pi * 4e-2 * (1:length(r))); %! [b,a] = cheby1(2, .5, [4e-4 8e-2]); %! y = filtfilt(b, a, r+s); %! assert (size(r), size(y)); %! assert (mean(abs(y)) < 1e3); %! assert (corr(s(250:750)(:), y(250:750)(:)) > .95) %! [b,a] = butter(2, [4e-4 8e-2]); %! yb = filtfilt(b, a, r+s); %! assert (mean(abs(yb)) < 1e3); %! assert (corr(y(:), yb(:)) > .99) %!test %! randn('state',0); %! r = randn(1,1000); %! s = 10 * sin(pi * 4e-2 * (1:length(r))); %! [b,a] = butter(2, [4e-4 8e-2]); %! y = filtfilt(b, a, [r.' s.']); %! yr = filtfilt(b, a, r); %! ys = filtfilt(b, a, s); %! assert (y, [yr.' ys.']); %! y2 = filtfilt(b.', a.', [r.' s.']); %! assert (y, y2); ������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/filtic.m��������������������������������������������������������������������������0000644�0000000�0000000�00000007531�14673270174�012353� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2004 David Billinghurst <David.Billinghurst@riotinto.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{zf} =} filtic (@var{b}, @var{a}, @var{y}) ## @deftypefnx {Function File} {@var{zf} =} filtic (@var{b}, @var{a}, @var{y}, @var{x}) ## ## Set initial condition vector for filter function ## The vector zf has the same values that would be obtained ## from function filter given past inputs x and outputs y ## ## The vectors x and y contain the most recent inputs and outputs ## respectively, with the newest values first: ## ## x = [x(-1) x(-2) ... x(-nb)], nb = length(b)-1 ## y = [y(-1) y(-2) ... y(-na)], na = length(a)-a ## ## If length(x)<nb then it is zero padded ## If length(y)<na then it is zero padded ## ## zf = filtic(b, a, y) ## Initial conditions for filter with coefficients a and b ## and output vector y, assuming input vector x is zero ## ## zf = filtic(b, a, y, x) ## Initial conditions for filter with coefficients a and b ## input vector x and output vector y ## @end deftypefn function zf = filtic(b,a,y,x) if (nargin>4 || nargin<3) || (nargout>1) print_usage; endif if nargin < 4, x = []; endif nz = max(length(a)-1,length(b)-1); zf=zeros(nz,1); ## Pad arrays a and b to length nz+1 if required if length(a)<(nz+1) a(length(a)+1:nz+1)=0; endif if length(b)<(nz+1) b(length(b)+1:nz+1)=0; endif ## Pad arrays x and y to length nz if required if length(x) < nz x(length(x)+1:nz)=0; endif if length(y) < nz y(length(y)+1:nz)=0; endif for i=nz:-1:1 for j=i:nz-1 zf(j) = b(j+1)*x(i) - a(j+1)*y(i)+zf(j+1); endfor zf(nz)=b(nz+1)*x(i)-a(nz+1)*y(i); endfor zf = zf ./ a(1); endfunction %!test %! ## Simple low pass filter %! b=[0.25 0.25]; %! a=[1.0 -0.5]; %! zf_ref=0.75; %! zf=filtic(b,a,[1.0],[1.0]); %! assert(zf,zf_ref,8*eps); %! %!test %! ## Simple high pass filter %! b=[0.25 -0.25]; %! a=[1.0 0.5]; %! zf_ref = [-0.25]; %! zf=filtic(b,a,[0.0],[1.0]); %! assert(zf,zf_ref,8*eps); %! %!test %! ## Second order cases %! [b,a]=butter(2,0.4); %! N=1000; ## Long enough for filter to settle %! xx=ones(1,N); %! [yy,zf_ref] = filter(b,a,xx); %! x=xx(N:-1:N-1); %! y=yy(N:-1:N-1); %! zf = filtic(b,a,y,x); %! assert(zf,zf_ref,8*eps); %! %! xx = cos(2*pi*linspace(0,N-1,N)/8); %! [yy,zf_ref] = filter(b,a,xx); %! x=xx(N:-1:N-1); %! y=yy(N:-1:N-1); %! zf = filtic(b,a,y,x); %! assert(zf,zf_ref,8*eps); %! %!test %! ## Third order filter - takes longer to settle %! N=10000; %! [b,a]=cheby1(3,10,0.5); %! xx=ones(1,N); %! [yy,zf_ref] = filter(b,a,xx); %! x=xx(N:-1:N-2); %! y=yy(N:-1:N-2); %! zf = filtic(b,a,y,x); %! assert(zf,zf_ref,8*eps); %! %!test %! ## Eight order high pass filter %! N=10000; %! [b,a]=butter(8,0.2); %! xx = cos(2*pi*linspace(0,N-1,N)/8); %! [yy,zf_ref] = filter(b,a,xx); %! x=xx(N:-1:N-7); %! y=yy(N:-1:N-7); %! zf = filtic(b,a,y,x); %! assert(zf,zf_ref,8*eps); %! %!test %! ## Case with 3 args %! [b,a]=butter(2,0.4); %! N=100; %! xx=[ones(1,N) zeros(1,2)]; %! [yy,zf_ref] = filter(b,a,xx); %! y=[yy(N+2) yy(N+1)]; %! zf=filtic(b,a,y); %! assert(zf,zf_ref,8*eps); ## Case when a(1) != 1 %!test %! a = [2, -3, 1]; %! b = [4, -3]; %! y = [0; 1]; %! z = filtic (b, a, y); %! assert (z, [-0.5; 0]); �����������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/filtord.m�������������������������������������������������������������������������0000644�0000000�0000000�00000004763�14673270174�012550� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2023 Leonardo Araujo <leolca@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{n} = } filtord (@var{b}, @var{a}) ## @deftypefnx {Function File} {@var{n} = } filtord (@var{sos}) ## ## Returns the filter order @var{n} for a filter defined by the numerator ## coefficients, @var{b}, and the denominator coefficients, @var{a}. ## It also accepts a filter defined by a matrix of second-order sections, ## @var{sos}. ## ## Example: ## @example ## [b, a] = butter (8, 0.5); ## filtord (b, a) ## @end example ## @end deftypefn function n = filtord (b, a) if (nargin < 1 || nargin > 2) || ( nargin == 2 && ( ! isrow (b) || ! isrow (a) ) ) print_usage; endif if (nargin == 1 && isrow (b)) a = 1; endif if isrow (b) n = max ( length (b)-1, length (a)-1 ); else n = (size (b, 1) - 1) * 2 + max (sum (b(end,1:3) != 0) , sum (b(end,4:6) != 0)) - 1; endif endfunction %!demo %! b = [1 0]; %! a = [1 1]; %! n = filtord (b, a) %!demo %! b = [1 0 0 0 0 0 0 1]; %! a = [1 0 0 0 0 0 0 .5]; %! [sos, g] = tf2sos (b, a); %! n = filtord (sos) %! ## test input validation %!error n = filtord () %!error n = filtord (1, 1, 1) %!error n = filtord ([1:10]', 1) %!error n = filtord (1, [1:10]') %!error n = filtord ([1:10]', [1:10]') %!error n = filtord (1:10, 1:10, 1:10) %!error n = filtord (ones(3), ones(3)) %!test %! b = [1 0 0]; %! a = [1 0 0 0]; %! n = filtord (b, a); %! assert (n, 3, 1e-6) %!test %! [b, a] = butter (5, .5); %! n = filtord (b, a); %! assert (n, 5, 1e-6) %!test %! [b, a] = butter (6, .5); %! n = filtord (b, a); %! assert (n, 6, 1e-6) %!test %! b = [1 0 0 0 0 0 1]; %! a = [1 0 0 0 0 0 .5]; %! [sos, g] = tf2sos (b, a); %! n = filtord (sos); %! assert (n, 6, 1e-6) %!test %! b = [1 0 0 0 0 0 0 1]; %! a = [1 0 0 0 0 0 0 .5]; %! [sos, g] = tf2sos (b, a); %! n = filtord (sos); %! assert (n, 7, 1e-6) �������������signal-1.4.6/inst/findpeaks.m�����������������������������������������������������������������������0000644�0000000�0000000�00000032323�14673270174�013042� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2012 Juan Pablo Carbajal <carbajal@ifi.uzh.ch> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{pks}, @var{loc}, @var{extra}] =} findpeaks (@var{data}) ## @deftypefnx {Function File} {@dots{} =} findpeaks (@dots{}, @var{property}, @var{value}) ## @deftypefnx {Function File} {@dots{} =} findpeaks (@dots{}, @asis{"DoubleSided"}) ## Finds peaks on @var{data}. ## ## Peaks of a positive array of data are defined as local maxima. For ## double-sided data, they are maxima of the positive part and minima of ## the negative part. @var{data} is expected to be a single column ## vector. ## ## The function returns the value of @var{data} at the peaks in ## @var{pks}. The index indicating their position is returned in ## @var{loc}. ## ## The third output argument is a structure with additional information: ## ## @table @asis ## @item "parabol" ## A structure containing the parabola fitted to each returned peak. The ## structure has two fields, @asis{"x"} and @asis{"pp"}. The field ## @asis{"pp"} contains the coefficients of the 2nd degree polynomial ## and @asis{"x"} the extrema of the interval where it was fitted. ## ## @item "height" ## The estimated height of the returned peaks (in units of @var{data}). ## ## @item "baseline" ## The height at which the roots of the returned peaks were calculated ## (in units of @var{data}). ## ## @item "roots" ## The abscissa values (in index units) at which the parabola fitted to ## each of the returned peaks realizes its width as defined below. ## @end table ## ## This function accepts property-value pair given in the list below: ## ## @table @asis ## ## @item "MinPeakHeight" ## Minimum peak height (non-negative scalar). Only peaks that exceed this ## value will be returned. For data taking positive and negative values ## use the option "DoubleSided". Default value @code{eps}. ## ## @item "MinPeakDistance" ## Minimum separation between (positive integer). Peaks separated by ## less than this distance are considered a single peak. This distance ## is also used to fit a second order polynomial to the peaks to ## estimate their width, therefore it acts as a smoothing parameter. ## The neighborhood size is equal to the value of @asis{"MinPeakDistance"}. ## Default value 1. ## ## @item "MinPeakWidth" ## Minimum width of peaks (positive integer). The width of the peaks is ## estimated using a parabola fitted to the neighborhood of each peak. ## The width is caulculated with the formula ## @verbatim ## a * (width - x0)^2 = 1 ## @end verbatim ## where a is the the concavity of the parabola and x0 its vertex. ## Default value 1. ## ## @item "MaxPeakWidth" ## Maximum width of peaks (positive integer). ## Default value @code{Inf}. ## ## @item "DoubleSided" ## Tells the function that data takes positive and negative values. The ## base-line for the peaks is taken as the mean value of the function. ## This is equivalent as passing the absolute value of the data after ## removing the mean. ## @end table ## ## Run @command{demo findpeaks} to see some examples. ## @end deftypefn function [pks idx varargout] = findpeaks (data, varargin) if (nargin < 1) print_usage (); endif if (! (isvector (data) && numel (data) >= 3)) error ("findpeaks:InvalidArgument", "findpeaks: DATA must be a vector of at least 3 elements"); endif transpose = (rows (data) == 1); if (transpose) data = data.'; endif ## --- Parse arguments --- # __data__ = abs (detrend (data, 0)); posscal = @(x) isscalar (x) && x >= 0; ## FIXME: inputParser was first implemented in the general package in the ## old @class type. This allowed for a very similar interface to ## Matlab but not quite equal. classdef was then implemented in ## Octave 4.0 release, which enabled inputParser to be implemented ## properly. However, this causes problem because we don't know ## what implementation may be running. A new version of the general ## package is being released to avoid the two implementations to ## co-exist. ## ## To keep supporting older octave versions, we have an alternative ## path that avoids inputParser. And if inputParser is available, ## we check what implementation is, and act accordingly. ## Note that in Octave 4.0, inputParser is classdef and Octave behaves ## weird for it. which ("inputParser") will return empty (thinks its a ## builtin function). if (exist ("inputParser") == 2 && isempty (strfind (which ("inputParser"), ["@inputParser" filesep "inputParser.m"]))) ## making use of classdef's inputParser .. parser = inputParser (); parser.FunctionName = "findpeaks"; parser.addParamValue ("MinPeakHeight", eps,posscal); parser.addParamValue ("MinPeakDistance", 1, posscal); parser.addParamValue ("MinPeakWidth", 1, posscal); parser.addParamValue ("MaxPeakWidth", Inf, posscal); parser.addSwitch ("DoubleSided"); parser.parse (varargin{:}); minH = parser.Results.MinPeakHeight; minD = parser.Results.MinPeakDistance; minW = parser.Results.MinPeakWidth; maxW = parser.Results.MaxPeakWidth; dSided = parser.Results.DoubleSided; else ## either old @inputParser or no inputParser at all... lvarargin = lower (varargin); ds = strcmpi (lvarargin, "DoubleSided"); if (any (ds)) dSided = true; lvarargin(ds) = []; else dSided = false; endif [~, minH, minD, minW, maxW] = parseparams (lvarargin, "minpeakheight", eps, "minpeakdistance", 1, "minpeakwidth", 1, "maxpeakwidth", Inf); if (! posscal (minH)) error ("findpeaks: MinPeakHeight must be a positive scalar"); elseif (! posscal (minD)) error ("findpeaks: MinPeakDistance must be a positive scalar"); elseif (! posscal (minW)) error ("findpeaks: MinPeakWidth must be a positive scalar"); elseif (! posscal (maxW)) error ("findpeaks: MaxPeakWidth must be a positive scalar"); endif endif if (dSided) [data, __data__] = deal (__data__, data); elseif (min (data) < 0) error ("findpeaks:InvalidArgument", 'Data contains negative values. You may want to "DoubleSided" option'); endif ## Rough estimates of first and second derivative df1 = diff (data, 1)([1; (1:end).']); df2 = diff (data, 2)([1; 1; (1:end).']); ## check for changes of sign of 1st derivative and negativity of 2nd ## derivative. ## <= in 1st derivative includes the case of oversampled signals. idx = find (df1.*[df1(2:end); 0] <= 0 & [df2(2:end); 0] < 0); ## Get peaks that are beyond given height tf = data(idx) > minH; idx = idx(tf); ## sort according to magnitude [~, tmp] = sort (data(idx), "descend"); idx_s = idx(tmp); ## Treat peaks separated less than minD as one D = abs (bsxfun (@minus, idx_s, idx_s.')); D += diag(NA(1,size(D,1))); # eliminate diagonal cpmparison if (any (D(:) < minD)) i = 1; peak = cell (); node2visit = 1:size(D,1); visited = []; idx_pruned = idx_s; ## debug ## h = plot(1:length(data),data,"-",idx_s,data(idx_s),'.r',idx_s,data(idx_s),'.g'); ## set(h(3),"visible","off"); while (! isempty (node2visit)) d = D(node2visit(1),:); visited = [visited node2visit(1)]; node2visit(1) = []; neighs = setdiff (find (d < minD), visited); if (! isempty (neighs)) ## debug ## set(h(3),"xdata",idx_s(neighs),"ydata",data(idx_s(neighs)),"visible","on") ## pause(0.2) ## set(h(3),"visible","off"); idx_pruned = setdiff (idx_pruned, idx_s(neighs)); visited = [visited neighs]; node2visit = setdiff (node2visit, visited); ## debug ## set(h(2),"xdata",idx_pruned,"ydata",data(idx_pruned)) ## pause endif endwhile idx = idx_pruned; endif extra = struct ("parabol", [], "height", [], "baseline", [], "roots", []); ## Estimate widths of peaks and filter for: ## width smaller than given. ## wrong concavity. ## not high enough ## data at peak is lower than parabola by 1% ## position of extrema minus center is bigger equal than minD/2 ## debug ## h = plot(1:length(data),data,"-",idx,data(idx),'.r',... ## idx,data(idx),'og',idx,data(idx),'-m'); ## set(h(4),"linewidth",2) ## set(h(3:4),"visible","off"); idx_pruned = idx; n = numel (idx); np = numel (data); struct_count = 0; for i=1:n ind = (floor (max(idx(i)-minD/2,1)) : ... ceil (min(idx(i)+minD/2,np))).'; pp = zeros (1,3); # If current peak is not local maxima, then fit parabola to neighbor if any (data(idx(i)-1) == data(idx(i))) # sample on left same as peak xm = 0; pp = ones (1,3); elseif any (data(ind) > data(idx(i))) pp = polyfit (ind, data(ind), 2); xm = -pp(2)^2 / (2*pp(1)); # position of extrema H = polyval (pp, xm); # value at extrema else # use it as vertex of parabola H = data(idx(i)); xm = idx(i); pp = zeros (1,3); pp(1) = (ind-xm).^2 \ (data(ind)-H); pp(2) = - 2 * pp(1) * xm; pp(3) = H + pp(1) * xm^2; endif ## debug # x = linspace(ind(1)-1,ind(end)+1,10); # set(h(4),"xdata",x,"ydata",polyval(pp,x),"visible","on") # set(h(3),"xdata",ind,"ydata",data(ind),"visible","on") # pause(0.2) # set(h(3:4),"visible","off"); # thrsh = min (data(ind([1 end]))); # rz = roots ([pp(1:2) pp(3)-thrsh]); # width = abs (diff (rz)); width = sqrt (abs(1 / pp(1))) + xm; if ( (width > maxW || width < minW) || ... pp(1) > 0 || ... H < minH || ... data(idx(i)) < 0.99*H || ... abs (idx(i) - xm) > minD/2) idx_pruned = setdiff (idx_pruned, idx(i)); elseif (nargout > 2) struct_count++; extra.parabol(struct_count).x = ind([1 end]); extra.parabol(struct_count).pp = pp; extra.roots(struct_count,1:2)= xm + [-width width]/2; extra.height(struct_count) = H; extra.baseline(struct_count) = mean ([H minH]); endif ## debug ## set(h(2),"xdata",idx_pruned,"ydata",data(idx_pruned)) ## pause(0.2) endfor idx = idx_pruned; if (dSided) pks = __data__(idx); else pks = data(idx); endif if (transpose) pks = pks.'; idx = idx.'; endif if (nargout() > 2) varargout{1} = extra; endif endfunction %!demo %! t = 2*pi*linspace(0,1,1024)'; %! y = sin(3.14*t) + 0.5*cos(6.09*t) + 0.1*sin(10.11*t+1/6) + 0.1*sin(15.3*t+1/3); %! %! data1 = abs(y); # Positive values %! [pks idx] = findpeaks(data1); %! %! data2 = y; # Double-sided %! [pks2 idx2] = findpeaks(data2,"DoubleSided"); %! [pks3 idx3] = findpeaks(data2,"DoubleSided","MinPeakHeight",0.5); %! %! subplot(1,2,1) %! plot(t,data1,t(idx),data1(idx),'xm') %! axis tight %! subplot(1,2,2) %! plot(t,data2,t(idx2),data2(idx2),"xm;>2*std;",t(idx3),data2(idx3),"or;>0.1;") %! axis tight %! legend("Location","NorthOutside","Orientation","horizontal") %! %! #---------------------------------------------------------------------------- %! # Finding the peaks of smooth data is not a big deal! %!demo %! t = 2*pi*linspace(0,1,1024)'; %! y = sin(3.14*t) + 0.5*cos(6.09*t) + 0.1*sin(10.11*t+1/6) + 0.1*sin(15.3*t+1/3); %! %! data = abs(y + 0.1*randn(length(y),1)); # Positive values + noise %! [pks idx] = findpeaks(data,"MinPeakHeight",1); %! %! dt = t(2)-t(1); %! [pks2 idx2] = findpeaks(data,"MinPeakHeight",1,... %! "MinPeakDistance",round(0.5/dt)); %! %! subplot(1,2,1) %! plot(t,data,t(idx),data(idx),'or') %! subplot(1,2,2) %! plot(t,data,t(idx2),data(idx2),'or') %! %! #---------------------------------------------------------------------------- %! # Noisy data may need tuning of the parameters. In the 2nd example, %! # MinPeakDistance is used as a smoother of the peaks. %!assert (isempty (findpeaks ([1, 1, 1]))) %!assert (isempty (findpeaks ([1; 1; 1]))) ## Test for bug #45056 %!test %! ## Test input vector is an oversampled sinusoid with clipped peaks %! x = min (3, cos (2*pi*[0:8000] ./ 600) + 2.01); %! assert (! isempty (findpeaks (x))) ## Test for bug #63987 %!test %! x = [1 10 2 2 1 9 1]; %! [pks, loc] = findpeaks(x); %! assert (loc, [2 6]) %! assert (pks, [10 9]) %% Test input validation %!error findpeaks () %!error findpeaks (1) %!error findpeaks ([1, 2]) ## Test Matlab compatibility %!test assert (findpeaks ([34 134 353 64 134 14 56 67 234 143 64 575 8657]), %! [353 134 234]) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/fir1.m����������������������������������������������������������������������������0000644�0000000�0000000�00000015553�14673270174�011745� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{b} =} fir1 (@var{n}, @var{w}) ## @deftypefnx {Function File} {@var{b} =} fir1 (@var{n}, @var{w}, @var{type}) ## @deftypefnx {Function File} {@var{b} =} fir1 (@var{n}, @var{w}, @var{type}, @var{window}) ## @deftypefnx {Function File} {@var{b} =} fir1 (@var{n}, @var{w}, @var{type}, @var{window}, @var{noscale}) ## ## Produce an order @var{n} FIR filter with the given frequency cutoff @var{w}, ## returning the @var{n}+1 filter coefficients in @var{b}. If @var{w} is a ## scalar, it specifies the frequency cutoff for a lowpass or highpass filter. ## If @var{w} is a two-element vector, the two values specify the edges of a ## bandpass or bandstop filter. If @var{w} is an N-element vector, each ## value specifies a band edge of a multiband pass/stop filter. ## ## The filter @var{type} can be specified with one of the following strings: ## "low", "high", "stop", "pass", "bandpass", "DC-0", or "DC-1". The default ## is "low" is @var{w} is a scalar, "pass" if @var{w} is a pair, or "DC-0" if ## @var{w} is a vector with more than 2 elements. ## ## An optional shaping @var{window} can be given as a vector with length ## @var{n}+1. If not specified, a Hamming window of length @var{n}+1 is used. ## ## With the option "noscale", the filter coefficients are not normalized. The ## default is to normalize the filter such that the magnitude response of the ## center of the first passband is 1. ## ## To apply the filter, use the return vector @var{b} with the @code{filter} ## function, for example @code{y = filter (b, 1, x)}. ## ## Examples: ## @example ## freqz (fir1 (40, 0.3)); ## freqz (fir1 (15, [0.2, 0.5], "stop")); # note the zero-crossing at 0.1 ## freqz (fir1 (15, [0.2, 0.5], "stop", "noscale")); ## @end example ## @seealso{filter, fir2} ## @end deftypefn ## FIXME: Consider using exact expression (in terms of sinc) for the ## impulse response rather than relying on fir2. ## FIXME: Find reference to the requirement that order be even for ## filters that end high. Figure out what to do with the ## window in these cases function b = fir1(n, w, varargin) if nargin < 2 || nargin > 5 print_usage; endif ## Assign default window, filter type and scale. ## If single band edge, the first band defaults to a pass band to ## create a lowpass filter. If multiple band edges, the first band ## defaults to a stop band so that the two band case defaults to a ## band pass filter. Ick. window = []; scale = 1; ftype = (length(w)==1); ## sort arglist, normalize any string for i=1:length(varargin) arg = varargin{i}; if ischar(arg), arg=lower(arg);endif if isempty(arg) continue; endif # octave bug---can't switch on [] switch arg case {'low','stop','dc-1'}, ftype = 1; case {'high','pass','bandpass','dc-0'}, ftype = 0; case {'scale'}, scale = 1; case {'noscale'}, scale = 0; otherwise window = arg; endswitch endfor ## build response function according to fir2 requirements bands = length(w)+1; f = zeros(1,2*bands); f(1) = 0; f(2*bands)=1; f(2:2:2*bands-1) = w; f(3:2:2*bands-1) = w; m = zeros(1,2*bands); m(1:2:2*bands) = rem([1:bands]-(1-ftype),2); m(2:2:2*bands) = m(1:2:2*bands); ## Increment the order if the final band is a pass band. Something ## about having a nyquist frequency of zero causing problems. if rem(n,2)==1 && m(2*bands)==1, warning("n must be even for highpass and bandstop filters. Incrementing."); n = n+1; if isvector(window) && isreal(window) && !ischar(window) ## Extend the window using interpolation M = length(window); if M == 1, window = [window; window]; elseif M < 4 window = interp1(linspace(0,1,M),window,linspace(0,1,M+1),'linear'); else window = interp1(linspace(0,1,M),window,linspace(0,1,M+1),'spline'); endif endif endif ## compute the filter b = fir2(n, f, m, [], 2, window); ## normalize filter magnitude if scale == 1 ## find the middle of the first band edge ## find the frequency of the normalizing gain if m(1) == 1 ## if the first band is a passband, use DC gain w_o = 0; elseif f(4) == 1 ## for a highpass filter, ## use the gain at half the sample frequency w_o = 1; else ## otherwise, use the gain at the center ## frequency of the first passband w_o = f(3) + (f(4)-f(3))/2; endif ## compute |h(w_o)|^-1 renorm = 1/abs(polyval(b, exp(-1i*pi*w_o))); ## normalize the filter b = renorm*b; endif endfunction %!demo %! freqz(fir1(40,0.3)); %!demo %! freqz(fir1(15,[0.2, 0.5], 'stop')); # note the zero-crossing at 0.1 %!demo %! freqz(fir1(15,[0.2, 0.5], 'stop', 'noscale')); %!assert(fir1(2, .5, 'low', @hanning, 'scale'), [0 1 0]); %!assert(fir1(2, .5, 'low', "hanning", 'scale'), [0 1 0]); %!assert(fir1(2, .5, 'low', hanning(3), 'scale'), [0 1 0]); %!assert(fir1(10,.5,'noscale'), fir1(10,.5,'low','hamming','noscale')); %!assert(fir1(10,.5,'high'), fir1(10,.5,'high','hamming','scale')); %!assert(fir1(10,.5,'boxcar'), fir1(10,.5,'low','boxcar','scale')); %!assert(fir1(10,.5,'hanning','scale'), fir1(10,.5,'scale','hanning','low')); %!assert(fir1(10,.5,'haNNing','NOscale'), fir1(10,.5,'noscale','Hanning','LOW')); %!assert(fir1(10,.5,'boxcar',[]), fir1(10,.5,'boxcar')); %% Test expected magnitudes of passbands, stopbands, and cutoff frequencies %!test %! b = fir1 (30, 0.3); %! h = abs (freqz (b, 1, [0, 0.3, 1], 2)); %! assert (h(1), 1, 1e-3) %! assert (all (h(2:3) <= [1/sqrt(2), 3e-3])) %!test %! b = fir1 (30, 0.7, "high"); %! h = abs (freqz (b, 1, [0, 0.7, 1], 2)); %! assert (h(3), 1, 1e-3) %! assert (all (h(1:2) <= [3e-3, 1/sqrt(2)])) %!test %! b = fir1 (30, [0.3, 0.7]); %! h = abs (freqz (b, 1, [0, 0.3, 0.5, 0.7, 1], 2)); %! assert (h(3), 1, 1e-3) %! assert (all (h([1:2, 4:5]) <= [3e-3, 1/sqrt(2), 1/sqrt(2), 3e-3])) %!test %! b = fir1 (50, [0.3, 0.7], "stop"); %! h = abs (freqz (b, 1, [0, 0.3, 0.5, 0.7, 1], 2)); %! assert (h(1), 1, 1e-3) %! assert (h(5), 1, 1e-3) %! assert (all (h(2:4) <= [1/sqrt(2), 3e-3, 1/sqrt(2)])) �����������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/fir2.m����������������������������������������������������������������������������0000644�0000000�0000000�00000021626�14673270174�011744� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{b} =} fir2 (@var{n}, @var{f}, @var{m}) ## @deftypefnx {Function File} {@var{b} =} fir2 (@var{n}, @var{f}, @var{m}, @var{grid_n}) ## @deftypefnx {Function File} {@var{b} =} fir2 (@var{n}, @var{f}, @var{m}, @var{grid_n}, @var{ramp_n}) ## @deftypefnx {Function File} {@var{b} =} fir2 (@var{n}, @var{f}, @var{m}, @var{grid_n}, @var{ramp_n}, @var{window}) ## ## Produce an order @var{n} FIR filter with arbitrary frequency response ## @var{m} over frequency bands @var{f}, returning the @var{n}+1 filter ## coefficients in @var{b}. The vector @var{f} specifies the frequency band ## edges of the filter response and @var{m} specifies the magnitude response ## at each frequency. ## ## The vector @var{f} must be nondecreasing over the range [0,1], and the ## first and last elements must be 0 and 1, respectively. A discontinuous ## jump in the frequency response can be specified by duplicating a band edge ## in @var{f} with different values in @var{m}. ## ## The resolution over which the frequency response is evaluated can be ## controlled with the @var{grid_n} argument. The default is 512 or the ## next larger power of 2 greater than the filter length. ## ## The band transition width for discontinuities can be controlled with the ## @var{ramp_n} argument. The default is @var{grid_n}/25. Larger values ## will result in wider band transitions but better stopband rejection. ## ## An optional shaping @var{window} can be given as a vector with length ## @var{n}+1. If not specified, a Hamming window of length @var{n}+1 is used. ## ## To apply the filter, use the return vector @var{b} with the @code{filter} ## function, for example @code{y = filter (b, 1, x)}. ## ## Example: ## @example ## f = [0, 0.3, 0.3, 0.6, 0.6, 1]; m = [0, 0, 1, 1/2, 0, 0]; ## [h, w] = freqz (fir2 (100, f, m)); ## plot (f, m, ";target response;", w/pi, abs (h), ";filter response;"); ## @end example ## @seealso{filter, fir1} ## @end deftypefn function b = fir2(n, f, m, grid_n, ramp_n, window) if nargin < 3 || nargin > 6 print_usage; endif ## verify frequency and magnitude vectors are reasonable t = length(f); if t<2 || f(1)!=0 || f(t)!=1 || any(diff(f)<0) error ("fir2: frequency must be nondecreasing starting from 0 and ending at 1"); elseif t != length(m) error ("fir2: frequency and magnitude vectors must be the same length"); ## find the grid spacing and ramp width elseif (nargin>4 && length(grid_n)>1) || ... (nargin>5 && (length(grid_n)>1 || length(ramp_n)>1)) error ("fir2: grid_n and ramp_n must be integers"); endif if nargin < 4, grid_n=[]; endif if nargin < 5, ramp_n=[]; endif if (! (isscalar (n) && (n == fix (n)) && (n >= 0))) error ("fir2: n must be a non negative integer"); else # ensure n is used as a double type n = double(n); endif ## find the window parameter, or default to hamming w=[]; if length(grid_n)>1, w=grid_n; grid_n=[]; endif if length(ramp_n)>1, w=ramp_n; ramp_n=[]; endif if nargin < 6, window=w; endif if isempty(window), window=hamming(n+1); endif if !isreal(window) || ischar(window), window=feval(window, n+1); endif if length(window) != n+1, error ("fir2: window must be of length n+1"); endif ## Default grid size is 512... unless n+1 >= 1024 if isempty (grid_n) if n+1 < 1024 grid_n = 512; else grid_n = n+1; endif endif ## ML behavior appears to always round the grid size up to a power of 2 grid_n = 2 ^ nextpow2 (grid_n); ## Error out if the grid size is not big enough for the window if 2*grid_n < n+1 error ("fir2: grid size must be greater than half the filter order"); endif if isempty (ramp_n), ramp_n = fix (grid_n / 25); endif ## Apply ramps to discontinuities if (ramp_n > 0) ## remember original frequency points prior to applying ramps basef = f(:); basem = m(:); ## separate identical frequencies, but keep the midpoint idx = find (diff(f) == 0); f(idx) = f(idx) - ramp_n/grid_n/2; f(idx+1) = f(idx+1) + ramp_n/grid_n/2; f = [f(:);basef(idx)]'; ## make sure the grid points stay monotonic in [0,1] f(f<0) = 0; f(f>1) = 1; f = unique([f(:);basef(idx)(:)]'); ## preserve window shape even though f may have changed m = interp1(basef, basem, f); ## axis([-.1 1.1 -.1 1.1]) ## plot(f,m,'-xb;ramped;',basef,basem,'-or;original;'); pause; endif ## interpolate between grid points grid = interp1(f,m,linspace(0,1,grid_n+1)'); ## hold on; plot(linspace(0,1,grid_n+1),grid,'-+g;grid;'); hold off; pause; ## Transform frequency response into time response and ## center the response about n/2, truncating the excess if (rem(n,2) == 0) b = ifft([grid ; grid(grid_n:-1:2)]); mid = (n+1)/2; b = real ([ b([end-floor(mid)+1:end]) ; b(1:ceil(mid)) ]); else ## Add zeros to interpolate by 2, then pick the odd values below. b = ifft([grid ; zeros(grid_n*2,1) ;grid(grid_n:-1:2)]); b = 2 * real([ b([end-n+1:2:end]) ; b(2:2:(n+1))]); endif ## Multiplication in the time domain is convolution in frequency, ## so multiply by our window now to smooth the frequency response. ## Also, for matlab compatibility, we return return values in 1 row b = b(:)' .* window(:)'; endfunction %% Test that the grid size is rounded up to the next power of 2 %% FIXME: test fails randomly on i386 %!xtest %! f = [0 0.6 0.6 1]; m = [1 1 0 0]; %! b9 = fir2 (30, f, m, 9); %! b16 = fir2 (30, f, m, 16); %! b17 = fir2 (30, f, m, 17); %! b32 = fir2 (30, f, m, 32); %! assert ( isequal (b9, b16)) %! assert ( isequal (b17, b32)) %! assert (~isequal (b16, b17)) %% Test expected magnitudes of passbands, stopbands, and cutoff frequencies %!test %! f = [0, 0.7, 0.7, 1]; m = [0, 0, 1, 1]; %! b = fir2 (50, f, m); %! h = abs (freqz (b, 1, [0, 0.7, 1], 2)); %! assert (h(1) <= 3e-3) %! assert (h(2) <= 1/sqrt (2)) %! assert (h(3), 1, 2e-3) %!test %! f = [0, 0.25, 0.25, 0.75, 0.75, 1]; m = [0, 0, 1, 1, 0, 0]; %! b = fir2 (50, f, m); %! h = abs (freqz (b, 1, [0, 0.25, 0.5, 0.75, 1], 2)); %! assert (h(1) <= 3e-3) %! assert (h(2) <= 1/sqrt (2)) %! assert (h(3), 1, 2e-3) %! assert (h(4) <= 1/sqrt (2)) %! assert (h(5) <= 3e-3) %!test %! f = [0, 0.45, 0.45, 0.55, 0.55, 1]; m = [1, 1, 0, 0, 1, 1]; %! b = fir2 (50, f, m); %! h = abs (freqz (b, 1, [0, 0.45, 0.5, 0.55, 1], 2)); %! assert (h(1), 1, 2e-3) %! assert (h(2) <= 1/sqrt (2)) %! assert (h(3) <= 1e-1) %! assert (h(4) <= 1/sqrt (2)) %! assert (h(5), 1, 2e-3) %!test #bug 59066 %! f = [0, 0.45, 0.45, 0.55, 0.55, 1]; m = [1, 1, 0, 0, 1, 1]; %! b = fir2 (int32(50), f, m); %! assert(numel(b), 51) %! %! fail ("fir2 (50.1, f, m)", "fir2: n must be a non negative integer") %! fail ("fir2 (-1, f, m)", "fir2: n must be a non negative integer") %!demo %! f=[0, 0.3, 0.3, 0.6, 0.6, 1]; m=[0, 0, 1, 1/2, 0, 0]; %! [h, w] = freqz(fir2(100,f,m)); %! subplot(121); %! plot(f,m,';target response;',w/pi,abs(h),';filter response;'); %! subplot(122); %! plot(f,20*log10(m+1e-5),';target response (dB);',... %! w/pi,20*log10(abs(h)),';filter response (dB);'); %!demo %! f=[0, 0.3, 0.3, 0.6, 0.6, 1]; m=[0, 0, 1, 1/2, 0, 0]; %! plot(f,20*log10(m+1e-5),';target response;'); %! hold on; %! [h, w] = freqz(fir2(50,f,m,512,0)); %! plot(w/pi,20*log10(abs(h)),';filter response (ramp=0);'); %! [h, w] = freqz(fir2(50,f,m,512,25.6)); %! plot(w/pi,20*log10(abs(h)),';filter response (ramp=pi/20 rad);'); %! [h, w] = freqz(fir2(50,f,m,512,51.2)); %! plot(w/pi,20*log10(abs(h)),';filter response (ramp=pi/10 rad);'); %! hold off; %!demo %! % Classical Jakes spectrum %! % X represents the normalized frequency from 0 %! % to the maximum Doppler frequency %! asymptote = 2/3; %! X = linspace(0,asymptote-0.0001,200); %! Y = (1 - (X./asymptote).^2).^(-1/4); %! %! % The target frequency response is 0 after the asymptote %! X = [X, asymptote, 1]; %! Y = [Y, 0, 0]; %! %! plot(X,Y,'b;Target spectrum;'); %! hold on; %! [H,F]=freqz(fir2(20, X, Y)); %! plot(F/pi,abs(H),'c;Synthesized spectrum (n=20);'); %! [H,F]=freqz(fir2(50, X, Y)); %! plot(F/pi,abs(H),'r;Synthesized spectrum (n=50);'); %! [H,F]=freqz(fir2(200, X, Y)); %! plot(F/pi,abs(H),'g;Synthesized spectrum (n=200);'); %! hold off; %! title('Theoretical/Synthesized CLASS spectrum'); %! xlabel('Normalized frequency (Fs=2)'); %! ylabel('Magnitude'); ����������������������������������������������������������������������������������������������������������signal-1.4.6/inst/firls.m���������������������������������������������������������������������������0000644�0000000�0000000�00000010522�14673270174�012212� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Quentin Spencer <qspencer@ieee.org> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{b} =} firls (@var{n}, @var{f}, @var{a}) ## @deftypefnx {Function File} {@var{b} =} firls (@var{n}, @var{f}, @var{a}, @var{w}) ## ## FIR filter design using least squares method. Returns a length @var{n}+1 ## linear phase filter such that the integral of the weighted mean ## squared error in the specified bands is minimized. ## ## The vector @var{f} specifies the frequencies of the band edges, normalized ## so that half the sample frequency is equal to 1. Each band is specified by ## two frequencies, to the vector must have an even length. ## ## The vector @var{a} specifies the amplitude of the desired response at each ## band edge. ## ## The optional argument @var{w} is a weighting function that contains one ## value for each band that weights the mean squared error in that band. ## ## @var{a} must be the same length as @var{f}, and @var{w} must be half the ## length of @var{f}. @var{n} must be even. If given an odd value, ## @code{firls} increments it by 1. ## ## The least squares optimization algorithm for computing FIR filter ## coefficients is derived in detail in: ## ## I. Selesnick, "Linear-Phase FIR Filter Design by Least Squares," ## http://cnx.org/content/m10577 ## @end deftypefn function coef = firls(N, frequencies, pass, weight, str); if (nargin < 3 || nargin > 6) print_usage; elseif (nargin == 3) weight = ones (1, length(pass)/2); str = []; elseif (nargin == 4) if ischar (weight) str = weight; weight = ones (size (pass)); else str = []; endif endif if length (frequencies) ~= length (pass) error("F and A must have equal lengths."); elseif 2 * length (weight) ~= length (pass) error("W must contain one weight per band."); elseif ischar (str) error("This feature is implemented yet"); else N += mod (N, 2); M = N/2; w = kron (weight(:), [-1; 1]); omega = frequencies * pi; i1 = 1:2:length (omega); i2 = 2:2:length (omega); ## Generate the matrix Q ## As illustrated in the above-cited reference, the matrix can be ## expressed as the sum of a Hankel and Toeplitz matrix. A factor of ## 1/2 has been dropped and the final filter coefficients multiplied ## by 2 to compensate. cos_ints = [omega; sin((1:N)' * omega)]; q = [1, 1./(1:N)]' .* (cos_ints * w); Q = toeplitz (q(1:M+1)) + hankel (q(1:M+1), q(M+1:end)); ## The vector b is derived from solving the integral: ## ## _ w ## / 2 ## b = / W(w) D(w) cos(kw) dw ## k / w ## - 1 ## ## Since we assume that W(w) is constant over each band (if not, the ## computation of Q above would be considerably more complex), but ## D(w) is allowed to be a linear function, in general the function ## W(w) D(w) is linear. The computations below are derived from the ## fact that: ## _ ## / a ax + b ## / (ax + b) cos(nx) dx = --- cos (nx) + ------ sin(nx) ## / 2 n ## - n ## cos_ints2 = [omega(i1).^2 - omega(i2).^2; ... cos((1:M)' * omega(i2)) - cos((1:M)' * omega(i1))] ./ ... ([2, 1:M]' * (omega(i2) - omega(i1))); d = [-weight .* pass(i1); weight .* pass(i2)] (:); b = [1, 1./(1:M)]' .* ((kron (cos_ints2, [1, 1]) + cos_ints(1:M+1,:)) * d); ## Having computed the components Q and b of the matrix equation, ## solve for the filter coefficients. a = Q \ b; coef = [ a(end:-1:2); 2 * a(1); a(2:end) ]; endif endfunction ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/firpmord.m������������������������������������������������������������������������0000644�0000000�0000000�00000036156�14673270174�012730� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2015 The Octave Project Developers ## ## See the file COPYRIGHT.md in the top-level directory of this ## distribution or <https://octave.org/copyright/>. ## ## This file is part of Octave. ## ## Octave 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. ## ## Octave 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 Octave; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{n}, @var{Fout}, @var{a}, @var{w}] =} firpmord (@var{f}, @var{a}, @var{d}) ## @deftypefnx {Function File} {[@var{n}, @var{Fout}, @var{a}, @var{w}] =} firpmord (@var{f}, @var{a}, @var{d}, @var{fs}) ## @deftypefnx {Function File} {@var{c} =} firpmord (@var{f}, @var{a}, @var{d}, "cell") ## @deftypefnx {Function File} {@var{c} =} firpmord (@var{f}, @var{a}, @var{d}, @var{fs}, "cell") ## @cindex signal processing ## ## Estimate the filter-order needed for @code{firpm} to design a type-I or ## type-II linear-phase FIR filter according to the given specifications. ## ## @heading Arguments ## ## @table @var ## ## @item f ## A vector of real-numbers, increasing in the range (0, @var{fs}/2), giving the ## frequencies of the left and right edges of each band for which a specific ## amplitude response is desired (omitting 0 and @var{fs}/2, which are implied): ## [r1 l2 r2 @dots{}]. Transition-bands are defined implicitly as the regions ## between the given bands. ## ## @item a ## A vector of real-numbers giving the ideal amplitude response. An amplitude ## value is given for each band specified by @var{f}: [a1 a2 @dots{}]. 1 ## represents unity-gain, 0 represents infinite attenuation, and @minus{}1 ## represents a phase change of pi radians. ## ## @item d ## A vector of positive real-numbers giving the maximum allowable linear ## deviation from the amplitudes given in @var{a}, thus constraining the actual ## amplitude response (where defined by @var{f}) to be within @var{a} +/@minus{} ## @var{d}. Note that, though related, @var{d} does not equate to ## @code{firpm}'s @var{w} argument. ## ## @item fs ## ## The sampling-frequency, which defaults to 2. ## ## @end table ## ## @heading Usage ## ## The function returns the estimated filter-order, together with the other ## design specification values, in one of two forms suitable for use with ## @code{firpm}. By default, multiple return values are used; alternatively, by ## giving @qcode{"cell"} (or @qcode{"c"}) as the last argument to @code{firpmord}, ## the returned values are contained within a cell-array that can, if desired, ## be passed directly to @code{firpm}. ## ## The following examples illustrate the use of both mechanisms, as well as ## aspects of @code{firpmord} usage in general: ## ## @example ## @group ## # Low-pass; frequencies in kHz: ## [n f a w] = firpmord ([2.5 3], [1 0], [0.01 db2mag(-60)], 8); ## b = firpm (n, f, a, w); ## @end group ## @end example ## ## @example ## @group ## # Band-pass: ## c = firpmord ([3 4 8 9], [0 1 0], [1e-3 1e-2 1e-3], 20, "cell"); ## b = firpm (c@{:@}); ## @end group ## @end example ## ## @example ## @group ## # High-pass: ## b = firpm (firpmord ([6.4 8]/16, [0 1], [1e-4 0.01], "c")@{:@}); ## @end group ## @end example ## ## In cases where elements of @var{d} follow a repeating pattern (e.g.@: all the ## elements are equal, or elements corresponding to pass-bands are equal and ## elements corresponding to stop-bands are equal), only as many elements as are ## needed to establish the pattern need be given. ## ## For example, the following @code{firpmord} invocation pairs are equivalent: ## ## @example ## @group ## # Low-pass: ## firpmord ([0.4 0.5], [0 1], [db2mag(-72) db2mag(-72)]); ## firpmord ([0.4 0.5], [0 1], [db2mag(-72)]); ## @end group ## @end example ## ## @example ## @group ## # Multi-band-pass: ## ds = db2mag(-80); dp = 0.01; ## firpmord ([1 2 3 4 5 6 7 8]/10, [0 1 0 1 0], [ds dp ds dp ds]); ## firpmord ([1 2 3 4 5 6 7 8]/10, [0 1 0 1 0], [ds dp]); ## @end group ## @end example ## ## @heading Notes ## ## The estimation algorithm used is per Ichige et al.@footnote{ K. Ichige, M. ## Iwaki, algorithm and R. Ishii, `Accurate Estimation of Minimum Filter Length ## for Optimum FIR Digital Filters', IEEE Transactions on Circuits and Systems, ## Vol.@: 47, No.@: 10, 2000, pp.@: 1008--1017} Accuracy tends to decrease as ## the number of bands increases. Even with two bands (i.e.@: high-pass or ## low-pass), the algorithm may under- or over-estimate. See the ## @code{firpmord} demonstrations for some examples. ## ## In order to precisely determine the minimum order needed for a particular ## design, @code{firpmord} could be used to seed an algorithm iterating ## invocations of @code{firpm} (as exemplified in demonstration number five). ## ## @heading Related documentation ## ## @seealso{firpm, kaiserord} ## ## @end deftypefn function [N, Fout, A, W] = firpmord (F, A, D, Fs = 2, cell) len = @(x) length (x); cell_given = nargin > 4; if (ischar (Fs) && nargin == 4) cell = Fs; Fs = 2; cell_given = 1; endif return_as_cell = ischar (cell) && strncmpi (cell, "cell", numel (cell)); Fs = real (Fs); if nargin < 3 || nargin > 5 || (!return_as_cell && cell_given) print_usage; elseif (! (isscalar (Fs) && Fs > 0)) error ("firpmord parameter Fs (sampling-frequency) must be a positive \ number"); endif F = real (F(:)) / Fs; A = real (A(:)); D = real (D(:)); if (any (F <= 0) || any (F >= .5) || any ([F; 1] - [0; F] <= 0)) error ("firpmord parameter F (band-edge frequencies) elements must \ increase between 0 and Fs/2") elseif (len (F) == 0 || len (F) != 2 * len (A) - 2) error ("firpmord parameter F (band-edge frequencies) length must be twice \ the length of A, less 2") elseif (len (D) < 1 || len (D) > len (A) || any (D <= 0)) error ("firpmord parameter D (deviations) must be a vector of positive \ numbers, its length not exceeding that of A") endif ## The following step could also be done for D, but the concision gain ## is not as compelling, and would result in the loss of the useful ## cross-check between the lengths of F and D. ## ## Repeat (as necessary) elements of A to obtain 1 element/band: l=1; for k=len (D)+1:len (A) D(k,1) = D(l++); endfor ## Scale D w.r.t. A: D ./= abs (A) + (A==0); ## Find the longest length needed to implement any of the ## low-pass or high-pass transitions within the given edges. ## HP transitions are mirrored in [0,.5] then treated as LP: Fl = F(1:2:(len (F) - 1)); # Freqs at left of transition. Fr = F(2:2:(len (F) - 0)); # Freqs at right of transition. L = 2; # Anything less is not a filter. for k=1:len (Fl) # (Fl, Fr have equal length.) if (A(k) > A(k+1)) # Low-pass transition? L = max (L, estimate_lp (Fl(k), Fr(k), D(k), D(k+1))); elseif (A(k) < A(k+1)) # High-pass transition? L = max (L, estimate_lp (.5-Fr(k), .5-Fl(k), D(k+1), D(k))); endif endfor ## Format length & specs for firpm: Fout = [0; F*2; 1]; W = max (D) ./ D; N = ceil (L) - 1; # Filter order. N += A(end) != 0 && rem (N, 2); # Fix-up high-pass/band-stop. A = kron(A, [1;1]); if (nargout < 2 && return_as_cell) N = {N, Fout, A, W}; endif endfunction ## Estimate filter-length needed for LP transition (Ichige, 2000): function L = estimate_lp (fp, fs, dp, ds) dF = fs-fp; assert (dF > 0) # Ichige eqn.# v = @(d) 2.325 * (-log10 (d))^-.445 * dF^-1.39; # (10) g = @(fp,d) 2/pi * atan (v(d) * (1/fp - 1/(.5-dF))); # (9) h = @(fp,c) 2/pi * atan (c/dF * (1/fp - 1/(.5-dF))); # (15) Nc = ceil (1.101 * (-log10 (2*dp))^1.1 / dF + 1); # (8) ... N3 = ceil (Nc * (g(fp, dp) + g(.5-fs, dp) + 1)/3); # (11) Nm = .52 * log10 (dp/ds) / dF * (-log10 (dp))^.17; # (15) DN = ceil (Nm * (h(fp, 1.1) - (h(.5-fs, .29) - 1)/2)); # (15) L = N3 + DN; # (15) endfunction ## Invocation tests: %!error <firpmord parameter Fs \(sampling-frequency\) must be a positive number> firpmord ([1 2], [1 0], [1 1], [1 1]); %!error <firpmord parameter F \(band-edge frequencies\) elements must increase between 0 and Fs/2> firpmord ([0 2], [1 0], [1 1]); %!error <firpmord parameter F \(band-edge frequencies\) elements must increase between 0 and Fs/2> firpmord ([.1 1], [1 0], [1 1]); %!error <firpmord parameter F \(band-edge frequencies\) length must be twice the length of A, less 2> firpmord ([.1 .9], [1], [.1 .1]); %!error <firpmord parameter D \(deviations\) must be a vector of positive numbers, its length not exceeding that of A> firpmord ([.1 .2], [1 0], [.1 .1 .1]); %!error <firpmord parameter D \(deviations\) must be a vector of positive numbers, its length not exceeding that of A> firpmord ([.1 .2], [1 0], [1 0]); %!assert ( %! firpmord ([0.4 0.5], [0 1], [2.5e-4 2.5e-4]), %! firpmord ([0.4 0.5], [0 1], [2.5e-4])) %!test ds = 1e-4; dp = 0.01; assert ( %! firpmord ([1 2 3 4 5 6 7 8]/10, [0 1 0 1 0], [ds dp ds dp ds]), %! firpmord ([1 2 3 4 5 6 7 8]/10, [0 1 0 1 0], [ds dp])) ## Tests using examples from the Ichige paper, tables II & III. ## There are some slight discrepancies; the reason is unknown: %!assert (1 + firpmord ([.1 .2], [0 1], [1e-4 .01], 1), 33) %!assert (1 + firpmord ([ 15 20], [ 1 0], [ .1 .001], 100), 38) %!assert (1 + firpmord ([ 8 10 ], [0 1 ], [.001 .1 ], 100), 91) %!assert (1 + firpmord ([ 8 10 15 20], [0 1 0], [.001 .1 .001], 100), 90) #+1? %!assert (1 + firpmord ([17 20 ], [1 0 ], [.01 1e-4 ], 100), 107)#-1? %!assert (1 + firpmord ([ 22 25], [ 0 1], [ 1e-4 .01], 100), 107) %!assert (1 + firpmord ([17 20 22 25], [1 0 1], [.01 1e-4 .01], 100), 107) %!assert (1 + firpmord ([ 21 25], [ 1 0], [ .01 1e-4], 100), 81) #+1? %!assert (1 + firpmord ([10 20 ], [0 1 ], [1e-4 .01 ], 100), 33) %!assert (1 + firpmord ([10 20 21 25], [0 1 0], [1e-4 .01 1e-4], 100), 81) #+1? %!assert (1 + firpmord ([20 25 ], [1 0 ], [.01 1e-4 ], 100), 65) #+1? %!assert (1 + firpmord ([ 26 30], [ 0 1], [ 1e-4 .01], 100), 81) #+2? %!assert (1 + firpmord ([20 25 26 30], [1 0 1], [.01 1e-4 .01], 100), 81) #+2? ## Demonstrations: %! %!demo %! %! db2mag = @(x) 10^(x/20); %! %! fs = 8000; %! [n f a w] = firpmord ([2500 3000], [1 0], [0.01 db2mag(-60)], fs); %! b = firpm (n, f, a, w); %! %! [h f] = freqz (b, 1, 2^14); clf %! plot (fs/2*f/pi, 20*log10 (abs (h))); grid on; axis ([0 fs/2 -90 5]) %! ylabel ("Magnitude (dB)"); xlabel ("Frequency (Hz)") %! title (sprintf ("Response analysis of firpmord / firpm low-pass filter design (order=%i)", length (b) - 1)) %! axes ("position", [.24 .4 .4 .3]) %! plot (fs/2*f/pi, abs (h)); grid on; axis ([0 2600 x=.987 2-x]) %! ylabel ("Magnitude") %! title ("Pass-band detail") %! %-------------------------------------------------- %! % Figure shows analysis of filter designed using %! % firpm with firpmord; specs. are almost met. %! %!demo %! %! db2mag = @(x) 10^(x/20); %! %! b = firpm (firpmord ([0.3 0.4], [0 1], [db2mag(-80) .01], "c"){:}); %! %! [h f] = freqz (b, 1, 2^14); clf %! plot (f/pi, 20*log10 (abs (h))); grid on; axis ([0 1 -110 5]) %! ylabel ("Magnitude (dB)"); xlabel ("Frequency (normalized)") %! title (sprintf ("Response analysis of firpmord / firpm high-pass filter design (order=%i)", length (b) - 1)) %! axes ("position", [.52 .4 .35 .3]) %! plot (f/pi, abs (h)); grid on; axis ([.39 1 x=.987 2-x]) %! ylabel ("Magnitude") %! title ("Pass-band detail") %! %-------------------------------------------------- %! % Figure shows analysis of filter designed using %! % firpm with firpmord; specs. are exceeded. %! %!demo %! %! db2mag = @(x) 10^(x/20); %! %! ds = db2mag (-80); dp = 0.01; %! b = firpm (firpmord ([1 2 3 4 5 6 7 8]/10, [0 1 0 1 0], [ds dp], "c"){:}); %! %! [h f] = freqz (b, 1, 2^14); clf %! plot (f/pi, 20*log10 (abs (h))); grid on; axis ([0 1 -110 5]) %! ylabel ("Magnitude (dB)"); xlabel ("Frequency (normalized)") %! title ("Response analysis of firpmord / firpm multi-band-pass filter design") %! title (sprintf ("Response analysis of firpmord / firpm multi-band-pass filter design (order=%i)", length (b) - 1)) %! axes ("position", [.38 .5 .5 .2]) %! plot (f/pi, abs (h)); grid on; axis ([.11 .79 x=.986 2-x]) %! ylabel ("Magnitude") %! title ("Pass-bands detail") %! %-------------------------------------------------- %! % Figure shows analysis of filter designed using %! % firpm with firpmord; specs. are met. %! %!demo %! %! db2mag = @(x) 10^(x/20); %! %! ds = db2mag (-40); dp = 1 - db2mag (-0.1); %! b = firpm (firpmord ([2 3 8 9]/32, [0 1 0], [ds dp], "c"){:}); %! %! [h f] = freqz (b, 1, 2^14); clf %! plot (f/pi, 20*log10 (abs (h))); grid on; axis ([0 1 -50 3]) %! ylabel ("Magnitude (dB)"); xlabel ("Frequency (normalized)") %! title (sprintf ("Response analysis of firpmord / firpm band-pass filter design (order=%i)", length (b) - 1)) %! axes ("position", [.45 .5 .4 .3]) %! plot (f/pi, 20*log10 (abs (h))); grid on; axis ([.08 .26 x=-.13 -x]) %! ylabel ("Magnitude (dB)") %! title ("Pass-band detail") %! %-------------------------------------------------- %! % Figure shows analysis of filter designed using %! % firpm with firpmord; specs. are not met. %! %!demo %! %! % FIRPMX: F, A, D, Fs are as firpmord. %! % type in {0,1,2} constrains order to be {even,odd,either} resp. %! %! function h = firpmx (type, F, A, D, Fs = 2) %! type *= !A(end); step = 2; bounds = [0 0]; %! while (bounds(2) - bounds(1) != step) %! if all (!bounds) [n f a w] = firpmord (F, A, D, Fs); %! elseif (!bounds(1)) n = min (n - step, round (n * 0.994)); %! elseif (!bounds(2)) n = max (n + step, round (n / 0.998)); %! else n = fix (mean (bounds)); %! endif %! n += rem (n + rem (type, 2), step); %! [b m] = firpm (n, f, a, w); %! bounds(1 + (met = (abs(m) <= max (D)))) = n; %! step -= bounds(2) - bounds(1) == type; %! if (met) h = b; endif %! endwhile %! endfunction %! %! db2mag = @(x) 10^(x/20); %! %! ds = db2mag (-40); dp = 1 - db2mag (-0.1); %! b = firpmx (2, [2 3 8 9]/32, [0 1 0], [ds dp]); %! %! [h f] = freqz (b, 1, 2^14); clf %! plot (f/pi, 20*log10 (abs (h))); grid on; axis ([0 1 -50 3]) %! ylabel ("Magnitude (dB)"); xlabel ("Frequency (normalized)") %! title (sprintf ("Response analysis of firpmord / iterative-firpm band-pass filter design (order=%i)", length (b) - 1)) %! axes ("position", [.45 .5 .4 .3]) %! plot (f/pi, 20*log10 (abs (h))); grid on; axis ([.08 .26 x=-.13 -x]) %! ylabel ("Magnitude (dB)") %! title ("Pass-band detail") %! %-------------------------------------------------- %! % Figure shows analysis of filter designed iteratively %! % using firpm with firpmord, so that specs. are met. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/flattopwin.m����������������������������������������������������������������������0000644�0000000�0000000�00000004454�14673270174�013271� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Author: Paul Kienzle <pkienzle@users.sf.net> (2004) ## This program is granted to the public domain. ## -*- texinfo -*- ## @deftypefn {Function File} {} flattopwin (@var{m}) ## @deftypefnx {Function File} {} flattopwin (@var{m}, "periodic") ## @deftypefnx {Function File} {} flattopwin (@var{m}, "symmetric") ## ## Return the filter coefficients of a Flat Top window of length @var{m}. ## The Flat Top window is defined by the function f(w): ## ## @example ## @group ## f(w) = 1 - 1.93 cos(2 pi w) + 1.29 cos(4 pi w) ## - 0.388 cos(6 pi w) + 0.0322cos(8 pi w) ## @end group ## @end example ## ## where w = i/(m-1) for i=0:m-1 for a symmetric window, or ## w = i/m for i=0:m-1 for a periodic window. The default ## is symmetric. The returned window is normalized to a peak ## of 1 at w = 0.5. ## ## This window has low pass-band ripple, but high bandwidth. ## ## According to [1]: ## ## The main use for the Flat Top window is for calibration, due ## to its negligible amplitude errors. ## ## [1] Gade, S; Herlufsen, H; (1987) "Use of weighting functions in DFT/FFT ## analysis (Part I)", Bruel & Kjaer Technical Review No.3. ## @end deftypefn function w = flattopwin (m, opt) if (nargin < 1 || nargin > 2) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("flattopwin: M must be a positive integer"); endif N = m - 1; if (nargin == 2) switch (opt) case "periodic" N = m; case "symmetric" N = m - 1; otherwise error ("flattopwin: window type must be either \"periodic\" or \"symmetric\""); endswitch endif if (m == 1) w = 1; else x = 2*pi*[0:m-1]'/N; w = (1-1.93*cos(x)+1.29*cos(2*x)-0.388*cos(3*x)+0.0322*cos(4*x))/4.6402; endif endfunction %!assert (flattopwin (1), 1); %!assert (flattopwin (2), 0.0042 / 4.6402 * ones (2, 1), eps); %!assert (flattopwin (15), flipud (flattopwin (15)), 10*eps); %!assert (flattopwin (16), flipud (flattopwin (16)), 10*eps); %!assert (flattopwin (15), flattopwin (15, "symmetric")); %!assert (flattopwin (16)(1:15), flattopwin (15, "periodic")); %% Test input validation %!error flattopwin () %!error flattopwin (0.5) %!error flattopwin (-1) %!error flattopwin (ones (1, 4)) %!error flattopwin (1, 2) %!error flattopwin (1, 2, 3) %!error flattopwin (1, "invalid") ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/fracshift.m�����������������������������������������������������������������������0000644�0000000�0000000�00000014145�14673270174�013051� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2008 Eric Chassande-Mottin, CNRS (France) ## Copyright (C) 2018 Juan Pablo Carbajal ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## Author: Eric Chassande-Mottin, CNRS (France) <ecm@apc.univ-paris7.fr> ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{y}, @var{h}] =} fracshift (@var{x}, @var{d}) ## @deftypefnx {Function File} {@var{y} =} fracshift (@var{x}, @var{d}, @var{h}) ## Shift the series @var{x} by a (possibly fractional) number of samples @var{d}. ## The interpolator @var{h} is either specified or either designed with a ## Kaiser-windowed sinecard. ## @seealso{circshift} ## @end deftypefn ## Ref [1] A. V. Oppenheim, R. W. Schafer and J. R. Buck, ## Discrete-time signal processing, Signal processing series, ## Prentice-Hall, 1999 ## ## Ref [2] T.I. Laakso, V. Valimaki, M. Karjalainen and U.K. Laine ## Splitting the unit delay, IEEE Signal Processing Magazine, ## vol. 13, no. 1, pp 30--59 Jan 1996 function [y, h] = fracshift( x, d, h = []) if (nargin > 3 || nargin < 2) print_usage; endif; ## check if filter is a vector if ~isempty (h) && ~isvector (h) error ('Octave:invalid-input-arg', ... 'fracshift.m: the filter h should be a vector'); endif ## check if input is a row vector isrowvector = false; if ((rows (x) == 1) && (columns (x) > 1)) x = x(:); isrowvector = true; endif ## if the delay is an exact integer, use circshift if d == fix (d) if ~isempty (h) warning ('Octave:ignore-input-arg', ... ['Provided filter is not used if shift is an integer.\n' ... 'Consider using circshift instead.\n']); endif else ## if required, filter design using reference [1] if isempty (h) h = design_filter (d); endif Lx = length (x); Lh = length (h); L = ( Lh - 1 ) / 2.0; Ly = Lx; ## pre and postpad filter response hpad = prepad (h, Lh); offset = floor (L); hpad = postpad (hpad, Ly + offset); ## filtering xfilt = upfirdn (x, hpad, 1, 1); x = xfilt((offset + 1):(offset + Ly), :); endif y = circshift (x, fix (d)); if isrowvector, y = y.'; endif endfunction function h = design_filter (d) ## properties of the interpolation filter log10_rejection = -3.0; ## use empirical formula from [1] Chap 7, Eq. (7.63) p 476 rejection_dB = -20.0 * log10_rejection; ## determine parameter of Kaiser window ## use empirical formula from [1] Chap 7, Eq. (7.62) p 474 ## FIXME since the parameters are fix the conditional below is not needed if ((rejection_dB >= 21) && (rejection_dB <= 50)) beta = 0.5842 * (rejection_dB - 21.0) ^ 0.4 + ... 0.07886 * (rejection_dB - 21.0); elseif (rejection_dB > 50) beta = 0.1102 * (rejection_dB - 8.7); else beta = 0.0; endif ## properties of the interpolation filter stopband_cutoff_f = 0.5; roll_off_width = stopband_cutoff_f / 10; ## ideal sinc filter ## determine filter length L = ceil ((rejection_dB - 8.0) / (28.714 * roll_off_width)); t = (-L:L).'; ideal_filter = 2 * stopband_cutoff_f * ... sinc (2 * stopband_cutoff_f * (t - (d - fix (d)))); ## apodize ideal (sincard) filter response m = 2 * L; t = (0:m).' - (d - fix (d)); t = 2 * beta / m * sqrt (t .* (m - t)); w = besseli (0, t) / besseli (0, beta); h = w .* ideal_filter; endfunction %!test %! d = [1.5 7/6]; %! N = 1024; %! t = ((0:N-1)-N/2).'; %! tt = bsxfun (@minus, t, d); %! err1= err2 = zeros(N/2,1); %! for n = 0:N/2-1, %! phi0 = 2*pi*rand; %! f0 = n/N; %! sigma = N/4; %! x = exp(-t.^2/(2*sigma)).*sin(2*pi*f0*t + phi0); %! xx = exp(-tt.^2/(2*sigma)).*sin(2*pi*f0*tt + phi0); %! [y,h] = fracshift(x, d(1)); %! err1(n+1) = max (abs (y - xx(:,1))); %! [y,h] = fracshift(x, d(2)); %! err2(n+1) = max (abs (y - xx(:,2))); %! endfor %! rolloff = .1; %! rejection = 10^-3; %! idx_inband = 1:ceil((1-rolloff)*N/2)-1; %! assert (max (err1(idx_inband)) < rejection); %! assert (max (err2(idx_inband)) < rejection); %!test %! N = 1024; %! p = 6; %! q = 7; %! d1 = 64; %! d2 = d1*p/q; %! t = 128; %! %! [b a] = butter (10,.25); %! n = zeros (N, 1); %! n(N/2+(-t:t)) = randn(2*t+1,1); %! n = filter(b,a,n); %! n1 = fracshift(n,d1); %! n1 = resample(n1,p,q); %! n2 = resample(n,p,q); %! n2 = fracshift(n2,d2); %! err = abs (n2 - n1); %! rejection = 10^-3; %! assert(max (err) < rejection); %!test #integer shift similar similar to non-integer %! N = 1024; %! t = linspace(0, 1, N).'; %! x = exp(-t.^2/2/0.25^2).*sin(2*pi*10*t); %! d = 10; %! y = fracshift(x, d); %! yh = fracshift(x, d+1e-8); %! assert(y, yh, 1e-8) %!warning fracshift([1 2 3 2 1], 3, h=0.5); #integer shift and filter provided %!test #bug 52758 %! x = [0 1 0 0 0 0 0 0]; %! y = fracshift(x, 1); %! assert (size(x) == size(y)) %!test #bug 47387 %! N = 1024; %! t = linspace(0, 1, N).'; %! x = exp(-t.^2/2/0.25^2).*sin(2*pi*10*t); %! dt = 0.25; %! d = dt / (t(2) - t(1)); %! y = fracshift(x, d); %! L = 37; %! _t = (-L:L).'; %! ideal_filter = sinc (_t - (d - fix (d))); %! m = 2 * L; %! _t = (0:m).' - (d - fix (d)); %! beta = 5.6533; %! _t = 2 * beta / m * sqrt (_t .* (m - _t)); %! w = besseli (0, _t) / besseli (0, beta); %! h = w .* ideal_filter; %! yh = fracshift(x, d, h); %! assert(y, yh, 1e-8) %!demo %! N = 1024; %! t = linspace (0, 1, N).'; %! x = exp(-t.^2/2/0.25^2).*sin(2*pi*10*t); %! %! dt = 0.25; %! d = dt / (t(2) - t(1)); %! y = fracshift(x, d); %! %! plot(t,y,'r-;shifted;', t, x, 'k-;original;') %! axis tight %! xlabel ('time') %! ylabel ('signal') ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/freqs.m���������������������������������������������������������������������������0000644�0000000�0000000�00000002734�14673270174�012221� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2003 Julius O. Smith III <jos@ccrma.stanford.edu> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{h} =} freqs (@var{b}, @var{a}, @var{w}) ## @deftypefnx {Function File} {} freqs (@var{b}, @var{a}, @var{w}) ## ## Compute the s-plane frequency response of the IIR filter B(s)/A(s) as ## H = polyval(B,j*W)./polyval(A,j*W). If called with no output ## argument, a plot of magnitude and phase are displayed. ## ## Example: ## @example ## b = [1 2]; a = [1 1]; ## w = linspace (0, 4, 128); ## freqs (b, a, w); ## @end example ## @end deftypefn function H = freqs(B,A,W) if (nargin ~= 3 || nargout>1) print_usage; endif H = polyval(B,j*W)./polyval(A,j*W); if nargout<1 freqs_plot(W,H); endif endfunction %!demo %! B = [1 2]; %! A = [1 1]; %! w = linspace(0,4,128); %! freqs(B,A,w); ������������������������������������signal-1.4.6/inst/freqs_plot.m����������������������������������������������������������������������0000644�0000000�0000000�00000002762�14673270174�013260� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2003 Julius O. Smith III <jos@ccrma.stanford.edu> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} freqs_plot (@var{w}, @var{h}) ## Plot the amplitude and phase of the vector @var{h}. ## @end deftypefn function freqs_plot(w,h) n = length(w); mag = 20*log10(abs(h)); phase = unwrap(arg(h)); maxmag = max(mag); subplot(211); plot(w, mag, ";Magnitude (dB);"); title('Frequency response plot by freqs'); axis("labely"); ylabel("dB"); xlabel(""); grid("on"); if (maxmag - min(mag) > 100) # make 100 a parameter? axis([w(1), w(n), maxmag-100, maxmag]); else axis("autoy"); endif subplot(212); plot(w, phase/(2*pi), ";Phase (radians/2pi);"); axis("label"); title(""); grid("on"); axis("autoy"); xlabel("Frequency (rad/sec)"); ylabel("Cycles"); axis([w(1), w(n)]); endfunction ��������������signal-1.4.6/inst/fwhm.m����������������������������������������������������������������������������0000644�0000000�0000000�00000012776�14673270174�012051� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Author: Petr Mikulik (2009) ## This program is granted to the public domain. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{f} =} fwhm (@var{y}) ## @deftypefnx {Function File} {@var{f} =} fwhm (@var{x}, @var{y}) ## @deftypefnx {Function File} {@var{f} =} fwhm (@dots{}, "zero") ## @deftypefnx {Function File} {@var{f} =} fwhm (@dots{}, "min") ## @deftypefnx {Function File} {@var{f} =} fwhm (@dots{}, "alevel", @var{level}) ## @deftypefnx {Function File} {@var{f} =} fwhm (@dots{}, "rlevel", @var{level}) ## ## Compute peak full-width at half maximum (FWHM) or at another level of peak ## maximum for vector or matrix data @var{y}, optionally sampled as @math{y(x)}. ## If @var{y} is a matrix, return FWHM for each column as a row vector. ## ## The default option "zero" computes fwhm at half maximum, i.e. ## @math{0.5*max(y)}. The option "min" computes fwhm at the middle curve, i.e. ## @math{0.5*(min(y)+max(y))}. ## ## The option "rlevel" computes full-width at the given relative level of peak ## profile, i.e. at @math{rlevel*max(y)} or @math{rlevel*(min(y)+max(y))}, ## respectively. For example, @code{fwhm (@dots{}, "rlevel", 0.1)} computes ## full width at 10 % of peak maximum with respect to zero or minimum; FWHM is ## equivalent to @code{fwhm(@dots{}, "rlevel", 0.5)}. ## ## The option "alevel" computes full-width at the given absolute level of ## @var{y}. ## ## Return 0 if FWHM does not exist (e.g. monotonous function or the function ## does not cut horizontal line at @math{rlevel*max(y)} or ## @math{rlevel*(max(y)+min(y))} or alevel, respectively). ## ## @end deftypefn function myfwhm = fwhm (y, varargin) if nargin < 1 || nargin > 5 print_usage; endif opt = 'zero'; is_alevel = 0; level = 0.5; if nargin==1 x = 1:length(y); else if ischar(varargin{1}) x = 1:length(y); k = 1; else x = y; y = varargin{1}; k = 2; endif while k <= length(varargin) if strcmp(varargin{k}, 'alevel') is_alevel = 1; k = k+1; if k > length(varargin) error('option "alevel" requires an argument'); endif level = varargin{k}; if ~isreal(level) || length(level) > 1 error('argument of "alevel" must be real number'); endif k = k+1; break endif if any(strcmp(varargin{k}, {'zero', 'min'})) opt = varargin{k}; k = k+1; endif if k > length(varargin) break; endif if strcmp(varargin{k}, 'rlevel') k = k+1; if k > length(varargin) error('option "rlevel" requires an argument'); endif level = varargin{k}; if ~isreal(level) || length(level) > 1 || level(1) < 0 || level(:) > 1 error('argument of "rlevel" must be real number from 0 to 1 (it is 0.5 for fwhm)'); endif k = k+1; break endif break endwhile if k ~= length(varargin)+1 error('fwhm: extraneous option(s)'); endif endif ## test the y matrix [nr, nc] = size(y); if (nr == 1 && nc > 1) y = y'; nr = nc; nc = 1; endif if length(x) ~= nr error('dimension of input arguments do not match'); endif ## Shift matrix columns so that y(+-xfwhm) = 0: if is_alevel ## case: full-width at the given absolute position y = y - level; else if strcmp(opt, 'zero') ## case: full-width at half maximum y = y - level * repmat(max(y), nr, 1); else ## case: full-width above background y = y - level * repmat((max(y) + min(y)), nr, 1); endif endif ## Trial for a "vectorizing" calculation of fwhm (i.e. all ## columns in one shot): ## myfwhm = zeros(1,nc); # default: 0 for fwhm undefined ## ind = find (y(1:end-1, :) .* y(2:end, :) <= 0); ## [r1,c1] = ind2sub(size(y), ind); ## ... difficult to proceed further. ## Thus calculate fwhm for each column independently: myfwhm = zeros(1,nc); # default: 0 for fwhm undefined for n=1:nc yy = y(:, n); ind = find((yy(1:end-1) .* yy(2:end)) <= 0); if length(ind) >= 2 && yy(ind(1)) > 0 # must start ascending ind = ind(2:end); endif [mx, imax] = max(yy); # protection against constant or (almost) monotonous functions if length(ind) >= 2 && imax >= ind(1) && imax <= ind(end) ind1 = ind(1); ind2 = ind1 + 1; xx1 = x(ind1) - yy(ind1) * (x(ind2) - x(ind1)) / (yy(ind2) - yy(ind1)); ind1 = ind(end); ind2 = ind1 + 1; xx2 = x(ind1) - yy(ind1) * (x(ind2) - x(ind1)) / (yy(ind2) - yy(ind1)); myfwhm(n) = xx2 - xx1; endif endfor endfunction %!test %! x=-pi:0.001:pi; y=cos(x); %! assert( abs(fwhm(x, y) - 2*pi/3) < 0.01 ); %! %!test %! assert( fwhm(-10:10) == 0 && fwhm(ones(1,50)) == 0 ); %! %!test %! x=-20:1:20; %! y1=-4+zeros(size(x)); y1(4:10)=8; %! y2=-2+zeros(size(x)); y2(4:11)=2; %! y3= 2+zeros(size(x)); y3(5:13)=10; %! assert( max(abs(fwhm(x, [y1;y2;y3]') - [20.0/3,7.5,9.25])) < 0.01 ); %! %!test %! x=1:3; y=[-1,3,-1]; assert(abs(fwhm(x,y)-0.75)<0.001 && abs(fwhm(x,y,'zero')-0.75)<0.001 && abs(fwhm(x,y,'min')-1.0)<0.001); %! %!test %! x=1:3; y=[-1,3,-1]; assert(abs(fwhm(x,y, 'rlevel', 0.1)-1.35)<0.001 && abs(fwhm(x,y,'zero', 'rlevel', 0.1)-1.35)<0.001 && abs(fwhm(x,y,'min', 'rlevel', 0.1)-1.40)<0.001); %! %!test %! x=1:3; y=[-1,3,-1]; assert(abs(fwhm(x,y, 'alevel', 2.5)-0.25)<0.001 && abs(fwhm(x,y,'alevel', -0.5)-1.75)<0.001); %! %!test %! x=-10:10; assert( fwhm(x.*x) == 0 ); %! %!test %! x=-5:5; y=18-x.*x; assert( abs(fwhm(y)-6.0) < 0.001 && abs(fwhm(x,y,'zero')-6.0) < 0.001 && abs(fwhm(x,y,'min')-7.0 ) < 0.001); ��signal-1.4.6/inst/fwht.m����������������������������������������������������������������������������0000644�0000000�0000000�00000005423�14673270174�012047� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} fwht (@var{x}) ## @deftypefnx {Function File} {} fwht (@var{x}, @var{n}) ## @deftypefnx {Function File} {} fwht (@var{x}, @var{n}, @var{order}) ## Compute the Walsh-Hadamard transform of @var{x} using the Fast ## Walsh-Hadamard Transform (FWHT) algorithm. If the input is a matrix, ## the FWHT is calculated along the columns of @var{x}. ## ## The number of elements of @var{x} must be a power of 2; if not, the ## input will be extended and filled with zeros. If a second argument ## is given, the input is truncated or extended to have length @var{n}. ## ## The third argument specifies the @var{order} in which the returned ## Walsh-Hadamard transform coefficients should be arranged. The ## @var{order} may be any of the following strings: ## ## @table @asis ## @item "sequency" ## The coefficients are returned in sequency order. This is the default ## if @var{order} is not given. ## ## @item "hadamard" ## The coefficients are returned in Hadamard order. ## ## @item "dyadic" ## The coefficients are returned in Gray code order. ## @end table ## ## @seealso{ifwht} ## @end deftypefn function y = fwht (x, n, order) if (nargin < 1 || nargin > 3) print_usage (); elseif (nargin == 1) n = order = []; elseif (nargin == 2) order = []; endif [y, n] = __fwht_opts__ ("fwht", x, n, order); y /= n; endfunction %!assert (isempty (fwht ([]))); %!assert (fwht (zeros (16)), zeros (16)); %!assert (fwht (ones (16, 1)), [1; (zeros (15, 1))]); %!assert (fwht (zeros (17, 1)), zeros (32, 1)); %!assert (fwht ([1 -1 1 -1 1 -1 1 -1]), [0 0 0 0 0 0 0 1]); %!test %! x = randi (16, 16); %! assert (ifwht (fwht (x)), x); %!test %! x = randi (16, 16); %! assert (ifwht (fwht (x, [], "sequency"), [], "sequency"), x); %!test %! x = randi (16, 16); %! assert (ifwht (fwht (x, [], "hadamard"), [], "hadamard"), x); %!test %! x = randi (16, 16); %! assert (ifwht (fwht (x, [], "dyadic"), [], "dyadic"), x); %% Test input validation %!error fwht (); %!error fwht (1, 2, 3, 4); %!error fwht (0, 0); %!error fwht (0, 5); %!error fwht (0, [], "invalid"); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/gauspuls.m������������������������������������������������������������������������0000644�0000000�0000000�00000004304�14673270174�012737� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier ## Copyright (C) 2018-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} gauspuls (@var{t}) ## @deftypefnx {Function File} {@var{y} =} gauspuls (@var{t}, @var{fc}) ## @deftypefnx {Function File} {@var{y} =} gauspuls (@var{t}, @var{fc}, @var{bw}) ## Generate a Gaussian modulated sinusoidal pulse sampled at times @var{t}. ## @seealso{pulstran, rectpuls, tripuls} ## @end deftypefn function y = gauspuls (t, fc = 1e3, bw = 0.5) if (nargin < 1 || nargin > 3) print_usage (); endif if (! isreal (fc) || ! isscalar (fc) || fc < 0) error ("gauspuls: FC must be a non-negative real scalar") endif if (! isreal (bw) || ! isscalar (bw) || bw <= 0) error ("gauspuls: BW must be a positive real scalar") endif fv = -(bw^2 * fc^2) / (8 * log (10 ^ (-6/20))); tv = 1 / (4*pi^2 * fv); y = exp (-t .* t / (2*tv)) .* cos (2*pi*fc * t); endfunction %!demo %! fs = 11025; # arbitrary sample rate %! f0 = 100; # pulse train sample rate %! x = pulstran (0:1/fs:4/f0, 0:1/f0:4/f0, "gauspuls"); %! plot ([0:length(x)-1]*1000/fs, x); %! xlabel ("Time (ms)"); %! ylabel ("Amplitude"); %! title ("Gaussian pulse train at 10 ms intervals"); %!assert (gauspuls ([]), []) %!assert (gauspuls (zeros (10, 1)), ones (10, 1)) %!assert (gauspuls (-1:1), [0, 1, 0]) %!assert (gauspuls (0:1/100:0.3, 0.1), gauspuls ([0:1/100:0.3]', 0.1)') ## Test input validation %!error gauspuls () %!error gauspuls (1, 2, 3, 4) %!error gauspuls (1, -1) %!error gauspuls (1, 2j) %!error gauspuls (1, 1e3, 0) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/gaussian.m������������������������������������������������������������������������0000644�0000000�0000000�00000003515�14673270174�012711� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} gaussian (@var{m}) ## @deftypefnx {Function File} {} gaussian (@var{m}, @var{a}) ## ## Return a Gaussian convolution window of length @var{m}. The width of the ## window is inversely proportional to the parameter @var{a}. Use larger ## @var{a} for a narrower window. Use larger @var{m} for longer tails. ## ## w = exp ( -(a*x)^2/2 ) ## ## for x = linspace ( -(m-1)/2, (m-1)/2, m ). ## ## Width a is measured in frequency units (sample rate/num samples). ## It should be f when multiplying in the time domain, but 1/f when ## multiplying in the frequency domain (for use in convolutions). ## @end deftypefn function w = gaussian (m, a) if (nargin < 1 || nargin > 2) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("gaussian: M must be a positive integer"); elseif (nargin == 1) a = 1; endif w = exp(-0.5*(([0:m-1]'-(m-1)/2)*a).^2); endfunction %!assert (gaussian (1), 1) %% Test input validation %!error gaussian () %!error gaussian (0.5) %!error gaussian (-1) %!error gaussian (ones (1, 4)) %!error gaussian (1, 2, 3) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/gausswin.m������������������������������������������������������������������������0000644�0000000�0000000�00000003536�14673270174�012742� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} gausswin (@var{m}) ## @deftypefnx {Function File} {} gausswin (@var{m}, @var{a}) ## ## Return the filter coefficients of a Gaussian window of length @var{m}. ## The width of the window is inversely proportional to the parameter @var{a}. ## Use larger @var{a} for a narrow window. Use larger @var{m} for a smoother ## curve. ## ## w = exp ( -(a*x)^2/2 ) ## ## for x = linspace(-(m-1)/m, (m-1)/m, m) ## @end deftypefn function w = gausswin (m, a) if (nargin < 1 || nargin > 2) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("Octave:invalid-input-arg", ... "gausswin: M must be a positive integer"); elseif (nargin == 1) a = 2.5; endif if (m == 1) w = 1; else w = exp (-0.5 * (a / (m-1) * (-(m-1):2:(m-1))') .^ 2); endif endfunction %!assert (gausswin (1), 1) %!assert (gausswin (2), [exp(-3.125); exp(-3.125)]) %!assert (gausswin (3), [exp(-3.125); 1; exp(-3.125)]) ## Test input validation %!error gausswin () %!error gausswin (0.5) %!error gausswin (-1) %!error gausswin (ones (1, 4)) %!error gausswin (1, 2, 3) ������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/gmonopuls.m�����������������������������������������������������������������������0000644�0000000�0000000�00000002113�14673270174�013113� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} gmonopuls (@var{t},@var{fc}) ## Return the gaussian monopulse. ## @end deftypefn function y = gmonopuls(t, fc = 1e3) if (nargin<1 || nargin > 2), print_usage; endif if fc < 0 , error("fc must be positive"); endif y = 2*sqrt(exp(1)) .* pi.*t.*fc.*exp(-2 .* (pi.*t.*fc).^2); endfunction �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/grpdelay.m������������������������������������������������������������������������0000644�0000000�0000000�00000027400�14673270174�012705� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2004 Julius O. Smith III <jos@ccrma.stanford.edu> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{g}, @var{w}] =} grpdelay (@var{b}) ## @deftypefnx {Function File} {[@var{g}, @var{w}] =} grpdelay (@var{b}, @var{a}) ## @deftypefnx {Function File} {[@var{g}, @var{w}] =} grpdelay (@dots{}, @var{n}) ## @deftypefnx {Function File} {[@var{g}, @var{w}] =} grpdelay (@dots{}, @var{n}, "whole") ## @deftypefnx {Function File} {[@var{g}, @var{f}] =} grpdelay (@dots{}, @var{n}, @var{Fs}) ## @deftypefnx {Function File} {[@var{g}, @var{f}] =} grpdelay (@dots{}, @var{n}, "whole", @var{Fs}) ## @deftypefnx {Function File} {[@var{g}, @var{w}] =} grpdelay (@dots{}, @var{w}) ## @deftypefnx {Function File} {[@var{g}, @var{f}] =} grpdelay (@dots{}, @var{f}, @var{Fs}) ## @deftypefnx {Function File} {} grpdelay (@dots{}) ## Compute the group delay of a filter. ## ## [g, w] = grpdelay(b) ## returns the group delay g of the FIR filter with coefficients b. ## The response is evaluated at 512 angular frequencies between 0 and ## pi. w is a vector containing the 512 frequencies. ## The group delay is in units of samples. It can be converted ## to seconds by multiplying by the sampling period (or dividing by ## the sampling rate fs). ## ## [g, w] = grpdelay(b,a) ## returns the group delay of the rational IIR filter whose numerator ## has coefficients b and denominator coefficients a. ## ## [g, w] = grpdelay(b,a,n) ## returns the group delay evaluated at n angular frequencies. For fastest ## computation n should factor into a small number of small primes. ## ## [g, w] = grpdelay(b,a,n,'whole') ## evaluates the group delay at n frequencies between 0 and 2*pi. ## ## [g, f] = grpdelay(b,a,n,Fs) ## evaluates the group delay at n frequencies between 0 and Fs/2. ## ## [g, f] = grpdelay(b,a,n,'whole',Fs) ## evaluates the group delay at n frequencies between 0 and Fs. ## ## [g, w] = grpdelay(b,a,w) ## evaluates the group delay at frequencies w (radians per sample). ## ## [g, f] = grpdelay(b,a,f,Fs) ## evaluates the group delay at frequencies f (in Hz). ## ## grpdelay(...) ## plots the group delay vs. frequency. ## ## If the denominator of the computation becomes too small, the group delay ## is set to zero. (The group delay approaches infinity when ## there are poles or zeros very close to the unit circle in the z plane.) ## ## Theory: group delay, g(w) = -d/dw [arg@{H(e^jw)@}], is the rate of change of ## phase with respect to frequency. It can be computed as: ## ## @example ## d/dw H(e^-jw) ## g(w) = ------------- ## H(e^-jw) ## @end example ## ## where ## ## @example ## H(z) = B(z)/A(z) = sum(b_k z^k)/sum(a_k z^k). ## @end example ## ## By the quotient rule, ## ## @example ## A(z) d/dw B(z) - B(z) d/dw A(z) ## d/dw H(z) = ------------------------------- ## A(z) A(z) ## @end example ## ## Substituting into the expression above yields: ## ## @example ## A dB - B dA ## g(w) = ----------- = dB/B - dA/A ## A B ## @end example ## ## Note that, ## ## @example ## d/dw B(e^-jw) = sum(k b_k e^-jwk) ## d/dw A(e^-jw) = sum(k a_k e^-jwk) ## @end example ## ## which is just the FFT of the coefficients multiplied by a ramp. ## ## As a further optimization when nfft>>length(a), the IIR filter (b,a) ## is converted to the FIR filter conv(b,fliplr(conj(a))). ## For further details, see ## http://ccrma.stanford.edu/~jos/filters/Numerical_Computation_Group_Delay.html ## @end deftypefn function [gd, w] = grpdelay (b, a = 1, nfft = 512, whole, Fs) if (nargin < 1 || nargin > 5) print_usage (); endif HzFlag = false; if (length (nfft) > 1) if (nargin > 4) print_usage (); elseif (nargin > 3) ## grpdelay (B, A, F, Fs) Fs = whole; HzFlag = true; else ## grpdelay (B, A, W) Fs = 1; endif w = 2*pi*nfft/Fs; nfft = length (w) * 2; whole = ""; else if (nargin < 5) Fs = 1; # return w in radians per sample if (nargin < 4) whole = ""; elseif (! ischar (whole)) Fs = whole; HzFlag = true; whole = ""; endif if (nargin < 3) nfft = 512; endif if (nargin < 2) a = 1; endif else HzFlag = true; endif if (isempty (nfft)) nfft = 512; endif if (! strcmp (whole, "whole")) nfft = 2*nfft; endif w = Fs*[0:nfft-1]/nfft; endif if (! HzFlag) w = w * 2 * pi; endif ## Make sure both are row vector a = a(:).'; b = b(:).'; oa = length (a) -1; # order of a(z) if (oa < 0) # a can be [] a = 1; oa = 0; endif ob = length (b) -1; # order of b(z) if (ob < 0) # b can be [] as well b = 1; ob = 0; endif oc = oa + ob; # order of c(z) c = conv (b, fliplr (conj (a))); # c(z) = b(z)*conj(a)(1/z)*z^(-oa) cr = c.*(0:oc); # cr(z) = derivative of c wrt 1/z num = fft (cr, nfft); den = fft (c, nfft); minmag = 10*eps; polebins = find (abs (den) < minmag); for b = polebins warning ("signal:grpdelay-singularity", "grpdelay: setting group delay to 0 at singularity"); num(b) = 0; den(b) = 1; ## try to preserve angle: ## db = den(b); ## den(b) = minmag*abs(num(b))*exp(j*atan2(imag(db),real(db))); ## warning(sprintf('grpdelay: den(b) changed from %f to %f',db,den(b))); endfor gd = real (num ./ den) - oa; if (! strcmp (whole, "whole")) ns = nfft/2; # Matlab convention ... should be nfft/2 + 1 gd = gd(1:ns); w = w(1:ns); else ns = nfft; # used in plot below endif ## compatibility gd = gd(:); w = w(:); if (nargout == 0) unwind_protect grid ("on"); # grid() should return its previous state if (HzFlag) funits = "Hz"; else funits = "radian/sample"; endif xlabel (["Frequency (" funits ")"]); ylabel ("Group delay (samples)"); plot (w(1:ns), gd(1:ns), ";;"); unwind_protect_cleanup grid ("on"); end_unwind_protect endif endfunction ## ------------------------ DEMOS ----------------------- %!demo % 1 %! %-------------------------------------------------------------- %! % From Oppenheim and Schafer, a single zero of radius r=0.9 at %! % angle pi should have a group delay of about -9 at 1 and 1/2 %! % at zero and 2*pi. %! %-------------------------------------------------------------- %! grpdelay([1 0.9],[],512,'whole',1); %! hold on; %! xlabel('Normalized Frequency (cycles/sample)'); %! stem([0, 0.5, 1],[0.5, -9, 0.5],'*b;target;'); %! hold off; %! title ('Zero at z = -0.9'); %! %!demo % 2 %! %-------------------------------------------------------------- %! % confirm the group delays approximately meet the targets %! % don't worry that it is not exact, as I have not entered %! % the exact targets. %! %-------------------------------------------------------------- %! b = poly([1/0.9*exp(1i*pi*0.2), 0.9*exp(1i*pi*0.6)]); %! a = poly([0.9*exp(-1i*pi*0.6), 1/0.9*exp(-1i*pi*0.2)]); %! grpdelay(b,a,512,'whole',1); %! hold on; %! xlabel('Normalized Frequency (cycles/sample)'); %! stem([0.1, 0.3, 0.7, 0.9], [9, -9, 9, -9],'*b;target;'); %! hold off; %! title ('Two Zeros and Two Poles'); %!demo % 3 %! %-------------------------------------------------------------- %! % fir lowpass order 40 with cutoff at w=0.3 and details of %! % the transition band [.3, .5] %! %-------------------------------------------------------------- %! subplot(211); %! Fs = 8000; % sampling rate %! Fc = 0.3*Fs/2; % lowpass cut-off frequency %! nb = 40; %! b = fir1(nb,2*Fc/Fs); % matlab freq normalization: 1=Fs/2 %! [H,f] = freqz(b,1,[],1); %! [gd,f] = grpdelay(b,1,[],1); %! plot(f,20*log10(abs(H))); %! title(sprintf('b = fir1(%d,2*%d/%d);',nb,Fc,Fs)); %! xlabel('Normalized Frequency (cycles/sample)'); %! ylabel('Amplitude Response (dB)'); %! grid('on'); %! subplot(212); %! del = nb/2; % should equal this %! plot(f,gd); %! title(sprintf('Group Delay in Pass-Band (Expect %d samples)',del)); %! ylabel('Group Delay (samples)'); %! axis([0, 0.2, del-1, del+1]); %!demo % 4 %! %-------------------------------------------------------------- %! % IIR bandstop filter has delays at [1000, 3000] %! %-------------------------------------------------------------- %! Fs = 8000; %! [b, a] = cheby1(3, 3, 2*[1000, 3000]/Fs, 'stop'); %! [H,f] = freqz(b,a,[],Fs); %! [gd,f] = grpdelay(b,a,[],Fs); %! subplot(211); %! plot(f,abs(H)); %! title('[b,a] = cheby1(3, 3, 2*[1000, 3000]/Fs, "stop");'); %! xlabel('Frequency (Hz)'); %! ylabel('Amplitude Response'); %! grid('on'); %! subplot(212); %! plot(f,gd); %! title('[gd,f] = grpdelay(b,a,[],Fs);'); %! ylabel('Group Delay (samples)'); % ------------------------ TESTS ----------------------- %!test % 00 %! [gd1,w] = grpdelay([0,1]); %! [gd2,w] = grpdelay([0,1],1); %! assert(gd1,gd2,10*eps); %!test % 0A %! [gd,w] = grpdelay([0,1],1,4); %! assert(gd,[1;1;1;1]); %! assert(w,pi/4*[0:3]',10*eps); %!test % 0B %! [gd,w] = grpdelay([0,1],1,4,'whole'); %! assert(gd,[1;1;1;1]); %! assert(w,pi/2*[0:3]',10*eps); %!test % 0C %! [gd,f] = grpdelay([0,1],1,4,0.5); %! assert(gd,[1;1;1;1]); %! assert(f,1/16*[0:3]',10*eps); %!test % 0D %! [gd,w] = grpdelay([0,1],1,4,'whole',1); %! assert(gd,[1;1;1;1]); %! assert(w,1/4*[0:3]',10*eps); %!test % 0E %! [gd,f] = grpdelay([1 -0.9j],[],4,'whole',1); %! gd0 = 0.447513812154696; gdm1 =0.473684210526316; %! assert(gd,[gd0;-9;gd0;gdm1],20*eps); %! assert(f,1/4*[0:3]',10*eps); %!test % 1A: %! gd= grpdelay(1,[1,.9],2*pi*[0,0.125,0.25,0.375]); %! assert(gd, [-0.47368;-0.46918;-0.44751;-0.32316],1e-5); %!test % 1B: %! gd= grpdelay(1,[1,.9],[0,0.125,0.25,0.375],1); %! assert(gd, [-0.47368;-0.46918;-0.44751;-0.32316],1e-5); %!test % 2: %! gd = grpdelay([1,2],[1,0.5,.9],4); %! assert(gd,[-0.29167;-0.24218;0.53077;0.40658],1e-5); %!test % 3 %! b1=[1,2];a1f=[0.25,0.5,1];a1=fliplr(a1f); %! % gd1=grpdelay(b1,a1,4); %! gd=grpdelay(conv(b1,a1f),1,4)-2; %! assert(gd, [0.095238;0.239175;0.953846;1.759360],1e-5); %!test % 4 %! warning ("off", "signal:grpdelay-singularity", "local"); %! Fs = 8000; %! [b, a] = cheby1(3, 3, 2*[1000, 3000]/Fs, 'stop'); %! [h, w] = grpdelay(b, a, 256, 'half', Fs); %! [h2, w2] = grpdelay(b, a, 512, 'whole', Fs); %! assert (size(h), size(w)); %! assert (length(h), 256); %! assert (size(h2), size(w2)); %! assert (length(h2), 512); %! assert (h, h2(1:256)); %! assert (w, w2(1:256)); %!test % 5 %! a = [1 0 0.9]; %! b = [0.9 0 1]; %! [dh, wf] = grpdelay(b, a, 512, 'whole'); %! [da, wa] = grpdelay(1, a, 512, 'whole'); %! [db, wb] = grpdelay(b, 1, 512, 'whole'); %! assert(dh,db+da,1e-5); ## test for bug #39133 (do not fail for row or column vector) %!test %! DR= [1.00000 -0.00000 -3.37219 0.00000 ... %! 5.45710 -0.00000 -5.24394 0.00000 ... %! 3.12049 -0.00000 -1.08770 0.00000 0.17404]; %! N = [-0.0139469 -0.0222376 0.0178631 0.0451737 ... %! 0.0013962 -0.0259712 0.0016338 0.0165189 ... %! 0.0115098 0.0095051 0.0043874]; %! assert (nthargout (1:2, @grpdelay, N, DR, 1024), %! nthargout (1:2, @grpdelay, N', DR', 1024)); ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/hann.m����������������������������������������������������������������������������0000644�0000000�0000000�00000004023�14673270174�012016� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2014-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} hann (@var{m}) ## @deftypefnx {Function File} {} hann (@var{m}, "periodic") ## @deftypefnx {Function File} {} hann (@var{m}, "symmetric") ## Return the filter coefficients of a Hanning window of length @var{m}. ## ## If the optional argument @code{"periodic"} is given, the periodic form ## of the window is returned. This is equivalent to the window of length ## @var{m}+1 with the last coefficient removed. The optional argument ## @code{"symmetric"} is equivalent to not specifying a second argument. ## ## This function exists for @sc{matlab} compatibility only, and is equivalent ## to @code{hanning (@var{m})}. ## ## @seealso{hanning} ## @end deftypefn function w = hann (varargin) if (nargin < 1 || nargin > 2) print_usage (); endif w = hanning (varargin{:}); endfunction %!assert (hann (1), 1); %!assert (hann (2), zeros (2, 1)); %!assert (hann (16), flipud (hann (16)), 10*eps); %!assert (hann (15), flipud (hann (15)), 10*eps); %!test %! N = 15; %! A = hann (N); %! assert (A(ceil (N/2)), 1); %!assert (hann (15), hann (15, "symmetric")); %!assert (hann (16)(1:15), hann (15, "periodic")); %!test %! N = 16; %! A = hann (N, "periodic"); %! assert (A (N/2 + 1), 1); %% Test input validation %!error hann () %!error hann (0.5) %!error hann (-1) %!error hann (1, "invalid") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/hilbert.m�������������������������������������������������������������������������0000644�0000000�0000000�00000007557�14673270174�012542� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2007 Peter L. Soendergaard ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{h} =} hilbert (@var{f}, @var{N}, @var{dim}) ## Analytic extension of real valued signal. ## ## @code{@var{h} = hilbert (@var{f})} computes the extension of the real ## valued signal @var{f} to an analytic signal. If @var{f} is a matrix, ## the transformation is applied to each column. For N-D arrays, ## the transformation is applied to the first non-singleton dimension. ## ## @code{real (@var{h})} contains the original signal @var{f}. ## @code{imag (@var{h})} contains the Hilbert transform of @var{f}. ## ## @code{hilbert (@var{f}, @var{N})} does the same using a length @var{N} ## Hilbert transform. The result will also have length @var{N}. ## ## @code{hilbert (@var{f}, [], @var{dim})} or ## @code{hilbert (@var{f}, @var{N}, @var{dim})} does the same along ## dimension @var{dim}. ## @end deftypefn function f=hilbert(f, N = [], dim = []) ## ------ PRE: initialization and dimension shifting --------- if (nargin<1 || nargin>3) print_usage; endif if ~isreal(f) warning ('HILBERT: ignoring imaginary part of signal'); f = real (f); endif D=ndims(f); ## Dummy assignment. order=1; if isempty(dim) dim=1; if sum(size(f)>1)==1 ## We have a vector, find the dimension where it lives. dim=find(size(f)>1); endif else if (numel(dim)~=1 || ~isnumeric(dim)) error('HILBERT: dim must be a scalar.'); endif if rem(dim,1)~=0 error('HILBERT: dim must be an integer.'); endif if (dim<1) || (dim>D) error('HILBERT: dim must be in the range from 1 to %d.',D); endif endif if (numel(N)>1 || ~isnumeric(N)) error('N must be a scalar.'); elseif (~isempty(N) && rem(N,1)~=0) error('N must be an integer.'); endif if dim>1 order=[dim, 1:dim-1,dim+1:D]; ## Put the desired dimension first. f=permute(f,order); endif Ls=size(f,1); ## If N is empty it is set to be the length of the transform. if isempty(N) N=Ls; endif ## Remember the exact size for later and modify it for the new length permutedsize=size(f); permutedsize(1)=N; ## Reshape f to a matrix. f=reshape(f,size(f,1),numel(f)/size(f,1)); W=size(f,2); if ~isempty(N) f=postpad(f,N); endif ## ------- actual computation ----------------- if N>2 f=fft(f); if rem(N,2)==0 f=[f(1,:); 2*f(2:N/2,:); f(N/2+1,:); zeros(N/2-1,W)]; else f=[f(1,:); 2*f(2:(N+1)/2,:); zeros((N-1)/2,W)]; endif f=ifft(f); endif ## ------- POST: Restoration of dimensions ------------ ## Restore the original, permuted shape. f=reshape(f,permutedsize); if dim>1 ## Undo the permutation. f=ipermute(f,order); endif endfunction %!demo %! ## notice that the imaginary signal is phase-shifted 90 degrees %! t=linspace(0,10,256); %! z = hilbert(sin(2*pi*0.5*t)); %! grid on; plot(t,real(z),';real;',t,imag(z),';imag;'); %!demo %! ## the magnitude of the hilbert transform eliminates the carrier %! t=linspace(0,10,1024); %! x=5*cos(0.2*t).*sin(100*t); %! grid on; plot(t,x,'g;z;',t,abs(hilbert(x)),'b;|hilbert(z)|;'); �������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/idct.m����������������������������������������������������������������������������0000644�0000000�0000000�00000005011�14673270174�012013� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} idct (@var{x}) ## @deftypefnx {Function File} {@var{y} =} idct (@var{x}, @var{n}) ## Compute the inverse discrete cosine transform of @var{x}. If @var{n} is ## given, then @var{x} is padded or trimmed to length @var{n} before computing ## the transform. If @var{x} is a matrix, compute the transform along the ## columns of the the matrix. The transform is faster if @var{x} is ## real-valued and even length. ## ## The inverse discrete cosine transform @var{x} can be defined as follows: ## ## @example ## N-1 ## x[n] = sum w(k) X[k] cos (pi (2n+1) k / 2N ), n = 0, ..., N-1 ## k=0 ## @end example ## ## with w(0) = sqrt(1/N) and w(k) = sqrt(2/N), k = 1, ..., N-1 ## ## @seealso{dct, dct2, idct2, dctmtx} ## @end deftypefn function y = idct (x, n) if (nargin < 1 || nargin > 2) print_usage; endif realx = isreal(x); transpose = (rows (x) == 1); if transpose, x = x (:); endif [nr, nc] = size (x); if nargin == 1 n = nr; elseif n > nr x = [ x ; zeros(n-nr,nc) ]; elseif n < nr x (n-nr+1 : n, :) = []; endif if ( realx && rem (n, 2) == 0 ) w = [ sqrt(n/4); sqrt(n/2)*exp((1i*pi/2/n)*[1:n-1]') ] * ones (1, nc); y = ifft (w .* x); y([1:2:n, n:-2:1], :) = 2*real(y); elseif n == 1 y = x; else ## reverse the steps of dct using inverse operations ## 1. undo post-fft scaling w = [ sqrt(4*n); sqrt(2*n)*exp((1i*pi/2/n)*[1:n-1]') ] * ones (1, nc); y = x.*w; ## 2. reconstruct fft result and invert it w = exp(-1i*pi*[n-1:-1:1]'/n) * ones(1,nc); y = ifft ( [ y ; zeros(1,nc); y(n:-1:2,:).*w ] ); ## 3. keep only the original data; toss the reversed copy y = y(1:n, :); if (realx) y = real (y); endif endif if transpose, y = y.'; endif endfunction �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/idct2.m���������������������������������������������������������������������������0000644�0000000�0000000�00000002747�14673270174�012112� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} idct2 (@var{x}) ## @deftypefnx {Function File} {@var{y} =} idct2 (@var{x}, @var{m}, @var{n}) ## @deftypefnx {Function File} {@var{y} =} idct2 (@var{x}, [@var{m}, @var{n}]) ## Compute the inverse 2-D discrete cosine transform of matrix @var{x}. ## If @var{m} and @var{n} are specified, the input is either padded or truncated ## to have @var{m} rows and @var{n} columns. ## @end deftypefn function y = idct2 (x, m, n) if (nargin < 1 || nargin > 3) print_usage; endif if nargin == 1 [m, n] = size (x); elseif (nargin == 2) n = m (2); m = m (1); endif if m == 1 y = idct (x.', n).'; elseif n == 1 y = idct (x, m); else y = idct (idct (x, m).', n).'; endif endfunction �������������������������signal-1.4.6/inst/idst.m����������������������������������������������������������������������������0000644�0000000�0000000�00000001470�14673270174�012040� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Author: Paul Kienzle <pkienzle@users.sf.net> (2006) ## This program is granted to the public domain. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} idst (@var{x}) ## @deftypefnx {Function File} {@var{y} =} idst (@var{x}, @var{n}) ## Computes the inverse type I discrete sine transform of @var{y}. If @var{n} is ## given, then @var{y} is padded or trimmed to length @var{n} before computing ## the transform. If @var{y} is a matrix, compute the transform along the ## columns of the the matrix. ## @seealso{dst} ## @end deftypefn function x = idst (y, n) if (nargin < 1 || nargin > 2) print_usage; endif if nargin == 1, n = size(y,1); if n==1, n = size(y,2); endif endif x = dst(y, n) * 2/(n+1); endfunction %!test %! x = log(gausswin(32)); %! assert(x, idst(dst(x)), 100*eps) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/ifht.m����������������������������������������������������������������������������0000644�0000000�0000000�00000004026�14673270174�012027� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2008 Muthiah Annamalai <muthiah.annamalai@uta.edu> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{m} =} ifht (@var{d}, @var{n}, @var{dim}) ## Calculate the inverse Fast Hartley Transform of real input @var{d}. If ## @var{d} is a matrix, the inverse Hartley transform is calculated along the ## columns by default. The options @var{n} and @var{dim} are similar to the ## options of FFT function. ## ## The forward and inverse Hartley transforms are the same (except for a ## scale factor of 1/N for the inverse hartley transform), but ## implemented using different functions. ## ## The definition of the forward hartley transform for vector d, ## @math{ ## m[K] = 1/N \sum_{i=0}^{N-1} d[i]*(cos[K*2*pi*i/N] + sin[K*2*pi*i/N]), for 0 <= K < N. ## m[K] = 1/N \sum_{i=0}^{N-1} d[i]*CAS[K*i], for 0 <= K < N. } ## ## @example ## ifht(1:4) ## @end example ## @seealso{fht, fft} ## @end deftypefn function m = ifht( d, n, dim ) if ( nargin < 1 ) print_usage(); endif if ( nargin == 3 ) Y = ifft(d,n,dim); elseif ( nargin == 2 ) Y = ifft(d,n); else Y = ifft(d); endif m = real(Y) + imag(Y); ## -- Traditional -- ## N = length(d); ## for K = 1:N ## i = 0:N-1; ## t = (2*pi*(K-1).*i/N); ## ker = (cos(t) + sin(t)); ## val = dot(d,ker)./N; ## m(K) = val; ## endfor endfunction %!assert(ifht(fht(1:4)),[1 2 3 4]) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/ifwht.m���������������������������������������������������������������������������0000644�0000000�0000000�00000004720�14673270174�012217� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} ifwht (@var{x}) ## @deftypefnx {Function File} {} ifwht (@var{x}, @var{n}) ## @deftypefnx {Function File} {} ifwht (@var{x}, @var{n}, @var{order}) ## Compute the inverse Walsh-Hadamard transform of @var{x} using the ## Fast Walsh-Hadamard Transform (FWHT) algorithm. If the input is a ## matrix, the inverse FWHT is calculated along the columns of @var{x}. ## ## The number of elements of @var{x} must be a power of 2; if not, the ## input will be extended and filled with zeros. If a second argument ## is given, the input is truncated or extended to have length @var{n}. ## ## The third argument specifies the @var{order} in which the returned ## inverse Walsh-Hadamard transform coefficients should be arranged. ## The @var{order} may be any of the following strings: ## ## @table @asis ## @item "sequency" ## The coefficients are returned in sequency order. This is the default ## if @var{order} is not given. ## ## @item "hadamard" ## The coefficients are returned in Hadamard order. ## ## @item "dyadic" ## The coefficients are returned in Gray code order. ## @end table ## ## @seealso{fwht} ## @end deftypefn function y = ifwht (x, n, order) if (nargin < 1 || nargin > 3) print_usage (); elseif (nargin == 1) n = order = []; elseif (nargin == 2) order = []; endif y = __fwht_opts__ ("ifwht", x, n, order); endfunction %!assert (isempty (ifwht ([]))); %!assert (ifwht (zeros (16)), zeros (16)); %!assert (ifwht ([1; (zeros (15, 1))]), ones (16, 1)); %!assert (ifwht (zeros (17, 1)), zeros (32, 1)); %!assert (ifwht ([0 0 0 0 0 0 0 1]), [1 -1 1 -1 1 -1 1 -1]); %% Test input validation %!error ifwht (); %!error ifwht (1, 2, 3, 4); %!error ifwht (0, 0); %!error ifwht (0, 5); %!error ifwht (0, [], "invalid"); ������������������������������������������������signal-1.4.6/inst/iirlp2mb.m������������������������������������������������������������������������0000644�0000000�0000000�00000027544�14673270174�012627� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2011 Alan J. Greenberger <alanjg@ptd.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## IIR Low Pass Filter to Multiband Filter Transformation ## ## [Num,Den,AllpassNum,AllpassDen] = iirlp2mb(B,A,Wo,Wt) ## [Num,Den,AllpassNum,AllpassDen] = iirlp2mb(B,A,Wo,Wt,Pass) ## ## Num,Den: numerator,denominator of the transformed filter ## AllpassNum,AllpassDen: numerator,denominator of allpass transform, ## B,A: numerator,denominator of prototype low pass filter ## Wo: normalized_angular_frequency/pi to be transformed ## Wt: [phi=normalized_angular_frequencies]/pi target vector ## Pass: This parameter may have values 'pass' or 'stop'. If ## not given, it defaults to the value of 'pass'. ## ## With normalized ang. freq. targets 0 < phi(1) < ... < phi(n) < pi radians ## ## for Pass == 'pass', the target multiband magnitude will be: ## -------- ---------- -----------... ## / \ / \ / . ## 0 phi(1) phi(2) phi(3) phi(4) phi(5) (phi(6)) pi ## ## for Pass == 'stop', the target multiband magnitude will be: ## ------- --------- ----------... ## \ / \ / . ## 0 phi(1) phi(2) phi(3) phi(4) (phi(5)) pi ## ## Example of use: ## [B, A] = butter(6, 0.5); ## [Num, Den] = iirlp2mb(B, A, 0.5, [.2 .4 .6 .8]); function [Num,Den,AllpassNum,AllpassDen] = iirlp2mb(varargin) usage = sprintf( "%s: Usage: [Num,Den,AllpassNum,AllpassDen]=iirlp2mb(B,A,Wo,Wt[,Pass])\n" ,mfilename()); B = varargin{1}; # numerator polynomial of prototype low pass filter A = varargin{2}; # denominator polynomial of prototype low pass filter Wo = varargin{3}; # (normalized angular frequency)/pi to be transformed Wt = varargin{4}; # vector of (norm. angular frequency)/pi transform targets # [phi(1) phi(2) ... ]/pi if(nargin < 4 || nargin > 5) error("%s",usage) endif if(nargin == 5) Pass = varargin{5}; switch(Pass) case 'pass' pass_stop = -1; case 'stop' pass_stop = 1; otherwise error("Pass must be 'pass' or 'stop'\n%s",usage) endswitch else pass_stop = -1; # Pass == 'pass' is the default endif if(Wo <= 0) error("Wo is %f <= 0\n%s",Wo,usage); endif if(Wo >= 1) error("Wo is %f >= 1\n%s",Wo,usage); endif oWt = 0; for i = 1 : length(Wt) if(Wt(i) <= 0) error("Wt(%d) is %f <= 0\n%s",i,Wt(i),usage); endif if(Wt(i) >= 1) error("Wt(%d) is %f >= 1\n%s",i,Wt(i),usage); endif if(Wt(i) <= oWt) error("Wt(%d) = %f, not monotonically increasing\n%s",i,Wt(i),usage); else oWt = Wt(i); endif endfor ## B(z) ## Inputs B,A specify the low pass IIR prototype filter G(z) = ---- . ## A(z) ## This module transforms G(z) into a multiband filter using the iterative ## algorithm from: ## [FFM] G. Feyh, J. Franchitti, and C. Mullis, "All-Pass Filter ## Interpolation and Frequency Transformation Problem", Proceedings 20th ## Asilomar Conference on Signals, Systems and Computers, Nov. 1986, pp. ## 164-168, IEEE. ## [FFM] moves the prototype filter position at normalized angular frequency ## .5*pi to the places specified in the Wt vector times pi. In this module, ## a generalization allows the position to be moved on the prototype filter ## to be specified as Wo*pi instead of being fixed at .5*pi. This is ## implemented using two successive allpass transformations. ## KK(z) ## In the first stage, find allpass J(z) = ---- such that ## K(z) ## jWo*pi -j.5*pi ## J(e ) = e (low pass to low pass transformation) ## ## PP(z) ## In the second stage, find allpass H(z) = ---- such that ## P(z) ## jWt(k)*pi -j(2k - 1)*.5*pi ## H(e ) = e (low pass to multiband transformation) ## ## ^ ## The variable PP used here corresponds to P in [FFM]. ## len = length(P(z)) == length(PP(z)), the number of polynomial coefficients ## ## len 1-i len 1-i ## P(z) = SUM P(i)z ; PP(z) = SUM PP(i)z ; PP(i) == P(len + 1 - i) ## i=1 i=1 (allpass condition) ## Note: (len - 1) == n in [FFM] eq. 3 ## ## The first stage computes the denominator of an allpass for translating ## from a prototype with position .5 to one with a position of Wo. It has the ## form: ## -1 ## K(2) - z ## ----------- ## -1 ## 1 - K(2)z ## ## From the low pass to low pass transformation in Table 7.1 p. 529 of A. ## Oppenheim and R. Schafer, Discrete-Time Signal Processing 3rd edition, ## Prentice Hall 2010, one can see that the denominator of an allpass for ## going in the opposite direction can be obtained by a sign reversal of the ## second coefficient, K(2), of the vector K (the index 2 not to be confused ## with a value of z, which is implicit). ## The first stage allpass denominator computation K = apd([pi * Wo]); ## The second stage allpass computation phi = pi * Wt; # vector of normalized angular frequencies between 0 and pi P = apd(phi); # calculate denominator of allpass for this target vector PP = revco(P); # numerator of allpass has reversed coefficients of P ## The total allpass filter from the two consecutive stages can be written as ## PP ## K(2) - --- ## P P ## ----------- * --- ## PP P ## 1 - K(2)--- ## P AllpassDen = P - (K(2) * PP); AllpassDen /= AllpassDen(1); # normalize AllpassNum = pass_stop * revco(AllpassDen); [Num,Den] = transform(B,A,AllpassNum,AllpassDen,pass_stop); endfunction function [Num,Den] = transform(B,A,PP,P,pass_stop) ## Given G(Z) = B(Z)/A(Z) and allpass H(z) = PP(z)/P(z), compute G(H(z)) ## For Pass = 'pass', transformed filter is: ## 2 nb-1 ## B1 + B2(PP/P) + B3(PP/P)^ + ... + Bnb(PP/P)^ ## ------------------------------------------------- ## 2 na-1 ## A1 + A2(PP/P) + A3(PP/P)^ + ... + Ana(PP/P)^ ## For Pass = 'stop', use powers of (-PP/P) ## na = length(A); # the number of coefficients in A nb = length(B); # the number of coefficients in B ## common low pass iir filters have na == nb but in general might not n = max(na,nb); # the greater of the number of coefficients ## n-1 ## Multiply top and bottom by P^ yields: ## ## n-1 n-2 2 n-3 nb-1 n-nb ## B1(P^ ) + B2(PP)(P^ ) + B3(PP^ )(P^ ) + ... + Bnb(PP^ )(P^ ) ## --------------------------------------------------------------------- ## n-1 n-2 2 n-3 na-1 n-na ## A1(P^ ) + A2(PP)(P^ ) + A3(PP^ )(P^ ) + ... + Ana(PP^ )(P^ ) ## Compute and store powers of P as a matrix of coefficients because we will ## need to use them in descending power order global Ppower; # to hold coefficients of powers of P, access inside ppower() np = length(P); powcols = np + (np-1)*(n-2); # number of coefficients in P^(n-1) ## initialize to "Not Available" with n-1 rows for powers 1 to (n-1) and ## the number of columns needed to hold coefficients for P^(n-1) Ppower = NA(n-1,powcols); Ptemp = P; # start with P to the 1st power for i = 1 : n-1 # i is the power for j = 1 : length(Ptemp) # j is the coefficient index for this power Ppower(i,j) = Ptemp(j); endfor Ptemp = conv(Ptemp,P); # increase power of P by one endfor ## Compute numerator and denominator of transformed filter Num = []; Den = []; for i = 1 : n ## n-i ## Regenerate P^ (p_pownmi) if((n-i) == 0) p_pownmi = [1]; else p_pownmi = ppower(n-i,powcols); endif ## i-1 ## Regenerate PP^ (pp_powim1) if(i == 1) pp_powim1 = [1]; else pp_powim1 = revco(ppower(i-1,powcols)); endif if(i <= nb) Bterm = (pass_stop^(i-1))*B(i)*conv(pp_powim1,p_pownmi); Num = polysum(Num,Bterm); endif if(i <= na) Aterm = (pass_stop^(i-1))*A(i)*conv(pp_powim1,p_pownmi); Den = polysum(Den,Aterm); endif endfor ## Scale both numerator and denominator to have Den(1) = 1 temp = Den(1); for i = 1 : length(Den) Den(i) = Den(i) / temp; endfor for i = 1 : length(Num) Num(i) = Num(i) / temp; endfor endfunction function P = apd(phi) # all pass denominator ## Given phi, a vector of normalized angular frequency transformation targets, ## return P, the denominator of an allpass H(z) lenphi = length(phi); Pkm1 = 1; # P0 initial condition from [FFM] eq. 22 for k = 1 : lenphi P = pk(Pkm1, k, phi(k)); # iterate Pkm1 = P; endfor endfunction function Pk = pk(Pkm1, k, phik) # kth iteration of P(z) ## Given Pkminus1, k, and phi(k) in radians , return Pk ## ## From [FFM] eq. 19 : k ## Pk = (z+1 )sin(phi(k)/2)Pkm1 - (-1) (z-1 )cos(phi(k)/2)PPkm1 ## Factoring out z ## -1 k -1 ## = z((1+z )sin(phi(k)/2)Pkm1 - (-1) (1-z )cos(phi(k)/2)PPkm1) ## PPk can also have z factored out. In H=PP/P, z in PPk will cancel z in Pk, ## so just leave out. Use ## -1 k -1 ## PK = (1+z )sin(phi(k)/2)Pkm1 - (-1) (1-z )cos(phi(k)/2)PPkm1 ## (expand) k ## = sin(phi(k)/2)Pkm1 - (-1) cos(phi(k)/2)PPkm1 ## ## -1 k -1 ## + z sin(phi(k)/2)Pkm1 + (-1) z cos(phi(k)/2)PPkm1 Pk = zeros(1,k+1); # there are k+1 coefficients in Pk sin_k = sin(phik/2); cos_k = cos(phik/2); for i = 1 : k Pk(i) += sin_k * Pkm1(i) - ((-1)^k * cos_k * Pkm1(k+1-i)); ## ## -1 ## Multiplication by z just shifts by one coefficient Pk(i+1) += sin_k * Pkm1(i) + ((-1)^k * cos_k * Pkm1(k+1-i)); endfor ## now normalize to Pk(1) = 1 (again will cancel with same factor in PPk) Pk1 = Pk(1); for i = 1 : k+1 Pk(i) = Pk(i) / Pk1; endfor endfunction function PP = revco(p) # reverse components of vector l = length(p); for i = 1 : l PP(l + 1 - i) = p(i); endfor endfunction function p = ppower(i,powcols) # Regenerate ith power of P from stored PPower global Ppower if(i == 0) p = 1; else p = []; for j = 1 : powcols if(isna(Ppower(i,j))) break; endif p = horzcat(p, Ppower(i,j)); endfor endif endfunction function poly = polysum(p1,p2) # add polynomials of possibly different length n1 = length(p1); n2 = length(p2); if(n1 > n2) ## pad p2 p2 = horzcat(p2, zeros(1,n1-n2)); elseif(n2 > n1) ## pad p1 p1 = horzcat(p1, zeros(1,n2-n1)); endif poly = p1 + p2; endfunction ������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/impinvar.m������������������������������������������������������������������������0000644�0000000�0000000�00000012764�14673270174�012732� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 R.G.H. Eschauzier <reschauzier@yahoo.com> ## Copyright (C) 2011 CarnĂ« Draug <carandraug+dev@gmail.com> ## Copyright (C) 2011 Juan Pablo Carbajal <carbajal@ifi.uzh.ch> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{b_out}, @var{a_out}] =} impinvar (@var{b}, @var{a}, @var{fs}, @var{tol}) ## @deftypefnx {Function File} {[@var{b_out}, @var{a_out}] =} impinvar (@var{b}, @var{a}, @var{fs}) ## @deftypefnx {Function File} {[@var{b_out}, @var{a_out}] =} impinvar (@var{b}, @var{a}) ## Converts analog filter with coefficients @var{b} and @var{a} to digital, ## conserving impulse response. ## ## If @var{fs} is not specified, or is an empty vector, it defaults to 1Hz. ## ## If @var{tol} is not specified, it defaults to 0.0001 (0.1%) ## This function does the inverse of impinvar so that the following example should ## restore the original values of @var{a} and @var{b}. ## ## @command{invimpinvar} implements the reverse of this function. ## @example ## [b, a] = impinvar (b, a); ## [b, a] = invimpinvar (b, a); ## @end example ## ## Reference: Thomas J. Cavicchi (1996) ``Impulse invariance and multiple-order ## poles''. IEEE transactions on signal processing, Vol 44 (9): 2344--2347 ## ## @seealso{bilinear, invimpinvar} ## @end deftypefn function [b_out, a_out] = impinvar (b_in, a_in, fs = 1, tol = 0.0001) if (nargin <2) print_usage; endif ## to be compatible with the matlab implementation where an empty vector can ## be used to get the default if (isempty(fs)) ts = 1; else ts = 1/fs; # we should be using sampling frequencies to be compatible with Matlab endif [r_in, p_in, k_in] = residue(b_in, a_in); # partial fraction expansion n = length(r_in); # Number of poles/residues if (length(k_in)>0) # Greater than zero means we cannot do impulse invariance error("Order numerator >= order denominator"); endif r_out = zeros(1,n); # Residues of H(z) p_out = zeros(1,n); # Poles of H(z) k_out = 0; # Constant term of H(z) i=1; while (i<=n) m = 1; first_pole = p_in(i); # Pole in the s-domain while (i<n && abs(first_pole-p_in(i+1))<tol) # Multiple poles at p(i) i++; # Next residue m++; # Next multiplicity endwhile [r, p, k] = z_res(r_in(i-m+1:i), first_pole, ts); # Find z-domain residues k_out += k; # Add direct term to output p_out(i-m+1:i) = p; # Copy z-domain pole(s) to output r_out(i-m+1:i) = r; # Copy z-domain residue(s) to output i++; # Next s-domain residue/pole endwhile [b_out, a_out] = inv_residue(r_out, p_out, k_out, tol); a_out = to_real(a_out); # Get rid of spurious imaginary part b_out = to_real(b_out); ## Shift results right to account for calculating in z instead of z^-1 b_out(end)=[]; endfunction ## Convert residue vector for single and multiple poles in s-domain (located at sm) to ## residue vector in z-domain. The variable k is the direct term of the result. function [r_out, p_out, k_out] = z_res (r_in, sm, ts) p_out = exp(ts * sm); # z-domain pole n = length(r_in); # Multiplicity of the pole r_out = zeros(1,n); # Residue vector ## First pole (no multiplicity) k_out = r_in(1) * ts; # PFE of z/(z-p) = p/(z-p)+1; direct part r_out(1) = r_in(1) * ts * p_out; # pole part of PFE for i=(2:n) # Go through s-domain residues for multiple pole r_out(1:i) += r_in(i) * polyrev(h1_z_deriv(i-1, p_out, ts)); # Add z-domain residues endfor endfunction %!function err = stozerr(bs,as,fs) %! %! # number of time steps %! n=100; %! %! # impulse invariant transform to z-domain %! [bz az]=impinvar(bs,as,fs); %! %! # create sys object of transfer function %! s=tf(bs,as); %! %! # calculate impulse response of continuous time system %! # at discrete time intervals 1/fs %! ys=impulse(s,(n-1)/fs,1/fs)'; %! %! # impulse response of discrete time system %! yz=filter(bz,az,[1 zeros(1,n-1)]); %! %! # find rms error %! err=sqrt(sum((yz*fs-ys).^2)/length(ys)); %! endfunction %! %!assert(stozerr([1],[1 1],100),0,0.0001); %!assert(stozerr([1],[1 2 1],100),0,0.0001); ## FIXME: The following test needs a wider tolerance on some systems ## (arm64, i386, powerpc). Is this a problem in this function or ## in the control package that needs to be fixed? %!assert(stozerr([1 1],[1 2 1],100),0,0.0002); %!assert(stozerr([1],[1 3 3 1],100),0,0.0001); %!assert(stozerr([1 1],[1 3 3 1],100),0,0.0001); %!assert(stozerr([1 1 1],[1 3 3 1],100),0,0.0001); %!assert(stozerr([1],[1 0 1],100),0,0.0001); %!assert(stozerr([1 1],[1 0 1],100),0,0.0001); %!assert(stozerr([1],[1 0 2 0 1],100),0,0.0001); %!assert(stozerr([1 1],[1 0 2 0 1],100),0,0.0001); %!assert(stozerr([1 1 1],[1 0 2 0 1],100),0,0.0001); %!assert(stozerr([1 1 1 1],[1 0 2 0 1],100),0,0.0001); ������������signal-1.4.6/inst/impz.m����������������������������������������������������������������������������0000644�0000000�0000000�00000007600�14673270174�012055� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{x}, @var{t}] =} impz (@var{b}) ## @deftypefnx {Function File} {[@var{x}, @var{t}] =} impz (@var{b}, @var{a}) ## @deftypefnx {Function File} {[@var{x}, @var{t}] =} impz (@var{b}, @var{a}, @var{n}) ## @deftypefnx {Function File} {[@var{x}, @var{t}] =} impz (@var{b}, @var{a}, @var{n}, @var{fs}) ## @deftypefnx {Function File} {} impz (@dots{}) ## ## Generate impulse-response characteristics of the filter. The filter ## coefficients correspond to the the z-plane rational function with ## numerator b and denominator a. If a is not specified, it defaults to ## 1. If n is not specified, or specified as [], it will be chosen such ## that the signal has a chance to die down to -120dB, or to not explode ## beyond 120dB, or to show five periods if there is no significant ## damping. If no return arguments are requested, plot the results. ## ## @seealso{freqz, zplane} ## @end deftypefn ## FIXME: Call equivalent function from control toolbox since it is ## probably more sophisticated than this one, and since it ## is silly to maintain two different versions of essentially ## the same thing. function [x_r, t_r] = impz(b, a = [1], n = [], fs = 1) if nargin == 0 || nargin > 4 print_usage; endif if isempty(n) && length(a) > 1 precision = 1e-6; r = roots(a); maxpole = max(abs(r)); if (maxpole > 1+precision) # unstable -- cutoff at 120 dB n = floor(6/log10(maxpole)); elseif (maxpole < 1-precision) # stable -- cutoff at -120 dB n = floor(-6/log10(maxpole)); else # periodic -- cutoff after 5 cycles n = 30; ## find longest period less than infinity ## cutoff after 5 cycles (w=10*pi) rperiodic = r(find(abs(r)>=1-precision & abs(arg(r))>0)); if !isempty(rperiodic) n_periodic = ceil(10*pi./min(abs(arg(rperiodic)))); if (n_periodic > n) n = n_periodic; endif endif ## find most damped pole ## cutoff at -60 dB rdamped = r(find(abs(r)<1-precision)); if !isempty(rdamped) n_damped = floor(-3/log10(max(abs(rdamped)))); if (n_damped > n) n = n_damped; endif endif endif n = n + length(b); elseif isempty(n) n = length(b); elseif (! isscalar (n)) ## TODO: missing option of having N as a vector of values to ## compute the impulse response. error ("impz: N must be empty or a scalar"); endif if length(a) == 1 x = fftfilt(b/a, [1, zeros(1,n-1)]'); else x = filter(b, a, [1, zeros(1,n-1)]'); endif t = [0:n-1]/fs; if nargout >= 1 x_r = x; endif if nargout >= 2 t_r = t; endif if nargout == 0 unwind_protect title "Impulse Response"; if (fs > 1000) t = t * 1000; xlabel("Time (msec)"); else xlabel("Time (sec)"); endif plot(t, x, "^r;;"); unwind_protect_cleanup title ("") xlabel ("") end_unwind_protect endif endfunction %!assert (size (impz (1, [1 -1 0.9], 100)), [100 1]) ## Missing functionality %!xtest %! [h, t] = impz (1, [1 -1 0.9], 0:101); %! assert (size (h), [101 1]) %! assert (t, 0:101) ��������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/interp.m��������������������������������������������������������������������������0000644�0000000�0000000�00000004572�14673270174�012404� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} interp (@var{x}, @var{q}) ## @deftypefnx {Function File} {@var{y} =} interp (@var{x}, @var{q}, @var{n}) ## @deftypefnx {Function File} {@var{y} =} interp (@var{x}, @var{q}, @var{n}, @var{Wc}) ## ## Upsample the signal x by a factor of q, using an order 2*q*n+1 FIR ## filter. Note that q must be an integer for this rate change method. ## n defaults to 4 and Wc defaults to 0.5. ## ## Example ## @example ## @group ## # Generate a signal. ## t=0:0.01:2; x=chirp(t,2,.5,10,'quadratic')+sin(2*pi*t*0.4); ## y = interp(x(1:4:length(x)),4,4,1); # interpolate a sub-sample ## stem(t(1:121)*1000,x(1:121),"-g;Original;"); hold on; ## stem(t(1:121)*1000,y(1:121),"-r;Interpolated;"); ## stem(t(1:4:121)*1000,x(1:4:121),"-b;Subsampled;"); hold off; ## @end group ## @end example ## ## @seealso{decimate, resample} ## @end deftypefn function y = interp(x, q, n = 4, Wc = 0.5) if nargin < 1 || nargin > 4, print_usage; endif if q != fix(q), error("decimate only works with integer q."); endif if rows(x)>1 y = zeros(length(x)*q+q*n+1,1); else y = zeros(1,length(x)*q+q*n+1); endif y(1:q:length(x)*q) = x; b = fir1(2*q*n+1, Wc/q); y=q*fftfilt(b, y); y(1:q*n+1) = []; # adjust for zero filter delay endfunction %!demo %! ## Generate a signal. %! t=0:0.01:2; x=chirp(t,2,.5,10,'quadratic')+sin(2*pi*t*0.4); %! y = interp(x(1:4:length(x)),4,4,1); # interpolate a sub-sample %! plot(t(1:121)*1000,y(1:121),"r-+;Interpolated;"); hold on; %! stem(t(1:4:121)*1000,x(1:4:121),"ob;Original;"); hold off; %! %! % graph shows interpolated signal following through the %! % sample points of the original signal. ��������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/invfreq.m�������������������������������������������������������������������������0000644�0000000�0000000�00000021611�14673270174�012546� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1986, 2000, 2003 Julius O. Smith III <jos@ccrma.stanford.edu> ## Copyright (C) 2007 Rolf Schirmacher <Rolf.Schirmacher@MuellerBBM.de> ## Copyright (C) 2003 Andrew Fitting ## Copyright (C) 2010 Pascal Dupuis <Pascal.Dupuis@uclouvain.be> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[B,A] =} invfreq(H,F,nB,nA) ## @deftypefnx {} {[B,A] =} invfreq(H,F,nB,nA,W) ## @deftypefnx {} {[B,A] =} invfreq(H,F,nB,nA,W,[],[],plane) ## @deftypefnx {} {[B,A] =} invfreq(H,F,nB,nA,W,iter,tol,plane) ## Fit filter B(z)/A(z) or B(s)/A(s) to complex frequency response at ## frequency points F. ## ## A and B are real polynomial coefficients of order ## nA and nB respectively. Optionally, the fit-errors can be weighted vs ## frequency according to the weights W. Also, the transform plane can be ## specified as either 's' for continuous time or 'z' for discrete time. 'z' ## is chosen by default. Eventually, Steiglitz-McBride iterations will be ## specified by iter and tol. ## ## H: desired complex frequency response ## It is assumed that A and B are real polynomials, hence H is one-sided. ## ## F: vector of frequency samples in radians ## ## nA: order of denominator polynomial A ## ## nB: order of numerator polynomial B ## ## plane='z': F on unit circle (discrete-time spectra, z-plane design) ## ## plane='s': F on jw axis (continuous-time spectra, s-plane design) ## ## H(k) = spectral samples of filter frequency response at points zk, ## where zk=exp(sqrt(-1)*F(k)) when plane='z' (F(k) in [0,.5]) ## and zk=(sqrt(-1)*F(k)) when plane='s' (F(k) nonnegative) ## ## Example: ## @example ## [B,A] = butter(12,1/4); ## [H,w] = freqz(B,A,128); ## [Bh,Ah] = invfreq(H,F,4,4); ## Hh = freqz(Bh,Ah); ## disp(sprintf('||frequency response error|| = %f',norm(H-Hh))); ## @end example ## ## References: ## ## J. O. Smith, "Techniques for Digital Filter Design and System ## Identification with Application to the Violin, Ph.D. Dissertation, ## Elec. Eng. Dept., Stanford University, June 1983, page 50; or, ## ## http://ccrma.stanford.edu/~jos/filters/FFT_Based_Equation_Error_Method.html ## @end deftypefn ## FIXME: implement Steiglitz-McBride iterations ## FIXME: improve numerical stability for high order filters (matlab is a bit better) ## FIXME: modify to accept more argument configurations function [B, A, SigN] = invfreq(H, F, nB, nA, W, iter, tol, tr, plane, varargin) if length(nB) > 1, zB = nB(2); nB = nB(1); else zB = 0; endif n = max(nA, nB); m = n+1; mA = nA+1; mB = nB+1; nF = length(F); if nargin < 5 || isempty(W), W = ones(1, nF); endif if nargin < 6, iter = []; endif if nargin < 7 tol = []; endif if nargin < 8 || isempty(tr), tr = ''; endif if nargin < 9, plane = 'z'; endif if nargin < 10, varargin = {}; endif if (! strcmp (plane, "s") && ! strcmp (plane, "z")) error ("invfreq: invalid PLANE argument '%s', expected 's' or 'z'", plane) endif fname = ["invfreq", plane]; if (nF != length (H)) error ("%s: length of H and F must be the same\n", fname) endif if (! isempty (iter) || ! isempty (tol)) warning (["%s: iterative algorithm not yet implemented, ", ... "ITER and TOL arguments are ignored\n"], fname); endif [reg, prop ] = parseparams(varargin); ## should we normalize freqs to avoid matrices with rank deficiency ? norm = false; ## by default, use Ordinary Least Square to solve normal equations method = 'LS'; if length(prop) > 0 indi = 1; while indi <= length(prop) switch prop{indi} case 'norm' if indi < length(prop) && ~ischar(prop{indi+1}), norm = logical(prop{indi+1}); prop(indi:indi+1) = []; continue else norm = true; prop(indi) = []; continue endif case 'method' if indi < length(prop) && ischar(prop{indi+1}), method = prop{indi+1}; prop(indi:indi+1) = []; continue else error('invfreq.m: incorrect/missing method argument'); endif otherwise # FIXME: just skip it for now disp(sprintf("Ignoring unknown argument %s", varargin{indi})); indi = indi + 1; endswitch endwhile endif Ruu = zeros(mB, mB); Ryy = zeros(nA, nA); Ryu = zeros(nA, mB); Pu = zeros(mB, 1); Py = zeros(nA,1); if strcmp(tr,'trace') disp(' ') disp('Computing nonuniformly sampled, equation-error, rational filter.'); disp(['plane = ',plane]); disp(' ') endif s = sqrt(-1)*F; switch plane case 'z' if max(F) > pi || min(F) < 0 disp('hey, you frequency is outside the range 0 to pi, making my own') F = linspace(0, pi, length(H)); s = sqrt(-1)*F; endif s = exp(-s); case 's' if max(F) > 1e6 && n > 5, if ~norm, disp('Be careful, there are risks of generating singular matrices'); disp('Call invfreqs as (..., "norm", true) to avoid it'); else Fmax = max(F); s = sqrt(-1)*F/Fmax; endif endif endswitch for k=1:nF, Zk = (s(k).^[0:n]).'; Hk = H(k); aHks = Hk*conj(Hk); Rk = (W(k)*Zk)*Zk'; rRk = real(Rk); Ruu = Ruu + rRk(1:mB, 1:mB); Ryy = Ryy + aHks*rRk(2:mA, 2:mA); Ryu = Ryu + real(Hk*Rk(2:mA, 1:mB)); Pu = Pu + W(k)*real(conj(Hk)*Zk(1:mB)); Py = Py + (W(k)*aHks)*real(Zk(2:mA)); endfor Rr = ones(length(s), mB+nA); Zk = s; for k = 1:min(nA, nB), Rr(:, 1+k) = Zk; Rr(:, mB+k) = -Zk.*H; Zk = Zk.*s; endfor for k = 1+min(nA, nB):max(nA, nB)-1, if k <= nB, Rr(:, 1+k) = Zk; endif if k <= nA, Rr(:, mB+k) = -Zk.*H; endif Zk = Zk.*s; endfor k = k+1; if k <= nB, Rr(:, 1+k) = Zk; endif if k <= nA, Rr(:, mB+k) = -Zk.*H; endif ## complex to real equation system -- this ensures real solution Rr = Rr(:, 1+zB:end); Rr = [real(Rr); imag(Rr)]; Pr = [real(H(:)); imag(H(:))]; ## normal equations -- keep for ref ## Rn= [Ruu(1+zB:mB, 1+zB:mB), -Ryu(:, 1+zB:mB)'; -Ryu(:, 1+zB:mB), Ryy]; ## Pn= [Pu(1+zB:mB); -Py]; switch method case {'ls' 'LS'} ## avoid scaling errors with Theta = R\P; ## [Q, R] = qr([Rn Pn]); Theta = R(1:end, 1:end-1)\R(1:end, end); [Q, R] = qr([Rr Pr], 0); Theta = R(1:end-1, 1:end-1)\R(1:end-1, end); ## SigN = R(end, end-1); SigN = R(end, end); case {'tls' 'TLS'} ## [U, S, V] = svd([Rn Pn]); ## SigN = S(end, end-1); ## Theta = -V(1:end-1, end)/V(end, end); [U, S, V] = svd([Rr Pr], 0); SigN = S(end, end); Theta = -V(1:end-1, end)/V(end, end); case {'mls' 'MLS' 'qr' 'QR'} ## [Q, R] = qr([Rn Pn], 0); ## solve the noised part -- DO NOT USE ECONOMY SIZE ! ## [U, S, V] = svd(R(nA+1:end, nA+1:end)); ## SigN = S(end, end-1); ## Theta = -V(1:end-1, end)/V(end, end); ## unnoised part -- remove B contribution and back-substitute ## Theta = [R(1:nA, 1:nA)\(R(1:nA, end) - R(1:nA, nA+1:end-1)*Theta) ## Theta]; ## solve the noised part -- economy size OK as #rows > #columns [Q, R] = qr([Rr Pr], 0); eB = mB-zB; sA = eB+1; [U, S, V] = svd(R(sA:end, sA:end)); ## noised (A) coefficients Theta = -V(1:end-1, end)/V(end, end); ## unnoised (B) part -- remove A contribution and back-substitute Theta = [R(1:eB, 1:eB)\(R(1:eB, end) - R(1:eB, sA:end-1)*Theta) Theta]; SigN = S(end, end); otherwise error("invfreq: unknown method %s", method); endswitch B = [zeros(zB, 1); Theta(1:mB-zB)].'; A = [1; Theta(mB-zB+(1:nA))].'; if strcmp(plane,'s') B = B(mB:-1:1); A = A(mA:-1:1); if norm, # Frequencies were normalized -- unscale coefficients Zk = Fmax.^[n:-1:0].'; for k = nB:-1:1+zB, B(k) = B(k)/Zk(k); endfor for k = nA:-1:1, A(k) = A(k)/Zk(k); endfor endif endif endfunction %!demo %! order = 6; # order of test filter %! fc = 1/2; # sampling rate / 4 %! n = 128; # frequency grid size %! [B, A] = butter(order,fc); %! [H, w] = freqz(B,A,n); %! [Bh, Ah] = invfreq(H,w,order,order); %! [Hh, wh] = freqz(Bh,Ah,n); %! plot(w,[abs(H), abs(Hh)]) %! xlabel("Frequency (rad/sample)"); %! ylabel("Magnitude"); %! legend('Original','Measured'); %! err = norm(H-Hh); %! disp(sprintf('L2 norm of frequency response error = %f',err)); �����������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/invfreqs.m������������������������������������������������������������������������0000644�0000000�0000000�00000006516�14673270174�012740� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1986, 2003 Julius O. Smith III <jos@ccrma.stanford.edu> ## Copyright (C) 2003 Andrew Fitting ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[B,A] =} invfreqs(H,F,nB,nA) ## @deftypefnx {} {[B,A] =} invfreqs(H,F,nB,nA,W) ## @deftypefnx {} {[B,A] =} invfreqs(H,F,nB,nA,W,iter,tol,'trace') ## Fit filter B(s)/A(s)to the complex frequency response H at frequency ## points F. ## ## A and B are real polynomial coefficients of order nA and nB. ## ## Optionally, the fit-errors can be weighted vs frequency according to ## the weights W. ## ## Note: all the guts are in invfreq.m ## ## H: desired complex frequency response ## ## F: frequency (must be same length as H) ## ## nA: order of the denominator polynomial A ## ## nB: order of the numerator polynomial B ## ## W: vector of weights (must be same length as F) ## ## Example: ## @example ## B = [1/2 1]; ## A = [1 1]; ## w = linspace(0,4,128); ## H = freqs(B,A,w); ## [Bh,Ah] = invfreqs(H,w,1,1); ## Hh = freqs(Bh,Ah,w); ## plot(w,[abs(H);abs(Hh)]) ## legend('Original','Measured'); ## err = norm(H-Hh); ## disp(sprintf('L2 norm of frequency response error = %f',err)); ## @end example ## @end deftypefn ## FIXME: check invfreq.m for todo's function [B, A, SigN] = invfreqs(H,F,nB,nA,W,iter,tol,tr, varargin) if nargin < 9 varargin = {}; if nargin < 8 tr = ''; if nargin < 7 tol = []; if nargin < 6 iter = []; if nargin < 5 W = ones(1,length(F)); endif endif endif endif endif ## now for the real work [B, A, SigN] = invfreq(H, F,nB, nA, W, iter, tol, tr, 's', varargin{:}); endfunction %!demo %! B = [1/2 1]; %! B = [1 0 0]; %! A = [1 1]; %! ##A = [1 36 630 6930 51975 270270 945945 2027025 2027025]/2027025; %! A = [1 21 210 1260 4725 10395 10395]/10395; %! A = [1 6 15 15]/15; %! w = linspace(0, 8, 128); %! H0 = freqs(B, A, w); %! Nn = (randn(size(w))+j*randn(size(w)))/sqrt(2); %! order = length(A) - 1; %! [Bh, Ah, Sig0] = invfreqs(H0, w, [length(B)-1 2], length(A)-1); %! Hh = freqs(Bh,Ah,w); %! [BLS, ALS, SigLS] = invfreqs(H0+1e-5*Nn, w, [2 2], order, [], [], [], [], "method", "LS"); %! HLS = freqs(BLS, ALS, w); %! [BTLS, ATLS, SigTLS] = invfreqs(H0+1e-5*Nn, w, [2 2], order, [], [], [], [], "method", "TLS"); %! HTLS = freqs(BTLS, ATLS, w); %! [BMLS, AMLS, SigMLS] = invfreqs(H0+1e-5*Nn, w, [2 2], order, [], [], [], [], "method", "QR"); %! HMLS = freqs(BMLS, AMLS, w); %! plot(w,[abs(H0); abs(Hh)]) %! xlabel("Frequency (rad/sec)"); %! ylabel("Magnitude"); %! legend('Original','Measured'); %! err = norm(H0-Hh); %! disp(sprintf('L2 norm of frequency response error = %f',err)); ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/invfreqz.m������������������������������������������������������������������������0000644�0000000�0000000�00000006273�14673270174�012747� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1986, 2003 Julius O. Smith III <jos@ccrma.stanford.edu> ## Copyright (C) 2003 Andrew Fitting ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[B,A] =} invfreqz(H,F,nB,nA) ## @deftypefnx {} {[B,A] =} invfreqz(H,F,nB,nA,W) ## @deftypefnx {} {[B,A] =} invfreqz(H,F,nB,nA,W,iter,tol,'trace') ## Fit filter B(z)/A(z)to the complex frequency response H at frequency ## points F. ## ## A and B are real polynomial coefficients of order nA and nB. ## Optionally, the fit-errors can be weighted vs frequency according to ## the weights W. ## ## Note: all the guts are in invfreq.m ## ## H: desired complex frequency response ## ## F: normalized frequency (0 to pi) (must be same length as H) ## ## nA: order of the denominator polynomial A ## ## nB: order of the numerator polynomial B ## ## W: vector of weights (must be same length as F) ## ## Example: ## @example ## [B,A] = butter(4,1/4); ## [H,F] = freqz(B,A); ## [Bh,Ah] = invfreq(H,F,4,4); ## Hh = freqz(Bh,Ah); ## disp(sprintf('||frequency response error|| = %f',norm(H-Hh))); ## @end example ## @end deftypefn ## FIXME: check invfreq.m for todo's function [B, A, SigN] = invfreqz(H, F, nB, nA, W, iter, tol, tr, varargin) if nargin < 9 varargin = {}; if nargin < 8 tr = ''; if nargin < 7 tol = []; if nargin < 6 iter = []; if nargin < 5 W = ones(1,length(F)); endif endif endif endif endif ## now for the real work [B, A, SigN] = invfreq(H, F, nB, nA, W, iter, tol, tr, 'z', varargin{:}); endfunction %!demo %! order = 9; # order of test filter %! # going to 10 or above leads to numerical instabilities and large errors %! fc = 1/2; # sampling rate / 4 %! n = 128; # frequency grid size %! [B0, A0] = butter(order, fc); %! [H0, w] = freqz(B0, A0, n); %! Nn = (randn(size(w))+j*randn(size(w)))/sqrt(2); %! [Bh, Ah, Sig0] = invfreqz(H0, w, order, order); %! [Hh, wh] = freqz(Bh, Ah, n); %! [BLS, ALS, SigLS] = invfreqz(H0+1e-5*Nn, w, order, order, [], [], [], [], "method", "LS"); %! HLS = freqz(BLS, ALS, n); %! [BTLS, ATLS, SigTLS] = invfreqz(H0+1e-5*Nn, w, order, order, [], [], [], [], "method", "TLS"); %! HTLS = freqz(BTLS, ATLS, n); %! [BMLS, AMLS, SigMLS] = invfreqz(H0+1e-5*Nn, w, order, order, [], [], [], [], "method", "QR"); %! HMLS = freqz(BMLS, AMLS, n); %! plot(w,[abs(H0) abs(Hh)]) %! xlabel("Frequency (rad/sample)"); %! ylabel("Magnitude"); %! legend('Original','Measured'); %! err = norm(H0-Hh); %! disp(sprintf('L2 norm of frequency response error = %f',err)); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/invimpinvar.m���������������������������������������������������������������������0000644�0000000�0000000�00000012657�14673270174�013450� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 R.G.H. Eschauzier <reschauzier@yahoo.com> ## Copyright (C) 2011 CarnĂ« Draug <carandraug+dev@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{b_out}, @var{a_out}] =} invimpinvar (@var{b}, @var{a}, @var{fs}, @var{tol}) ## @deftypefnx {Function File} {[@var{b_out}, @var{a_out}] =} invimpinvar (@var{b}, @var{a}, @var{fs}) ## @deftypefnx {Function File} {[@var{b_out}, @var{a_out}] =} invimpinvar (@var{b}, @var{a}) ## Converts digital filter with coefficients @var{b} and @var{a} to analog, ## conserving impulse response. ## ## This function does the inverse of impinvar so that the following example should ## restore the original values of @var{a} and @var{b}. ## @example ## [b, a] = impinvar (b, a); ## [b, a] = invimpinvar (b, a); ## @end example ## ## If @var{fs} is not specified, or is an empty vector, it defaults to 1Hz. ## ## If @var{tol} is not specified, it defaults to 0.0001 (0.1%) ## ## Reference: Thomas J. Cavicchi (1996) ``Impulse invariance and multiple-order ## poles''. IEEE transactions on signal processing, Vol 40 (9): 2344--2347 ## ## @seealso{bilinear, impinvar} ## @end deftypefn ## Impulse invariant conversion from s to z domain function [b_out, a_out] = invimpinvar (b_in, a_in, fs = 1, tol = 0.0001) if (nargin <2) print_usage; endif ## to be compatible with the matlab implementation where an empty vector can ## be used to get the default if (isempty(fs)) ts = 1; else ts = 1/fs; # we should be using sampling frequencies to be compatible with Matlab endif b_in = [b_in 0]; # so we can calculate in z instead of z^-1 [r_in, p_in, k_in] = residue(b_in, a_in); # partial fraction expansion n = length(r_in); # Number of poles/residues if (length(k_in) > 1) # Greater than one means we cannot do impulse invariance error("Order numerator > order denominator"); endif r_out = zeros(1,n); # Residues of H(s) sm_out = zeros(1,n); # Poles of H(s) i=1; while (i<=n) m=1; first_pole = p_in(i); # Pole in the z-domain while (i<n && abs(first_pole-p_in(i+1))<tol) # Multiple poles at p(i) i++; # Next residue m++; # Next multiplicity endwhile [r, sm, k] = inv_z_res(r_in(i-m+1:i), first_pole, ts); # Find s-domain residues k_in -= k; # Just to check, should end up zero for physical system sm_out(i-m+1:i) = sm; # Copy s-domain pole(s) to output r_out(i-m+1:i) = r; # Copy s-domain residue(s) to output i++; # Next z-domain residue/pole endwhile [b_out, a_out] = inv_residue(r_out, sm_out , 0, tol); a_out = to_real(a_out); # Get rid of spurious imaginary part b_out = to_real(b_out); b_out = polyreduce(b_out); endfunction ## Inverse function of z_res (see impinvar source) function [r_out sm_out k_out] = inv_z_res (r_in,p_in,ts) n = length(r_in); # multiplicity of the pole r_in = r_in.'; # From column vector to row vector j=n; while (j>1) # Go through residues starting from highest order down r_out(j) = r_in(j) / ((ts * p_in)^j); # Back to binomial coefficient for highest order (always 1) r_in(1:j) -= r_out(j) * polyrev(h1_z_deriv(j-1,p_in,ts)); # Subtract highest order result, leaving r_in(j) zero j--; endwhile ## Single pole (no multiplicity) r_out(1) = r_in(1) / ((ts * p_in)); k_out = r_in(1) / p_in; sm_out = log(p_in) / ts; endfunction %!function err = ztoserr(bz,az,fs) %! %! # number of time steps %! n=100; %! %! # make sure system is realizable (no delays) %! bz=prepad(bz,length(az)-1,0,2); %! %! # inverse impulse invariant transform to s-domain %! [bs as]=invimpinvar(bz,az,fs); %! %! # create sys object of transfer function %! s=tf(bs,as); %! %! # calculate impulse response of continuous time system %! # at discrete time intervals 1/fs %! ys=impulse(s,(n-1)/fs,1/fs)'; %! %! # impulse response of discrete time system %! yz=filter(bz,az,[1 zeros(1,n-1)]); %! %! # find rms error %! err=sqrt(sum((yz*fs-ys).^2)/length(ys)); %! endfunction %! %!assert(ztoserr([1],[1 -0.5],0.01),0,0.0001); %!assert(ztoserr([1],[1 -1 0.25],0.01),0,0.0001); %!assert(ztoserr([1 1],[1 -1 0.25],0.01),0,0.0001); %!assert(ztoserr([1],[1 -1.5 0.75 -0.125],0.01),0,0.0001); %!assert(ztoserr([1 1],[1 -1.5 0.75 -0.125],0.01),0,0.0001); %!assert(ztoserr([1 1 1],[1 -1.5 0.75 -0.125],0.01),0,0.0001); %!assert(ztoserr([1],[1 0 0.25],0.01),0,0.0001); %!assert(ztoserr([1 1],[1 0 0.25],0.01),0,0.0001); %!assert(ztoserr([1],[1 0 0.5 0 0.0625],0.01),0,0.0001); %!assert(ztoserr([1 1],[1 0 0.5 0 0.0625],0.01),0,0.0001); %!assert(ztoserr([1 1 1],[1 0 0.5 0 0.0625],0.01),0,0.0001); %!assert(ztoserr([1 1 1 1],[1 0 0.5 0 0.0625],0.01),0,0.0001); ���������������������������������������������������������������������������������signal-1.4.6/inst/isallpass.m�����������������������������������������������������������������������0000644�0000000�0000000�00000006761�14673270174�013100� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2023 Leonardo Araujo <leolca@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{L} = } isallpass (@var{b}, @var{a}) ## @deftypefnx {Function File} {@var{L} = } isallpass (@var{sos}) ## ## Determine whether a digital filter is allpass. The filter might be defined ## by the numerator coefficients, @var{b}, and the denominator coefficients, ## @var{a}, or, alternatively, by a matrix of second-order sections, @var{sos}. ## ## Example: ## @example ## a = [1 2 3]; ## b = [3 2 1]; ## isallpass (b, a) ## @end example ## ## Ref [1] Shyu, Jong-Jy, & Pei, Soo-Chang, ## A new approach to the design of complex all-pass IIR digital filters, ## Signal Processing, 40(2–3), 207–215, 1994. ## https://doi.org/10.1016/0165-1684(94)90068-x ## ## Ref [2] Vaidyanathan, P. P. Multirate Systems and Filter Banks. ## 1st edition, Pearson College Div, 1992. ## @end deftypefn function flag = isallpass (b, a) if (nargin < 1 || nargin > 2 ) print_usage; endif if (nargin == 2 && ( ! isrow (a) || ! isrow (b) )) error ( "coefficient array should be a row vector" ); endif if (nargin == 1 && ! all(size (b) > [1 1]) ) error ( "a valid second-order section representation should be given" ); endif if nargin == 2 && !all(size (b) == size (a)), flag = false; return; elseif (nargin == 2 && isrow (a) && isrow (b)) # remove leading and trailing zeros b = b(find (b, 1):end); a = a(find (a, 1):end); b = b(1:find (b,1,"last")); a = a(1:find (a,1,"last")); # normalize b = b./b(end); a = a./a(1); flag = (all(b == fliplr (conj(a))) || all(b == -fliplr (conj(a)))); elseif (nargin == 1 && all(size (b) > [1 1])) [b, a] = sos2tf (b); flag = isallpass (b, a); endif endfunction %!demo %! # H(z) = (b1 - z^-1) * (b2 - z^-1) / ((1 - b1*z^-1) * (1 - b2*z^-1)) %! b1 = 0.5 * (1 + i); %! b2 = 0.7 * (cos (pi/6) + i*sin (pi/6)); %! b = conv ([b1 -1], [b2 -1]); %! a = conv ([1 (-1)*conj(b1)],[1 (-1)*conj(b2)]); %! freqz (b, a); %! f = isallpass (b, a) %! ## test input validation %!error n = isallpass () %!error n = isallpass (1) %!error n = isallpass (1, 1, 1) %!error n = isallpass (1, 1, 1, 1) %!error n = isallpass (1, 1, 1, 1, 1) %!error n = isallpass ([1:10]', 1) %!error n = isallpass (1, [1:10]') %!error n = isallpass ([1:10]', [1:10]') %!error n = isallpass (1:10, 1:10, 1:10) %!error n = isallpass (ones (3), ones (3)) %!test %! b = [(1+i)/2 -1]; %! a = [1 -(1-i)/2]; %! f = isallpass (b, a); %! assert (f, true) %!test %! b = [(1+i)/2 -1]; %! a = [-1 (1-i)/2]; %! f = isallpass (b, a); %! assert (f, true) %!test %! [b, a] = butter (1, 0.5); %! f = isallpass (b, a); %! assert (f, false) %!test %! b1 = 0.5 * (1 + i); %! b2 = 0.7 * (cos (pi/6) + i*sin (pi/6)); %! b = conv ([b1 -1], [b2 -1]); %! a = conv ([1 -conj(b1)],[1, -conj(b2)]); %! f = isallpass (b, a); %! assert (f, true) ���������������signal-1.4.6/inst/ismaxphase.m����������������������������������������������������������������������0000644�0000000�0000000�00000007312�14673270174�013240� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2023 Leonardo Araujo <leolca@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{L} = } ismaxphase (@var{b}, @var{a}) ## @deftypefnx {Function File} {@var{L} = } ismaxphase (@var{sos}) ## @deftypefnx {Function File} {@var{L} = } ismaxphase (@dots{}, @var{tol}) ## ## Determine whether a digital filter is maximum phase (maximum energy-delay). ## The filter might be defined by the numerator coefficients, @var{b}, and the ## denominator coefficients, @var{a}, or, alternatively, by a matrix of ## second-order sections, @var{sos}. A tolerance @var{tol} might be given to ## define when two numbers are close enough to be considered equal. ## ## Example: ## @example ## b = [1 2 4 4 2 1]; ## zplane (b); ## ismaxphase (b) ## @end example ## ## Ref [1] Oppenheim, Alan, and Ronald Schafer. Discrete-Time Signal Processing. ## 3rd edition, Pearson, 2009. ## @end deftypefn function flag = ismaxphase (b, a, tol) if (nargin < 1 || nargin > 3 ) print_usage; endif if (nargin == 2 && ( ! isrow (a) || ! isrow (b) )) error ( "coefficient array should be a row vector" ); endif if (nargin == 1 && isrow (b)) a = 1; endif if nargin < 3 tol = eps^(3/4); elseif length (tol) > 1 error ( "a scalar is expected as the tolerance value" ); endif if (nargin > 1 && isrow (a) && isrow (b)) || (nargin == 1 && isrow (b)) zm = abs (roots (b)); pm = abs (roots (a)); # Zeros of a maximum phase filter are constrained to lie outside the unit circle. # The filter should be stable (poles inside the unit circle). flag = (all (zm > 1 + tol) || isempty (zm)) && (all (pm < 1 - tol) || isempty (pm)); elseif (nargin == 1 && all(size (b) > [1 1])) [b, a] = sos2tf (b); flag = ismaxphase (b, a, tol); endif endfunction %!demo %! [b, a] = butter (1, .5); %! f = ismaxphase (b, a) ## test input validation %!error n = ismaxphase () %!error n = ismaxphase (1, 1, 1, 1) %!error n = ismaxphase (1, 1, 1, 1, 1) %!error n = ismaxphase ([1:10]', 1) %!error n = ismaxphase (1, [1:10]') %!error n = ismaxphase ([1:10]', [1:10]') %!error n = ismaxphase (1:10, 1:10, 1:10) %!error n = ismaxphase (ones (3), ones (3)) %!test %! z1 = [0.9*exp(j*0.6*pi), 0.9*exp(-j*0.6*pi)]; %! z2 = [0.8*exp(j*0.8*pi), 0.8*exp(-j*0.8*pi)]; %! b = poly ([z1 z2]); %! a = 1; %! f = ismaxphase (b, a); %! assert (f, false) %!test %! z1 = [0.9*exp(j*0.6*pi), 0.9*exp(-j*0.6*pi)]; %! z2 = [0.8*exp(j*0.8*pi), 0.8*exp(-j*0.8*pi)]; %! b = poly ([1./z1 1./z2]); %! a = 1; %! f = ismaxphase (b, a); %! assert (f, true) %!test %! z1 = [0.9*exp(j*0.6*pi), 0.9*exp(-j*0.6*pi)]; %! z2 = [0.8*exp(j*0.8*pi), 0.8*exp(-j*0.8*pi)]; %! b = poly ([z1 1./z2]); %! a = 1; %! f = ismaxphase (b, a); %! assert (f, false) %!test %! z1 = [0.9*exp(j*0.6*pi), 0.9*exp(-j*0.6*pi)]; %! z2 = [0.8*exp(j*0.8*pi), 0.8*exp(-j*0.8*pi)]; %! b = poly ([1./z1 z2]); %! a = 1; %! f = ismaxphase (b, a); %! assert (f, false) %!test %! [b, a] = butter (1, .5); %! f = ismaxphase (b, a); %! assert (f, false) %!test %! [b, a] = butter (8, .5); %! f = ismaxphase (b, a); %! assert (f, false) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/isminphase.m����������������������������������������������������������������������0000644�0000000�0000000�00000006056�14673270174�013242� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2023 Leonardo Araujo <leolca@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{L} = } isminphase (@var{b}, @var{a}) ## @deftypefnx {Function File} {@var{L} = } isminphase (@var{sos}) ## @deftypefnx {Function File} {@var{L} = } isminphase (@dots{}, @var{tol}) ## ## Determine whether a digital filter is minimum phase. The filter might be defined ## by the numerator coefficients, @var{b}, and the denominator coefficients, ## @var{a}, or, alternatively, by a matrix of second-order sections, @var{sos}. ## A toleranve @var{tol} might be given to define when two numbers are close enough ## to be considered equal. ## ## Example: ## @example ## a = [1 0.5]; b = [3 1]; ## isminphase (b, a) ## @end example ## ## Ref [1] Oppenheim, Alan, and Ronald Schafer. Discrete-Time Signal Processing. ## 3rd edition, Pearson, 2009. ## @end deftypefn function flag = isminphase (b, a, tol) if (nargin < 1 || nargin > 3 || (nargin == 2 && !isrow (b)) || (length (a) > 1 && ! isrow (a)) || (length (b) > 1 && ! isrow (b)) || (nargin == 3 && ! isscalar (tol)) ) print_usage; endif if (nargin == 2 && ! isrow (b)) tol = a; endif if (nargin == 1 && isrow (b)) a = 1; endif if nargin < 3 tol = eps^(3/4); endif if (nargin == 2 && isrow (a) && isrow (b)) || (nargin == 1 && isrow (b)) zm = abs (roots (b)); pm = abs (roots (a)); flag = (all (zm < 1 - tol) || isempty (zm)) && (all (pm < 1 - tol) || isempty (pm)); elseif (nargin == 1 && all(size (b) > [1 1])) [b, a] = sos2tf (b); flag = isminphase (b, a, tol); endif endfunction %!demo %! b = [3 1]; %! a = [1 .5]; %! f = isminphase (b, a) %! ## test input validation %!error n = isminphase () %!error n = isminphase (1, 1, 1, 1) %!error n = isminphase (1, 1, 1, 1, 1) %!error n = isminphase ([1:10]', 1) %!error n = isminphase (1, [1:10]') %!error n = isminphase ([1:10]', [1:10]') %!error n = isminphase (1:10, 1:10, 1:10) %!error n = isminphase (ones (3), ones (3)) %!test %! b = [3 1]; %! a = [1 .5]; %! f = isminphase (b, a); %! assert (f, true) %!test %! [b, a] = butter (1, .5); %! f = isminphase (b, a); %! assert (f, false) %!test %! [b, a] = butter (8, .5); %! f = isminphase (b, a); %! assert (f, false) %!test %! b = 1.25^2 * conv (conv (conv ([1 -0.9*e^(-j*0.6*pi)], [1 -0.9*e^(j*0.6*pi)]), [1 -0.8*e^(-j*0.8*pi)]), [1 -0.8*e^(j*0.8*pi)]); %! a = 1; %! f = isminphase (b, a); %! assert (f, true) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/isstable.m������������������������������������������������������������������������0000644�0000000�0000000�00000005274�14673270174�012711� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2022 The Octave Project Developers ## Copyright (C) 2017 Vasilis Lefkopoulos <vlefkopo@gmail.com> ## ## 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 <http://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{FLAG} =} isstable (@var{B}, @var{A}) ## Returns a logical output equal to TRUE, if the filter is stable. ## This can be done with coeffients of the filer @var{B} and @var{A}. ## Alternatively by using a second order sections matrix (SOS). ## ## Inputs: ## @itemize ## @item ## @var{B}: Numerator coefficients of the filter ## ## @item ## @var{A}: Denominator coeffients of the filter. Can be an empty vector. ## @end itemize ## ## Output: ## @itemize ## @item ## @var{FLAG}: Returns a logical output, equal to TRUE if the filter is stable. ## @end itemize ## ## Examples: ## @example ## b = [1 2 3 4 5 5 1 2]; ## a = [4 5 6 7 9 10 4 6]; ## flag = isstable (b, a) ## flag = 0 ## @end example ## ## Using SOS ## @example ## [z, p, k] = butter (6, 0.7, 'high'); ## sos = zp2sos (z, p, k); ## flag = isstable (sos) ## flag = 1 ## @end example ## @end deftypefn function flag = isstable (b, varargin) if isempty (varargin) # Only one argument was given if any(size (b) > [1 1]) # A matrix was given and is converted to vectors b & a [b, a] = sos2tf (b); else # Second input vector was omitted a = 1; endif else a = varargin{1}; endif if isempty (a) || (length (a) == 1) # An FIR filter is always stable flag = true; else if (a(1) != 1) # Normalization, so that a(1) equals 1 b = b ./ a(1); a = a ./ a(1); endif r = roots (a); if any (abs (r) > 1) flag = false; else flag = true; endif endif endfunction %!test %! b = [1 2 3 4 5 5 1 2]; %! a = []; %! assert (isstable (b,a), true) %!test %! b = [1 2 3 4 5 5 1 2]; %! a = [4 5 6 7 9 10 4 6]; %! assert (isstable (b,a), false) %!test %! b = [1 2 3 4 5 5 1 2]; %! a = [4 5 6 7 9 10 4 6]; %! a = polystab(a); %! assert (isstable (b,a), true) %!test %! [z,p,g] = butter(6,0.7,'high'); %! sos = zp2sos(z,p,g); %! assert (isstable(sos) , true) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/kaiser.m��������������������������������������������������������������������������0000644�0000000�0000000�00000004313�14673270174�012352� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1995, 1996, 1997 Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at> ## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} kaiser (@var{m}) ## @deftypefnx {Function File} {} kaiser (@var{m}, @var{beta}) ## ## Return the filter coefficients of a Kaiser window of length @var{m}. The ## Fourier transform of the window has a stop-band attenuation that is derived ## from the parameter @var{beta}. ## ## For the definition of the Kaiser window, see A. V. Oppenheim & ## R. W. Schafer, "Discrete-Time Signal Processing". ## ## The continuous version of width m centered about x=0 is: ## ## @example ## @group ## besseli(0, beta * sqrt(1-(2*x/m).^2)) ## k(x) = -------------------------------------, m/2 <= x <= m/2 ## besseli(0, beta) ## @end group ## @end example ## ## @seealso{kaiserord} ## @end deftypefn function w = kaiser (m, beta = 0.5) if (nargin < 1 || nargin > 2) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("kaiser: M must be a positive integer"); elseif (! (isscalar (beta) && isreal (beta))) error ("kaiser: BETA must be a real scalar"); endif if (m == 1) w = 1; else N = m - 1; k = (0 : N)'; k = 2 * beta / N * sqrt (k .* (N - k)); w = besseli (0, k) / besseli (0, beta); endif endfunction %!demo %! % use demo("kaiserord"); %!assert (kaiser (1), 1) %% Test input validation %!error kaiser () %!error kaiser (0.5) %!error kaiser (-1) %!error kaiser (ones (1, 4)) %!error kaiser (1, 2, 3) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/kaiserord.m�����������������������������������������������������������������������0000644�0000000�0000000�00000013410�14673270174�013055� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{n}, @var{Wn}, @var{beta}, @var{ftype}] =} kaiserord (@var{f}, @var{m}, @var{dev}) ## @deftypefnx {Function File} {[@dots{}] =} kaiserord (@var{f}, @var{m}, @var{dev}, @var{fs}) ## ## Return the parameters needed to produce a filter of the desired ## specification from a Kaiser window. The vector @var{f} contains pairs of ## frequency band edges in the range [0,1]. The vector @var{m} specifies the ## magnitude response for each band. The values of @var{m} must be zero for ## all stop bands and must have the same magnitude for all pass bands. The ## deviation of the filter @var{dev} can be specified as a scalar or a vector ## of the same length as @var{m}. The optional sampling rate @var{fs} can be ## used to indicate that @var{f} is in Hz in the range [0,@var{fs}/2]. ## ## The returned value @var{n} is the required order of the filter (the length ## of the filter minus 1). The vector @var{Wn} contains the band edges of ## the filter suitable for passing to @code{fir1}. The value @var{beta} is ## the parameter of the Kaiser window of length @var{n}+1 to shape the filter. ## The string @var{ftype} contains the type of filter to specify to ## @code{fir1}. ## ## The Kaiser window parameters n and beta are computed from the ## relation between ripple (A=-20*log10(dev)) and transition width ## (dw in radians) discovered empirically by Kaiser: ## ## @example ## @group ## / 0.1102(A-8.7) A > 50 ## beta = | 0.5842(A-21)^0.4 + 0.07886(A-21) 21 <= A <= 50 ## \ 0.0 A < 21 ## ## n = (A-8)/(2.285 dw) ## @end group ## @end example ## ## Example: ## @example ## @group ## [n, w, beta, ftype] = kaiserord ([1000, 1200], [1, 0], [0.05, 0.05], 11025); ## b = fir1 (n, w, kaiser (n+1, beta), ftype, "noscale"); ## freqz (b, 1, [], 11025); ## @end group ## @end example ## @seealso{fir1, kaiser} ## @end deftypefn ## FIXME: order is underestimated for the final test case: 2 stop bands. function [n, w, beta, ftype] = kaiserord(f, m, dev, fs) if (nargin<2 || nargin>4) print_usage; endif ## default sampling rate parameter if nargin<4, fs=2; endif ## parameter checking if length(f)!=2*length(m)-2 error("kaiserord must have one magnitude for each frequency band"); endif if any(m(1:length(m)-2)!=m(3:length(m))) error("kaiserord pass and stop bands must be strictly alternating"); endif if length(dev)!=length(m) && length(dev)!=1 error("kaiserord must have one deviation for each frequency band"); endif dev = min(dev); if dev <= 0, error("kaiserord must have dev>0"); endif ## use midpoints of the transition region for band edges w = (f(1:2:length(f))+f(2:2:length(f)))/fs; ## determine ftype if length(w) == 1 if m(1)>m(2), ftype='low'; else ftype='high'; endif elseif length(w) == 2 if m(1)>m(2), ftype='stop'; else ftype='pass'; endif else if m(1)>m(2), ftype='DC-1'; else ftype='DC-0'; endif endif ## compute beta from dev A = -20*log10(dev); if (A > 50) beta = 0.1102*(A-8.7); elseif (A >= 21) beta = 0.5842*(A-21)^0.4 + 0.07886*(A-21); else beta = 0.0; endif ## compute n from beta and dev dw = 2*pi*min(f(2:2:length(f))-f(1:2:length(f)))/fs; n = max(1,ceil((A-8)/(2.285*dw))); ## if last band is high, make sure the order of the filter is even. if ((m(1)>m(2)) == (rem(length(w),2)==0)) && rem(n,2)==1, n = n+1; endif endfunction %!demo %! Fs = 11025; %! for i=1:4 %! if i==1, %! subplot(221); bands=[1200, 1500]; mag=[1, 0]; dev=[0.1, 0.1]; %! elseif i==2 %! subplot(222); bands=[1000, 1500]; mag=[0, 1]; dev=[0.1, 0.1]; %! elseif i==3 %! subplot(223); bands=[1000, 1200, 3000, 3500]; mag=[0, 1, 0]; dev=0.1; %! elseif i==4 %! subplot(224); bands=100*[10, 13, 15, 20, 30, 33, 35, 40]; %! mag=[1, 0, 1, 0, 1]; dev=0.05; %! endif %! [n, w, beta, ftype] = kaiserord(bands, mag, dev, Fs); %! d=max(1,fix(n/10)); %! if mag(length(mag))==1 && rem(d,2)==1, d=d+1; endif %! [h, f] = freqz(fir1(n,w,ftype,kaiser(n+1,beta),'noscale'),1,[],Fs); %! hm = freqz(fir1(n-d,w,ftype,kaiser(n-d+1,beta),'noscale'),1,[],Fs); %! plot(f,abs(hm),sprintf("r;order %d;",n-d), ... %! f,abs(h), sprintf("b;order %d;",n)); %! b = [0, bands, Fs/2]; hold on; %! for i=2:2:length(b), %! hi=mag(i/2)+dev(1); lo=max(mag(i/2)-dev(1),0); %! plot([b(i-1), b(i), b(i), b(i-1), b(i-1)],[hi, hi, lo, lo, hi],"c;;"); %! endfor; hold off; %! endfor %! %! %-------------------------------------------------------------- %! % A filter meets the specifications if its frequency response %! % passes through the ends of the criteria boxes, and fails if %! % it passes through the top or the bottom. The criteria are %! % met precisely if the frequency response only passes through %! % the corners of the boxes. The blue line is the filter order %! % returned by kaiserord, and the red line is some lower filter %! % order. Confirm that the blue filter meets the criteria and %! % the red line fails. ## FIXME: extend demo to show detail at criteria box corners ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/levinson.m������������������������������������������������������������������������0000644�0000000�0000000�00000006441�14673270174�012735� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2006 Peter V. Lanspeary <peter.lanspeary@.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{a}, @var{v}, @var{ref}] =} levinson (@var{acf}) ## @deftypefnx {Function File} {[@dots{}] =} levinson (@var{acf}, @var{p}) ## ## Use the Durbin-Levinson algorithm to solve: ## toeplitz(acf(1:p)) * x = -acf(2:p+1). ## The solution [1, x'] is the denominator of an all pole filter ## approximation to the signal x which generated the autocorrelation ## function acf. ## ## acf is the autocorrelation function for lags 0 to p. ## p defaults to length(acf)-1. ## Returns ## a=[1, x'] the denominator filter coefficients. ## v= variance of the white noise = square of the numerator constant ## ref = reflection coefficients = coefficients of the lattice ## implementation of the filter ## Use freqz(sqrt(v),a) to plot the power spectrum. ## ## REFERENCE ## [1] Steven M. Kay and Stanley Lawrence Marple Jr.: ## "Spectrum analysis -- a modern perspective", ## Proceedings of the IEEE, Vol 69, pp 1380-1419, Nov., 1981 ## @end deftypefn ## Based on: ## yulewalker.m ## Copyright (C) 1995 Friedrich Leisch <Friedrich.Leisch@ci.tuwien.ac.at> ## GPL license ## FIXME: Matlab doesn't return reflection coefficients and ## errors in addition to the polynomial a. ## FIXME: What is the difference between aryule, levinson, ## ac2poly, ac2ar, lpc, etc.? function [a, v, ref] = levinson (acf, p) if ( nargin<1 ) print_usage; elseif( ~isvector(acf) || length(acf)<2 ) error( "levinson: arg 1 (acf) must be vector of length >1\n"); elseif ( nargin>1 && ( ~isscalar(p) || fix(p)~=p ) ) error( "levinson: arg 2 (p) must be integer >0\n"); else if ((nargin == 1)||(p>=length(acf))) p = length(acf) - 1; endif if( columns(acf)>1 ) acf=acf(:); endif # force a column vector if nargout < 3 && p < 100 ## direct solution [O(p^3), but no loops so slightly faster for small p] ## Kay & Marple Eqn (2.39) R = toeplitz(acf(1:p), conj(acf(1:p))); a = R \ -acf(2:p+1); a = [ 1, a.' ]; v = real( a*conj(acf(1:p+1)) ); else ## durbin-levinson [O(p^2), so significantly faster for large p] ## Kay & Marple Eqns (2.42-2.46) ref = zeros(p,1); g = -acf(2)/acf(1); a = [ g ]; v = real( ( 1 - g*conj(g)) * acf(1) ); ref(1) = g; for t = 2 : p g = -(acf(t+1) + a * acf(t:-1:2)) / v; a = [ a+g*conj(a(t-1:-1:1)), g ]; v = v * ( 1 - real(g*conj(g)) ) ; ref(t) = g; endfor a = [1, a]; endif endif endfunction �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/lpc.m�����������������������������������������������������������������������������0000644�0000000�0000000�00000010334�14673270174�011652� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013 Leonardo Araujo ## ## 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 <http://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{a} = } lpc (@var{x}) ## @deftypefnx {Function File} {@var{a} = } lpc (@var{x}, @var{p}) ## @deftypefnx {Function File} {[@var{a}, @var{g}] = } lpc (@dots{}) ## @deftypefnx {Function File} {[@var{a}, @var{g}] = } lpc (@var{x}, @var{p}) ## ## Determines the forward linear predictor by minimizing the prediction error ## in the least squares sense. Use the Durbin-Levinson algorithm to solve ## the Yule-Walker equations obtained by the autocorrelation of the input ## signal. ## ## @var{x} is a data vector used to estimate the lpc model of @var{p}-th order, ## given by the prediction polynomial @code{@var{a} = [1 @var{a}(2) @dots{} ## @var{a}(@var{p}+1)]}. If @var{p} is not provided, @code{length(@var{p}) - 1} ## is used as default. ## ## @var{x} might also be a matrix, in which case each column is regarded as a ## separate signal. @code{lpc} will return a model estimate for each column of ## @var{x}. ## ## @var{g} is the variance (power) of the prediction error for each signal in ## @var{x}. ## ## @seealso{aryule,levinson} ## @end deftypefn function [a, g] = lpc (x, p) if (nargin < 1 || nargin > 2) print_usage; elseif (! isrow (x) && rows (x) < 2) error( "lpc: rows(X) must be >1" ); elseif (nargin == 2 && (! isscalar (p) || fix (p) != p || p > length (x) - 1 || p < 1)) error( "lpc: P must be an integer >0 and <rows(X)" ); endif if (nargin < 2) p = length (x) - 1; endif if (isrow (x)) x = x'; endif n = columns (x); for j = 1:n r = xcorr (x(:,j)', p+1, "biased"); r(1:p+1) = []; # remove negative autocorrelation lags r(1) = real (r(1)); # levinson/toeplitz requires exactly real r(1) [a(j,:), g(j,1)] = levinson (r, p); # Use the Durbin-Levinson to solve: # toeplitz (acf(1:p)) * x = -acf(2:p+1). endfor endfunction %!demo %! noise = randn (10000, 1); %! x = filter (1, [1 1/2 1/4 1/8], noise); %! x = x(end-4096:end); %! [a, g] = lpc (x, 3); %! xe = filter ([0 -a(2:end)], 1, x); %! e = x - xe; %! [ac, k] = xcorr (e, "coeff"); %! subplot (2,1,1); plot (x(1:100), "b-", xe(1:100), "r--"); %! xlabel ("sample"); ylabel ("amplitude"); legend ("original","LPC estimate"); %! subplot (2,1,2); plot (k,ac,"b-"); xlabel ("lag"); %! title ("autocorrelation of prediction error"); %!demo %! if !isempty ( pkg ("list", "ltfat") ) %! pkg load ltfat %! [sig, fs] = linus; %! x = sig(13628:14428); %! [a, g] = lpc (x, 8); %! F = round (sort (unique (abs (angle (roots (a))))) * fs / (2 * pi) ); %! [h, w] = freqz (1, a, 512, "whole"); %! subplot (2, 1, 1); %! plot ( 1E3 * [0:1/fs:(length (x)-1)*1/fs], x); %! xlabel ("time (ms)"); ylabel ("Amplitude"); %! title ( "'linus' test signal" ); %! subplot (2, 1, 2); %! plot (w(1:256)/pi, 20*log10 (abs (h(1:256)))); %! xlabel ("Normalized Frequency ({\\times \\pi} rad/sample)") %! ylabel ("Magnitude (dB)") %! txt = sprintf (['Signal sampling rate = %d kHz\nFormant frequencies: ' ... %! '\nF1 = %d Hz\nF2 = %d Hz\nF3 = %d Hz\nF4 = %d Hz'], fs/1E3, ... %! F(1), F(2), F(3), F(4)); %! text (0.6, 20, txt); %! endif %! ## test input validation %!error [a, g] = lpc () %!error [a, g] = lpc (1) %!error [a, g] = lpc (1, 1) %!error [a, g] = lpc (1, 1, 1) %!error [a, g] = lpc (1:10, 0) %!error [a, g] = lpc (1:10, 10) %!error [a, g] = lpc (1:10, 0.5) %!error [a, g] = lpc (1:10, 1, [1 2]) %!test %! x = [1:4 4:-1:1]; %! [a, g] = lpc (x, 5); %! assert (a, [1.0 -1.823903 1.101798 -0.405738 0.521153 -0.340032], 1e-6) %! assert (g, 0.272194, 1e-6) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/marcumq.m�������������������������������������������������������������������������0000644�0000000�0000000�00000045017�14673270174�012547� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2012 Robert T. Short <rtshort@ieee.org> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} marcumq (@var{a}, @var{b}) ## @deftypefnx {Function File} {@var{q} =} marcumq (@var{a}, @var{b}, @var{m}) ## @deftypefnx {Function File} {@var{q} =} marcumq (@var{a}, @var{b}, @var{m}, @var{tol}) ## ## Compute the generalized Marcum Q function of order @var{m} with ## noncentrality parameter @var{a} and argument @var{b}. If the order ## @var{m} is omitted it defaults to 1. An optional relative tolerance ## @var{tol} may be included, the default is @code{eps}. ## ## If the input arguments are commensurate vectors, this function ## will produce a table of values. ## ## This function computes Marcum's Q function using the infinite ## Bessel series, truncated when the relative error is less than ## the specified tolerance. The accuracy is limited by that of ## the Bessel functions, so reducing the tolerance is probably ## not useful. ## ## Reference: Marcum, "Tables of Q Functions", Rand Corporation. ## ## Reference: R.T. Short, "Computation of Noncentral Chi-squared ## and Rice Random Variables", www.phaselockedsystems.com/publications ## ## @end deftypefn function q = marcumq (a, b, m = 1, tol = eps) if ((nargin < 2) || (nargin > 4)) print_usage (); endif if (any (a < 0)) error ("marcumq: A must be a non-negative value"); endif if (any (b < 0)) error ("marcumq: B must be a non-negative value"); endif if (any (m < 1) || any (fix (m) != m)) error ("marcumq: M must be a positive integer"); endif [a, b, m] = tablify (a, b, m); q = arrayfun (@mq, a, b, m, tol); endfunction ## Subfunction to compute the actual Marcum Q function. function q = mq (a, b, m, tol) ## Special cases. if (b == 0) q = 1; N = 0; return; endif if (a == 0) k = 0:(m - 1); q = exp (-b^2 / 2) * sum (b.^(2 * k) ./ (2.^k .* factorial (k))); N = 0; return; endif ## The basic iteration. If a<b compute Q_M, otherwise ## compute 1-Q_M. k = m; z = a * b; t = 1; k = 0; if (a < b) s = 1; c = 0; x = a / b; d = x; S = besseli (0, z, 1); if (m > 1) for k = 1:m - 1 t = (d + 1 / d) * besseli (k, z, 1); S = S + t; d = d * x; endfor endif N = k++; else s = -1; c = 1; x = b / a; k = m; d = x^m; S = 0; N = 0; endif do t = d * besseli (abs (k), z, 1); S = S + t; d = d * x; N = k++; until (abs (t / S) < tol) q = c + s * exp (-(a - b)^2 / 2) * S; endfunction ## Internal helper function to create a table of like dimensions from arguments. function [varargout] = tablify (varargin) if (nargin < 2) varargout = varargin; return; endif empty = cellfun (@isempty, varargin); nrows = cellfun (@rows, varargin(! empty)); ridx = (nrows > 1); if (any (ridx)) rdim = nrows(ridx)(1); else rdim = 1; endif ncols = cellfun (@columns, varargin(! empty)); cidx = (ncols > 1); if (any (cidx)) cdim = ncols(cidx)(1); else cdim = 1; endif if (any (nrows(ridx) != rdim) || any (ncols(cidx) != cdim)) error ("tablify: incommensurate sizes"); endif varargout = varargin; varargout(! ridx) = cellindexmat (varargout(! ridx), ones (rdim, 1), ":"); varargout(! cidx) = cellindexmat (varargout(! cidx), ":", ones (1, cdim)); endfunction %% Tests for number and validity of arguments. %!error marcumq (1) %!error marcumq (-1, 1, 1, 1, 1) %!error marcumq (-1, 1) %!error marcumq (1, -1) %!error marcumq (1, 1, 0) %!error marcumq (1, 1, -1) %!error marcumq (1, 1, 1.1) ## Notes on tests and accuracy. ## ----------------------------------- ## The numbers used as the reference (Q) in the tables below are ## from J.I. Marcum, "Table of Q Functions", Rand Technical Report ## RM-339, 1950/1/1. ## ## There is one discrepancy in the tables. Marcum has ## Q(14.00,17.10) = 0.001078 ## while we compute ## Q(14.00,17.10) = 0.0010785053 = 0.001079 ## This is obviously a non-problem. ## ## As further tests, I created several different versions of the ## Q function computation, including a Bessel series expansion and ## numerical integration. All of them agree to with 10^(-16). %!test %! a = [0.00; 0.05; 1.00; 2.00; 3.00; 4.00; 5.00; 6.00; 7.00; 8.00; 9.00; 10.00; %! 11.00; 12.00; 13.00; 14.00; 15.00; 16.00; 17.00; 18.00; 19.00; 20.00; %! 21.00; 22.00; 23.00; 24.00]; %! b = [0.000000, 0.100000, 1.100000, 2.100000, 3.100000, 4.100000]; %! Q = [1.000000, 0.995012, 0.546074, 0.110251, 0.008189, 0.000224; %! 1.000000, 0.995019, 0.546487, 0.110554, 0.008238, 0.000226; %! 1.000000, 0.996971, 0.685377, 0.233113, 0.034727, 0.002092; %! 1.000000, 0.999322, 0.898073, 0.561704, 0.185328, 0.027068; %! 1.000000, 0.999944, 0.985457, 0.865241, 0.526735, 0.169515; %! 1.000000, 0.999998, 0.999136, 0.980933, 0.851679, 0.509876; %! 1.000000, 1.000000, 0.999979, 0.998864, 0.978683, 0.844038; %! 1.000000, 1.000000, 1.000000, 0.999973, 0.998715, 0.977300; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.999969, 0.998618; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999966; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000]; %! q = marcumq (a, b); %! assert (q, Q, 1e-6); %!test %! a = [0.00; 0.05; 1.00; 2.00; 3.00; 4.00; 5.00; 6.00; 7.00; 8.00; 9.00; 10.00; %! 11.00; 12.00; 13.00; 14.00; 15.00; 16.00; 17.00; 18.00; 19.00; 20.00; %! 21.00; 22.00; 23.00; 24.00]; %! b = [5.100000, 6.100000, 7.100000, 8.100000, 9.100000, 10.10000]; %! Q = [0.000002, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.000002, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.000049, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.001606, 0.000037, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.024285, 0.001420, 0.000032, 0.000000, 0.000000, 0.000000; %! 0.161412, 0.022812, 0.001319, 0.000030, 0.000000, 0.000000; %! 0.499869, 0.156458, 0.021893, 0.001256, 0.000028, 0.000000; %! 0.839108, 0.493229, 0.153110, 0.021264, 0.001212, 0.000027; %! 0.976358, 0.835657, 0.488497, 0.150693, 0.020806, 0.001180; %! 0.998549, 0.975673, 0.833104, 0.484953, 0.148867, 0.020458; %! 0.999965, 0.998498, 0.975152, 0.831138, 0.482198, 0.147437; %! 1.000000, 0.999963, 0.998458, 0.974742, 0.829576, 0.479995; %! 1.000000, 1.000000, 0.999962, 0.998426, 0.974411, 0.828307; %! 1.000000, 1.000000, 1.000000, 0.999961, 0.998400, 0.974138; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.999960, 0.998378; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999960; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000]; %! q = marcumq (a, b); %! assert (q, Q, 1e-6); %!test %! a = [0.00; 0.05; 1.00; 2.00; 3.00; 4.00; 5.00; 6.00; 7.00; 8.00; 9.00; 10.00; %! 11.00; 12.00; 13.00; 14.00; 15.00; 16.00; 17.00; 18.00; 19.00; 20.00; %! 21.00; 22.00; 23.00; 24.00]; %! b = [11.10000, 12.10000, 13.10000, 14.10000, 15.10000, 16.10000]; %! Q = [0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.000026, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.001155, 0.000026, 0.000000, 0.000000, 0.000000, 0.000000; %! 0.020183, 0.001136, 0.000025, 0.000000, 0.000000, 0.000000; %! 0.146287, 0.019961, 0.001120, 0.000025, 0.000000, 0.000000; %! 0.478193, 0.145342, 0.019778, 0.001107, 0.000024, 0.000000; %! 0.827253, 0.476692, 0.144551, 0.019625, 0.001096, 0.000024; %! 0.973909, 0.826366, 0.475422, 0.143881, 0.019494, 0.001087; %! 0.998359, 0.973714, 0.825607, 0.474333, 0.143304, 0.019381; %! 0.999959, 0.998343, 0.973546, 0.824952, 0.473389, 0.142803; %! 1.000000, 0.999959, 0.998330, 0.973400, 0.824380, 0.472564; %! 1.000000, 1.000000, 0.999958, 0.998318, 0.973271, 0.823876; %! 1.000000, 1.000000, 1.000000, 0.999958, 0.998307, 0.973158; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.999957, 0.998297; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999957; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000]; %! q = marcumq (a, b); %! assert (q, Q, 1e-6); %!test %! a = [0.00; 0.05; 1.00; 2.00; 3.00; 4.00; 5.00; 6.00; 7.00; 8.00; 9.00; 10.00; %! 11.00; 12.00; 13.00; 14.00; 15.00; 16.00; 17.00; 18.00; 19.00; 20.00; %! 21.00; 22.00; 23.00; 24.00]; %! b = [17.10000, 18.10000, 19.10000]; %! Q = [0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000000, 0.000000, 0.000000; %! 0.000024, 0.000000, 0.000000; %! 0.001078, 0.000024, 0.000000; %! 0.019283, 0.001071, 0.000023; %! 0.142364, 0.019197, 0.001065; %! 0.471835, 0.141976, 0.019121; %! 0.823429, 0.471188, 0.141630; %! 0.973056, 0.823030, 0.470608; %! 0.998289, 0.972965, 0.822671; %! 0.999957, 0.998281, 0.972883; %! 1.000000, 0.999957, 0.998274; %! 1.000000, 1.000000, 0.999956; %! 1.000000, 1.000000, 1.000000]; %! q = marcumq (a, b); %! assert (q, Q, 1e-6); ## The tests for M>1 were generating from Marcum's tables by ## using the formula ## Q_M(a,b) = Q(a,b) + exp(-(a-b)^2/2)*sum_{k=1}^{M-1}(b/a)^k*exp(-ab)*I_k(ab) %!test %! M = 2; %! a = [0.00; 0.05; 1.00; 2.00; 3.00; 4.00; 5.00; 6.00; 7.00; 8.00; 9.00; 10.00; %! 11.00; 12.00; 13.00; 14.00; 15.00; 16.00; 17.00; 18.00; 19.00; 20.00; %! 21.00; 22.00; 23.00; 24.00]; %! b = [ 0.00, 0.10, 2.10, 7.10, 12.10, 17.10]; %! Q = [1.000000, 0.999987, 0.353353, 0.000000, 0.000000, 0.000000; %! 1.000000, 0.999988, 0.353687, 0.000000, 0.000000, 0.000000; %! 1.000000, 0.999992, 0.478229, 0.000000, 0.000000, 0.000000; %! 1.000000, 0.999999, 0.745094, 0.000001, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.934771, 0.000077, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.992266, 0.002393, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.999607, 0.032264, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.999992, 0.192257, 0.000000, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.545174, 0.000000, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.864230, 0.000040, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.981589, 0.001555, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.998957, 0.024784, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.999976, 0.166055, 0.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.509823, 0.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.846066, 0.000032; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.978062, 0.001335; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.998699, 0.022409; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.999970, 0.156421; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.495223; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.837820; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.976328; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.998564; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999966; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000]; %! q = marcumq (a, b, M); %! assert (q, Q, 1e-6); %!test %! M = 5; %! a = [0.00; 0.05; 1.00; 2.00; 3.00; 4.00; 5.00; 6.00; 7.00; 8.00; 9.00; 10.00; %! 11.00; 12.00; 13.00; 14.00; 15.00; 16.00; 17.00; 18.00; 19.00; 20.00; %! 21.00; 22.00; 23.00; 24.00]; %! b = [ 0.00, 0.10, 2.10, 7.10, 12.10, 17.10]; %! Q = [1.000000, 1.000000, 0.926962, 0.000000, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.927021, 0.000000, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.947475, 0.000001, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.980857, 0.000033, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.996633, 0.000800, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.999729, 0.011720, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.999990, 0.088999, 0.000000, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.341096, 0.000000, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.705475, 0.000002, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.933009, 0.000134, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.993118, 0.003793, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.999702, 0.045408, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.999995, 0.238953, 0.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.607903, 0.000001; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.896007, 0.000073; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.987642, 0.002480; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.999389, 0.034450; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.999988, 0.203879; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.565165; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.876284; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.984209; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999165; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999983; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000]; %! q = marcumq (a, b, M); %! assert (q, Q, 1e-6); %!test %! M = 10; %! a = [0.00; 0.05; 1.00; 2.00; 3.00; 4.00; 5.00; 6.00; 7.00; 8.00; 9.00; 10.00; %! 11.00; 12.00; 13.00; 14.00; 15.00; 16.00; 17.00; 18.00; 19.00; 20.00; %! 21.00; 22.00; 23.00; 24.00]; %! b = [ 0.00, 0.10, 2.10, 7.10, 12.10, 17.10]; %! Q = [1.000000, 1.000000, 0.999898, 0.000193, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.999897, 0.000194, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.999931, 0.000416, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.999980, 0.002377, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.999997, 0.016409, 0.000000, 0.000000; %! 1.000000, 1.000000, 0.999999, 0.088005, 0.000000, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.302521, 0.000000, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.638401, 0.000000, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.894322, 0.000022, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.984732, 0.000840, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.998997, 0.014160, 0.000000; %! 1.000000, 1.000000, 1.000000, 0.999972, 0.107999, 0.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.391181, 0.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.754631, 0.000004; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.951354, 0.000266; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.995732, 0.006444; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.999843, 0.065902; %! 1.000000, 1.000000, 1.000000, 1.000000, 0.999998, 0.299616; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.676336; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.925312; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.992390; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999679; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999995; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000; %! 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000]; %! q = marcumq (a, b, M); %! assert (q, Q, 1e-6); �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/mexihat.m�������������������������������������������������������������������������0000644�0000000�0000000�00000002174�14673270174�012536� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{psi}, @var{x}] =} mexihat (@var{lb}, @var{ub}, @var{n}) ## Compute the Mexican hat wavelet. ## @end deftypefn function [psi,x] = mexihat(lb,ub,n) if (nargin < 3); print_usage; endif if (n <= 0) error("n must be strictly positive"); endif x = linspace(lb,ub,n); psi = (1-x.^2).*(2/(sqrt(3)*pi^0.25)) .* exp(-x.^2/2) ; endfunction ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/meyeraux.m������������������������������������������������������������������������0000644�0000000�0000000�00000001765�14673270174�012743� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} meyeraux (@var{x}) ## Compute the Meyer wavelet auxiliary function. ## @end deftypefn function y = meyeraux(x) if (nargin < 1); print_usage; endif y = 35.*x.^4-84.*x.^5+70.*x.^6-20.*x.^7; endfunction �����������signal-1.4.6/inst/morlet.m��������������������������������������������������������������������������0000644�0000000�0000000�00000002136�14673270174�012377� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{psi}, @var{x}] =} morlet (@var{lb}, @var{ub}, @var{n}) ## Compute the Morlet wavelet. ## @end deftypefn function [psi,x] = morlet(lb,ub,n) if (nargin < 3); print_usage; endif if (n <= 0) error("n must be strictly positive"); endif x = linspace(lb,ub,n); psi = cos(5.*x) .* exp(-x.^2/2) ; endfunction ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/movingrms.m�����������������������������������������������������������������������0000644�0000000�0000000�00000005543�14673270174�013123� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2012 Juan Pablo Carbajal <carbajal@ifi.uzh.ch> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{rmsx},@var{w}] =} movingrms (@var{x},@var{w},@var{rc},@var{Fs}=1) ## Calculate moving RMS value of the signal in @var{x}. ## ## The signal is convoluted against a sigmoid window of width @var{w} and ## risetime @var{rc}. The units of these parameters are relative to the value ## of the sampling frequency given in @var{Fs} (Default value = 1). ## ## Run @code{demo movingrms} to see an example. ## ## @seealso{sigmoid_train} ## @end deftypefn function [rmsx w]= movingrms (x,width, risetime, Fs=1) [N nc] = size (x); if width*Fs > N/2 idx = [1 N]; w = ones(N,1); else idx = round ((N + width*Fs*[-1 1])/2); w = sigmoid_train ((1:N)', idx, risetime*Fs); endif fw = fft (w.^2); fx = fft (x.^2); rmsx = real(ifft (fx.*fw)/(N-1)); rmsx (rmsx < eps*max(rmsx(:))) = 0; rmsx = circshift (sqrt (rmsx), round(mean(idx))); ##w = circshift (w, -idx(1)); endfunction %!demo %! N = 128; %! t = linspace(0,1,N)'; %! x = sigmoid_train (t,[0.4 inf],1e-2).*(2*rand(size(t))-1); %! Fs = 1/diff(t(1:2)); %! width = 0.05; %! rc = 5e-3; %! [wx w] = movingrms (zscore (x),width,rc,Fs); %! area (t,wx,'facecolor',[0.85 0.85 1],'edgecolor','b','linewidth',2); %! hold on; %! h = plot (t,x,'r-;Data;',t,w,'g-;Window;'); %! set (h, 'linewidth', 2); %! hold off; %! # --------------------------------------------------------------------------- %! # The shaded plot shows the local RMS of the Data: white noise with onset at %! # aprox. t== 0.4. %! # The observation window is also shown. %!demo %! N = 128; %! t = linspace(0,1,N)'; %! x = exp(-((t-0.5)/0.1).^2) + 0.1*rand(N,1); %! Fs = 1/diff(t(1:2)); %! width = 0.1; %! rc = 2e-3; %! [wx w] = movingrms (zscore (x),width,rc,Fs); %! area (t,wx,'facecolor',[0.85 0.85 1],'edgecolor','b','linewidth',2); %! hold on; %! h = plot (t,x,'r-;Data;',t,w,'g-;Window;'); %! set (h, 'linewidth', 2); %! hold off; %! # --------------------------------------------------------------------------- %! # The shaded plot shows the local RMS of the Data: Gausian with centered at %! # aprox. t== 0.5. %! # The observation window is also shown. �������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/mscohere.m������������������������������������������������������������������������0000644�0000000�0000000�00000004557�14673270174�012713� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{Pxx}, @var{freq}] =} mscohere (@var{x}, @var{y}) ## @deftypefnx {Function File} {[@dots{}] =} mscohere (@var{x}, @var{y}, @var{window}) ## @deftypefnx {Function File} {[@dots{}] =} mscohere (@var{x}, @var{y}, @var{window}, @var{overlap}) ## @deftypefnx {Function File} {[@dots{}] =} mscohere (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}) ## @deftypefnx {Function File} {[@dots{}] =} mscohere (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}) ## @deftypefnx {Function File} {[@dots{}] =} mscohere (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}, @var{range}) ## @deftypefnx {Function File} {} mscohere (@dots{}) ## ## Estimate (mean square) coherence of signals @var{x} and @var{y}. ## Use the Welch (1967) periodogram/FFT method. ## @seealso{pwelch} ## @end deftypefn function varargout = mscohere(varargin) ## ## Check fixed argument if (nargin < 2 || nargin > 7) print_usage (); endif nvarargin = length(varargin); ## remove any pwelch RESULT args and add 'cross' for iarg=1:nvarargin arg = varargin{iarg}; if ( ~isempty(arg) && ischar(arg) && ( strcmp(arg,'power') || ... strcmp(arg,'cross') || strcmp(arg,'trans') || ... strcmp(arg,'coher') || strcmp(arg,'ypower') )) varargin{iarg} = []; endif endfor varargin{nvarargin+1} = 'coher'; ## if ( nargout==0 ) pwelch(varargin{:}); elseif ( nargout==1 ) Pxx = pwelch(varargin{:}); varargout{1} = Pxx; elseif ( nargout>=2 ) [Pxx,f] = pwelch(varargin{:}); varargout{1} = Pxx; varargout{2} = f; endif endfunction �������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/ncauer.m��������������������������������������������������������������������������0000644�0000000�0000000�00000007054�14673270174�012356� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paulo Neis <p_neis@yahoo.com.br> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{z}, @var{p}, @var{g}] =} cauer(@var{Rp}, @var{Rs}, @var{n}) ## Analog prototype for Cauer filter. ## ## @table @asis ## @item Rp ## Passband ripple ## @item Rs ## Stopband ripple ## @item n ## Desired order ## @item z ## complex vector of zeros for the model. ## @item p ## complex vector of poles for the model. ## @item g ## gain value. ## @end table ## ## References: ## ## - Serra, Celso Penteado, Teoria e Projeto de Filtros, Campinas: CARTGRAF, ## 1983. ## ## - Lamar, Marcus Vinicius, Notas de aula da disciplina TE 456 - Circuitos ## Analogicos II, UFPR, 2001/2002. ## @end deftypefn function [zer, pol, T0] = ncauer (Rp, Rs, n) ## Cutoff frequency = 1: wp=1; ## Stop band edge ws: ws=__ellip_ws(n, Rp, Rs); k=wp/ws; k1=sqrt(1-k^2); q0=(1/2)*((1-sqrt(k1))/(1+sqrt(k1))); q= q0 + 2*q0^5 + 15*q0^9 + 150*q0^13; #(....) D=(10^(0.1*Rs)-1)/(10^(0.1*Rp)-1); ## Filter order maybe this, but not used now: ## n=ceil(log10(16*D)/log10(1/q)) l=(1/(2*n))*log((10^(0.05*Rp)+1)/(10^(0.05*Rp)-1)); sig01=0; sig02=0; for m=0 : 30 sig01=sig01+(-1)^m * q^(m*(m+1)) * sinh((2*m+1)*l); endfor for m=1 : 30 sig02=sig02+(-1)^m * q^(m^2) * cosh(2*m*l); endfor sig0=abs((2*q^(1/4)*sig01)/(1+2*sig02)); w=sqrt((1+k*sig0^2)*(1+sig0^2/k)); ## if rem(n,2) r=(n-1)/2; else r=n/2; endif ## wi=zeros(1,r); for ii=1 : r if rem(n,2) mu=ii; else mu=ii-1/2; endif soma1=0; for m=0 : 30 soma1 = soma1 + 2*q^(1/4) * ((-1)^m * q^(m*(m+1)) * sin(((2*m+1)*pi*mu)/n)); endfor soma2=0; for m=1 : 30 soma2 = soma2 + 2*((-1)^m * q^(m^2) * cos((2*m*pi*mu)/n)); endfor wi(ii)=(soma1/(1+soma2)); endfor ## Vi=sqrt((1-(k.*(wi.^2))).*(1-(wi.^2)/k)); A0i=1./(wi.^2); sqrA0i=1./(wi); B0i=((sig0.*Vi).^2 + (w.*wi).^2)./((1+sig0^2.*wi.^2).^2); B1i=(2 * sig0.*Vi)./(1 + sig0^2 * wi.^2); ## Gain T0: if rem(n,2) T0=sig0*prod(B0i./A0i)*sqrt(ws); else T0=10^(-0.05*Rp)*prod(B0i./A0i); endif ## zeros: zer=[i*sqrA0i, -i*sqrA0i]; ## poles: pol=[(-2*sig0*Vi+2*i*wi.*w)./(2*(1+sig0^2*wi.^2)), (-2*sig0*Vi-2*i*wi.*w)./(2*(1+sig0^2*wi.^2))]; ## If n odd, there is a real pole -sig0: if rem(n,2) pol=[pol, -sig0]; endif ## pol=(sqrt(ws)).*pol; zer=(sqrt(ws)).*zer; endfunction ## usage: ws = __ellip_ws(n, rp, rs) ## Calculate the stop band edge for the Cauer filter. function ws=__ellip_ws(n, rp, rs) kl0 = ((10^(0.1*rp)-1)/(10^(0.1*rs)-1)); k0 = (1-kl0); int = ellipke([kl0 ; k0]); ql0 = int(1); q0 = int(2); x = n*ql0/q0; kl = fminbnd(@(y) __ellip_ws_min(y,x) ,eps, 1-eps); ws = sqrt(1/kl); endfunction ## usage: err = __ellip_ws_min(kl, x) function err=__ellip_ws_min(kl, x) int=ellipke([kl; 1-kl]); ql=int(1); q=int(2); err=abs((ql/q)-x); endfunction ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/nuttallwin.m����������������������������������������������������������������������0000644�0000000�0000000�00000005074�14673270174�013302� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} nuttallwin (@var{m}) ## @deftypefnx {Function File} {} nuttallwin (@var{m}, "periodic") ## @deftypefnx {Function File} {} nuttallwin (@var{m}, "symmetric") ## Return the filter coefficients of a Blackman-Harris window defined by ## Nuttall of length @var{m}. ## ## If the optional argument @code{"periodic"} is given, the periodic form ## of the window is returned. This is equivalent to the window of length ## @var{m}+1 with the last coefficient removed. The optional argument ## @code{"symmetric"} is equivalent to not specifying a second argument. ## ## @seealso{blackman, blackmanharris} ## @end deftypefn function w = nuttallwin (m, opt) if (nargin < 1 || nargin > 2) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("nuttallwin: M must be a positive integer"); endif N = m - 1; if (nargin == 2) switch (opt) case "periodic" N = m; case "symmetric" N = m - 1; otherwise error ("nuttallwin: window type must be either \"periodic\" or \"symmetric\""); endswitch endif if (m == 1) w = 1; else a0 = 0.355768; a1 = 0.487396; a2 = 0.144232; a3 = 0.012604; n = [-N/2:(m-1)/2]'; w = a0 + a1.*cos(2.*pi.*n./N) + a2.*cos(4.*pi.*n./N) + a3.*cos(6.*pi.*n./N); endif endfunction %!assert (nuttallwin (1), 1) %!assert (nuttallwin (2), zeros (2, 1), eps) %!assert (nuttallwin (15), flipud (nuttallwin (15)), 10*eps); %!assert (nuttallwin (16), flipud (nuttallwin (16)), 10*eps); %!assert (nuttallwin (15), nuttallwin (15, "symmetric")); %!assert (nuttallwin (16)(1:15), nuttallwin (15, "periodic")); %% Test input validation %!error nuttallwin () %!error nuttallwin (0.5) %!error nuttallwin (-1) %!error nuttallwin (ones (1, 4)) %!error nuttallwin (1, 2) %!error nuttallwin (1, "invalid") ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/parzenwin.m�����������������������������������������������������������������������0000644�0000000�0000000�00000003125�14673270174�013111� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} parzenwin (@var{m}) ## Return the filter coefficients of a Parzen window of length @var{m}. ## @seealso{rectwin, bartlett} ## @end deftypefn function w = parzenwin (m) if (nargin != 1) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("parzenwin: M must be a positive integer"); endif N = m - 1; n = -(N/2):N/2; n1 = n(find(abs(n) <= N/4)); n2 = n(find(n > N/4)); n3 = n(find(n < -N/4)); w1 = 1 -6.*(abs(n1)./(m/2)).^2 + 6*(abs(n1)./(m/2)).^3; w2 = 2.*(1-abs(n2)./(m/2)).^3; w3 = 2.*(1-abs(n3)./(m/2)).^3; w = [w3 w1 w2]'; endfunction %!assert (parzenwin (1), 1) %!assert (parzenwin (2), 0.25 * ones (2, 1)) %% Test input validation %!error parzenwin () %!error parzenwin (0.5) %!error parzenwin (-1) %!error parzenwin (ones (1, 4)) %!error parzenwin (1, 2) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/pburg.m���������������������������������������������������������������������������0000644�0000000�0000000�00000014070�14673270174�012214� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{psd},@var{f_out}] =} pburg(@var{x}, @var{poles}, @var{freq}, @var{Fs}, @var{range}, @var{method}, @var{plot_type}, @var{criterion}) ## Calculate Burg maximum-entropy power spectral density. ## ## The functions "arburg" and "ar_psd" do all the work. ## See "help arburg" and "help ar_psd" for further details. ## ## ARGUMENTS: ## ## All but the first two arguments are optional and may be empty. ## ## @table @asis ## @item x ## [vector] sampled data ## @item poles ## [integer scalar] required number of poles of the AR model ## @item freq ## [real vector] frequencies at which power spectral density is calculated. ## ## [integer scalar] number of uniformly distributed frequency ## values at which spectral density is calculated. ## [default=256] ## @item Fs ## [real scalar] sampling frequency (Hertz) [default=1] ## @end table ## ## CONTROL-STRING ARGUMENTS -- each of these arguments is a character string. ## ## Control-string arguments can be in any order after the other arguments. ## ## ## @table @asis ## @item range ## 'half', 'onesided' : frequency range of the spectrum is ## from zero up to but not including sample_f/2. Power ## from negative frequencies is added to the positive ## side of the spectrum. ## ## 'whole', 'twosided' : frequency range of the spectrum is ## -sample_f/2 to sample_f/2, with negative frequencies ## stored in "wrap around" order after the positive ## frequencies; e.g. frequencies for a 10-point 'twosided' ## spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 ## ## 'shift', 'centerdc' : same as 'whole' but with the first half ## of the spectrum swapped with second half to put the ## zero-frequency value in the middle. (See "help ## fftshift". If "freq" is vector, 'shift' is ignored. ## If model coefficients "ar_coeffs" are real, the default ## range is 'half', otherwise default range is 'whole'. ## ## @item method ## 'fft': use FFT to calculate power spectral density. ## ## 'poly': calculate spectral density as a polynomial of 1/z ## N.B. this argument is ignored if the "freq" argument is a ## vector. The default is 'poly' unless the "freq" ## argument is an integer power of 2. ## ## @item plot_type ## 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': ## specifies the type of plot. The default is 'plot', which ## means linear-linear axes. 'squared' is the same as 'plot'. ## 'dB' plots "10*log10(psd)". This argument is ignored and a ## spectrum is not plotted if the caller requires a returned ## value. ## ## @item criterion ## [optional string arg] model-selection criterion. Limits ## the number of poles so that spurious poles are not ## added when the whitened data has no more information ## in it (see Kay & Marple, 1981). Recognized values are ## ## 'AKICc' -- approximate corrected Kullback information ## criterion (recommended), ## ## 'KIC' -- Kullback information criterion ## ## 'AICc' -- corrected Akaike information criterion ## ## 'AIC' -- Akaike information criterion ## ## 'FPE' -- final prediction error" criterion ## ## The default is to NOT use a model-selection criterion ## @end table ## ## RETURNED VALUES: ## ## If return values are not required by the caller, the spectrum ## is plotted and nothing is returned. ## ## @table @asis ## @item psd ## [real vector] power-spectral density estimate ## @item f_out ## [real vector] frequency values ## @end table ## ## HINTS ## ## This function is a wrapper for arburg and ar_psd. ## ## See "help arburg", "help ar_psd". ## @end deftypefn function [psd,f_out]=pburg(x,poles,varargin) ## if ( nargin<2 ) error( 'pburg: need at least 2 args. Use "help pburg"' ); endif nvarargin=length(varargin); criterion=[]; ## ## Search for a "criterion" arg. If found, remove it ## from "varargin" list and feed it to arburg instead. for iarg = 1: nvarargin arrgh = varargin{iarg}; if ( ischar(arrgh) && ( strcmp(arrgh,'AKICc') ||... strcmp(arrgh,'KIC') || strcmp(arrgh,'AICc') ||... strcmp(arrgh,'AIC') || strcmp(arrgh,'FPE') ) ) criterion=arrgh; if ( nvarargin>1 ) varargin{iarg}= []; else varargin={}; endif endif endfor ## [ar_coeffs,residual]=arburg(x,poles,criterion); if ( nargout==0 ) ar_psd(ar_coeffs,residual,varargin{:}); elseif ( nargout==1 ) psd = ar_psd(ar_coeffs,residual,varargin{:}); elseif ( nargout>=2 ) [psd,f_out] = ar_psd(ar_coeffs,residual,varargin{:}); endif endfunction %!demo %! a = [1.0 -1.6216505 1.1102795 -0.4621741 0.2075552 -0.018756746]; %! Fs = 25; %! n = 16384; %! signal = detrend (filter (0.70181, a, rand (1, n))); %! % frequency shift by modulating with exp(j.omega.t) %! skewed = signal .* exp (2*pi*i*2/Fs*[1:n]); %! hold on; %! pburg (signal, 3, [], Fs); %! pburg (signal, 4, [], Fs, "whole"); %! pburg (signal, 5, 128, Fs, "shift", "semilogy"); %! pburg (skewed, 7, 128, Fs, "AKICc", "shift", "semilogy"); %! user_freq = [-0.2:0.02:0.2]*Fs; %! pburg (skewed, 7, user_freq, Fs, "AKICc", "semilogy"); %! hold off; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/peak2peak.m�����������������������������������������������������������������������0000644�0000000�0000000�00000005464�14673270174�012747� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2014 Georgios Ouzounis <ouzounis_georgios@hotmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} peak2peak (@var{x}) ## @deftypefnx {Function File} {@var{y} =} peak2peak (@var{x}, @var{dim}) ## Compute the difference between the maximum and minimum values in the vector ## @var{x}. ## ## If @var{x} is a matrix, compute the difference for each column and return ## them in a row vector. ## ## If the optional argument @var{dim} is given, operate along this dimension. ## @seealso{max, min, peak2rms, rms, rssq} ## @end deftypefn function y = peak2peak (x, dim) if (nargin < 1 || nargin > 2) print_usage (); endif if (nargin > 1 && ! (isscalar (dim) && dim == fix (dim) && dim > 0)) error ("peak2peak: DIM must be an integer and a valid dimension"); endif if (nargin == 1) y = max (x) - min (x); else y = max (x, [], dim) - min (x, [], dim); endif endfunction %!test %! X = [23 42 85; 62 46 65; 18 40 28]; %! Y = peak2peak (X); %! assert (Y, [44 6 57]); %! Y = peak2peak (X, 1); %! assert (Y, [44 6 57]); %! Y = peak2peak (X, 2); %! assert (Y, [62; 19; 22]); %!test %! X = [71 62 33]; %! X(:, :, 2) = [88 36 21]; %! X(:, :, 3) = [83 46 85]; %! Y = peak2peak (X); %! T = [38]; %! T(:, :, 2) = [67]; %! T(:, :, 3) = [39]; %! assert (Y, T); %!test %! X = [71 72 22; 16 22 50; 29 44 14]; %! X(:, :, 2) = [10 15 62; 1 94 30; 72 43 53]; %! X(:, :, 3) = [57 98 32; 84 95 51; 25 24 0]; %! Y = peak2peak (X); %! T = [55 50 36]; %! T(:, :, 2) = [71 79 32]; %! T(:, :, 3) = [59 74 51]; %! assert (Y, T); %! Y = peak2peak (X, 2); %! T = [50; 34; 30]; %! T(:, :, 2) = [52; 93; 29]; %! T(:, :, 3) = [66; 44; 25]; %! assert (Y, T); %! Y = peak2peak (X, 3); %! T = [61 83 40; 83 73 21; 47 20 53]; %! assert (Y, T); %!test %! X = [60 61; 77 77]; %! X(:, :, 2) = [24 24; 22 74]; %! temp = [81 87; 88 62]; %! temp(:, :, 2) = [20 83; 81 18]; %! X(:, :, :, 2) = temp; %! Y = peak2peak (X); %! T = [17 16]; %! T(:, :, 2) = [2 50]; %! T2 = [7 25]; %! T2(:, :, 2) = [61 65]; %! T(:, :, :, 2) = T2; %! assert (Y, T); ## Test input validation %!error peak2peak () %!error peak2peak (1, 2, 3) %!error peak2peak (1, 1.5) %!error peak2peak (1, 0) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/peak2rms.m������������������������������������������������������������������������0000644�0000000�0000000�00000003510�14673270174�012616� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2015 Andreas Weber <octave@tech-chat.de> ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} peak2rms (@var{x}) ## @deftypefnx {Function File} {@var{y} =} peak2rms (@var{x}, @var{dim}) ## Compute the ratio of the largest absolute value to the root-mean-square ## (RMS) value of the vector @var{x}. ## ## If @var{x} is a matrix, compute the peak-magnitude-to-RMS ratio for each ## column and return them in a row vector. ## ## If the optional argument @var{dim} is given, operate along this dimension. ## @seealso{max, min, peak2peak, rms, rssq} ## @end deftypefn function y = peak2rms (x, dim) if (nargin < 1 || nargin > 2) print_usage (); endif if (nargin == 1) y = max (abs (x)) ./ sqrt (meansq (x)); else y = max (abs (x), [], dim) ./ sqrt (meansq (x, dim)); endif endfunction %!assert (peak2rms (1), 1) %!assert (peak2rms (-5), 1) %!assert (peak2rms ([-2 3; 4 -2]), [4/sqrt(10), 3/sqrt((9+4)/2)]) %!assert (peak2rms ([-2 3; 4 -2], 2), [3/sqrt((9+4)/2); 4/sqrt(10)]) %!assert (peak2rms ([1 2 3], 3), [1 1 1]) ## Test input validation %!error peak2rms () %!error peak2rms (1, 2, 3) %!error peak2rms (1, 1.5) %!error peak2rms (1, -1) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/pei_tseng_notch.m�����������������������������������������������������������������0000644�0000000�0000000�00000010433�14673270174�014244� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2011 Alexander Klein <alexander.klein@math.uni-giessen.de> ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{b}, @var{a}] =} pei_tseng_notch (@var{frequencies}, @var{bandwidths}) ## Return coefficients for an IIR notch-filter with one or more filter frequencies and according (very narrow) bandwidths ## to be used with @code{filter} or @code{filtfilt}. ## The filter construction is based on an allpass which performs a reversal of phase at the filter frequencies. ## Thus, the mean of the phase-distorted and the original signal has the respective frequencies removed. ## See the demo for an illustration. ## ## Original source: ## Pei, Soo-Chang, and Chien-Cheng Tseng ## "IIR Multiple Notch Filter Design Based on Allpass Filter" ## 1996 IEEE Tencon ## doi: 10.1109/TENCON.1996.608814) ## @end deftypefn ## FIXME: Implement Laplace-space frequencies and bandwidths, and perhaps ## better range checking for bandwidths? function [ b, a ] = pei_tseng_notch ( frequencies, bandwidths ) err = nargchk ( 2, 2, nargin, "string" ); if ( err ) error ( err ); elseif ( !isvector ( frequencies ) || !isvector ( bandwidths ) ) error ( "All arguments must be vectors!" ) elseif ( length ( frequencies ) != length ( bandwidths ) ) error ( "All arguments must be of equal length!" ) elseif ( !all ( frequencies > 0 && frequencies < 1 ) ) error ( "All frequencies must be in (0, 1)!" ) elseif ( !all ( bandwidths > 0 && bandwidths < 1 ) ) error ( "All bandwidths must be in (0, 1)!" ) endif ## Ensure row vectors frequencies = frequencies (:)'; bandwidths = bandwidths (:)'; ## Normalize appropriately frequencies *= pi; bandwidths *= pi; M2 = 2 * length ( frequencies ); ## Splice center and offset frequencies ( Equation 11 ) omega = vec ( [ frequencies - bandwidths / 2; frequencies ] ); ## Splice center and offset phases ( Equations 12 ) factors = ( 1 : 2 : M2 ); phi = vec ( [ -pi * factors + pi / 2; -pi * factors ] ); ## Create linear equation t_beta = tan ( ( phi + M2 * omega ) / 2 ); Q = zeros ( M2 ); for k = 1 : M2 Q ( : ,k ) = sin ( k .* omega ) - t_beta .* cos ( k .* omega ); endfor ## Compute coefficients of system function ( Equations 19, 20 ) ... h_a = ( Q \ t_beta )' ; denom = [ 1, h_a ]; num = [ fliplr( h_a ), 1 ]; ## ... and transform them to coefficients for difference equations a = denom; b = ( num + denom ) / 2; endfunction %!test %! ## 2Hz bandwidth %! sf = 800; sf2 = sf/2; %! data=[sinetone(49,sf,10,1),sinetone(50,sf,10,1),sinetone(51,sf,10,1)]; %! [b, a] = pei_tseng_notch ( 50 / sf2, 2 / sf2 ); %! filtered = filter ( b, a, data ); %! damp_db = 20 * log10 ( max ( filtered ( end - 1000 : end, : ) ) ); %! assert ( damp_db, [ -3 -251.9 -3 ], -0.1 ) %!test %! ## 1Hz bandwidth %! sf = 800; sf2 = sf/2; %! data=[sinetone(49.5,sf,10,1),sinetone(50,sf,10,1),sinetone(50.5,sf,10,1)]; %! [b, a] = pei_tseng_notch ( 50 / sf2, 1 / sf2 ); %! filtered = filter ( b, a, data ); %! damp_db = 20 * log10 ( max ( filtered ( end - 1000 : end, : ) ) ); %! assert ( damp_db, [ -3 -240.4 -3 ], -0.1 ) %!demo %! sf = 800; sf2 = sf/2; %! data=[[1;zeros(sf-1,1)],sinetone(49,sf,1,1),sinetone(50,sf,1,1),sinetone(51,sf,1,1)]; %! [b,a]=pei_tseng_notch ( 50 / sf2, 2/sf2 ); %! filtered = filter(b,a,data); %! %! clf %! subplot ( columns ( filtered ), 1, 1) %! plot(filtered(:,1),";Impulse response;") %! subplot ( columns ( filtered ), 1, 2 ) %! plot(filtered(:,2),";49Hz response;") %! subplot ( columns ( filtered ), 1, 3 ) %! plot(filtered(:,3),";50Hz response;") %! subplot ( columns ( filtered ), 1, 4 ) %! plot(filtered(:,4),";51Hz response;") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/phasez.m��������������������������������������������������������������������������0000644�0000000�0000000�00000012467�14673270174�012377� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2023 Leonardo Araujo <leolca@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{phi}, @var{w}] = } phasez (@var{b}, @var{a}, @var{n}) ## @deftypefnx {Function File} {[@var{phi}, @var{w}] = } phasez (@var{b}, @var{a}) ## @deftypefnx {Function File} {[@var{phi}, @var{w}] = } phasez (@var{sos}, @var{n}) ## @deftypefnx {Function File} {[@var{phi}, @var{w}] = } phasez (@var{sos}) ## @deftypefnx {Function File} {[@var{phi}, @var{w}] = } phasez (@dots{}, @var{n}, "whole") ## @deftypefnx {Function File} {[@var{phi}, @var{w}] = } phasez (@dots{}, @var{n}, Fs) ## @deftypefnx {Function File} {} phasez (@dots{}) ## ## Compute the phase response of digital filter defined either by its ## coefficients (@var{b} and @var{a} are the numerator and denominator ## coefficients respectively) or by its second-order sections representation, ## given by the matrix @var{sos}. The output @var{phi} is the phase response ## computed in a vector the vector of frequencies @var{w}. ## ## The phase response is evaluated at @var{n} angular frequencies between ## 0 and ## @ifnottex ## pi. ## @end ifnottex ## @tex ## $\pi$. ## @end tex ## ## @noindent ## If @var{a} is omitted, the denominator is assumed to be 1 (this ## corresponds to a simple FIR filter). ## ## If @var{n} is omitted, a value of 512 is assumed. ## ## If the third/forth argument, @qcode{"whole"}, is given, the response is ## evaluated at @var{n} angular frequencies between 0 and ## @ifnottex ## 2*pi. ## @end ifnottex ## @tex ## $\pi$. ## @end tex ## It is possible also to pass the value @qcode{"half"}, which will lead to ## the default behaviour. ## ## Example: ## @example ## [b, a] = butter (2, [.15,.3]); ## phasez (b, a); ## @end example ## ## Ref [1] Oppenheim, Alan, and Ronald Schafer. Discrete-Time Signal Processing. ## 3rd edition, Pearson, 2009. ## ## @seealso{freqz, phasedelay} ## @end deftypefn function [phi, w] = phasez (b, a, n, region, Fs) if (nargin < 1 || nargin > 5) print_usage; elseif nargin == 1 a = 1; region = Fs = []; n = 512; elseif nargin == 2 if (! ismatrix (b) || ! ismatrix (a)), print_usage; endif n = 512; region = Fs = []; elseif nargin == 3 if size (b, 1) > 1 && size (b, 2) == 6, if ischar (n) region = n; n = a; Fs = []; else Fs = n; n = a; endif else if ! isscalar (n), print_usage; endif region = Fs = []; endif elseif nargin ==4 if ischar (region) Fs = []; else Fs = region; region = []; endif elseif nargin == 5 && ! ischar (region), print_usage; endif if isrow (b) [h, w] = freqz (b, a, n, region, Fs); phi = my_unwrap(angle(h)); elseif (size (b, 1) > 1 && size (b, 2) == 6) phi = zeros (n, 1); for i=1:size (b,1) [h, w] = freqz (b(i,1:3), b(i,4:6), n, region, Fs); phi += my_unwrap(angle(h)); endfor endif switch nargout case 0 if isempty (Fs), plot (w/pi, phi); xlabel ( 'Normalized Frequency (\times\pi rad/sample)' ); else plot (w, phi); xlabel ( "Frequency (Hz)" ); xlim ([0 Fs/2]); endif ylabel ( "Phase (radians)" ); grid ("on"); case 1 varargout = {phi}; case 2 varargout = {phi, w}; endswitch endfunction %!demo %! N = 2; %! b = ones (1, N)/N; %! a = 1; %! [phi, w] = phasez (b, a) %! ## test input validation %!error n = phasez () %!error n = phasez (1, 1, 1, 1, 1) %!error n = phasez (1:10, 1:10, 1:10) %!error n = phasez (ones (3), ones (3)) %!test %! % moving average %! N = 2; %! b = ones (1, N)/N; %! a = 1; %! [phi, w] = phasez (b, a); %! PHI = -w * (N-1) /2; %! assert (phi, PHI, eps^(3/5)) %!test %! % moving average %! N = 5; %! b = ones (1, N)/N; %! a = 1; %! [phi, w] = phasez (b, a); %! PHI = -w * (N-1) /2; %! assert (phi, PHI, eps^(3/5)) %!test %! % Oppenheim - Example 5.6 - 2nd-Order IIR System %! % %! % 1 %! % H(z) = --------------------------- %! % 1 − 2r cos θz^−1 + r^2 z^−2 %! % %! % ang(H(e^jω)) = − arctan[ r sin(ω − θ) / (1 − r cos(ω − θ)) ] − arctan[ r sin(ω + θ) / (1 − r cos(ω + θ)) ] %! % %! r = 0.5; theta = pi/4; %! b = 1; %! a = [ 1 -2*r*cos(theta) r^2]; %! [phi, w] = phasez (b, a); %! PHI = - atan ( r*sin (w - theta) ./ (1 - r*cos (w - theta)) ) - atan ( r*sin (w + theta) ./ (1 - r*cos (w+theta)) ); %! assert (phi, PHI, eps^(3/5)) function x = my_unwrap ( x ) stillunwrap = true; while stillunwrap, dx = diff (x); idx = find (abs(dx) > pi-0.05 , 1); if ! isempty (idx), if dx(idx) > 0, x(idx+1:end)-=pi; else x(idx+1:end)+=pi; endif else stillunwrap = false; endif endwhile endfunction ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/poisswin.m������������������������������������������������������������������������0000644�0000000�0000000�00000004215�14673270174�012750� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2023 The Octave Project Developers ## ## See the file COPYRIGHT.md in the top-level directory of this ## distribution or <https://octave.org/copyright/>. ## ## This file is part of Octave. ## ## Octave 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. ## ## Octave 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 Octave; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} poisswin (@var{m}, @var{alpha}) ## Return the coefficients of a Poisson (a.k.a. exponential) window@footnote{S. ## Gade & H. Herlufsen, `Windows to FFT analysis (Part I)', Technical Review 3, ## Bruel & Kjaer, 1987} of length @var{m} and adjustable parameter ## @var{alpha}. ## @end deftypefn function W = poisswin (m, a) if nargin!=2 print_usage (); elseif !isscalar (m) || imag (m) || mod (m,1) || m<0 error ('poisswin: M must be a positive integer'); elseif !isscalar (a) || imag (a) error ('poisswin: ALPHA must be a real scalar'); endif if m<3 W = ones (m,1); return endif T = [1-m:2:0]/(m-1); T -= T(end); W = exp (a*T); W = [W W(m-length (W):-1:1)]'; endfunction %!test % even M; odd alpha: %! w=[0.3878 0.4308 0.4786 0.5318 0.5908 0.6564 0.7292 0.8102 0.9001 1]; %! assert (poisswin (20, 1), [w flip(w)]', 51e-6); %!test % odd M; even alpha: %! w=[0.1353 0.1653 0.2019 0.2466 0.3012 0.3679 0.4493 0.5488 0.6703 0.8187]; %! assert (poisswin (21, 2), [w 1 flip(w)]', 51e-6); %% Test input validation: %!error poisswin %!error poisswin (21.5,1) %!error poisswin (21i,1) %!error poisswin (21:22,1) %!error poisswin ({21},1) %!error poisswin (21, 4i) %!error poisswin (21, 2:3) %!error poisswin (21, {4}) %!error poisswin (21, 4, 1) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/polystab.m������������������������������������������������������������������������0000644�0000000�0000000�00000002043�14673270174�012727� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## b = polystab(a) ## ## Stabilize the polynomial transfer function by replacing all roots ## outside the unit circle with their reflection inside the unit circle. function b = polystab(a) r = roots(a); v = find(abs(r)>1); r(v) = 1./conj(r(v)); b = a(1) * poly ( r ); if isreal(a), b = real(b); endif endfunction ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/pow2db.m��������������������������������������������������������������������������0000644�0000000�0000000�00000003415�14673270174�012273� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2018 P Sudeepam ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} pow2db (@var{x}) ## Convert power to decibels (dB). ## ## The decibel value of @var{x} is defined as ## @tex ## $d = 10 * \log_{10} (x)$. ## @end tex ## @ifnottex ## @var{d} = @code{10 * log10 (x)}. ## @end ifnottex ## ## If @var{x} is a vector, matrix, or N-dimensional array, the decibel value ## is computed over the elements of @var{x}. ## ## Examples: ## ## @example ## @group ## pow2db ([0, 10, 100]) ## @result{} -Inf 10 20 ## @end group ## @end example ## @seealso{db2pow} ## @end deftypefn function y = pow2db (x) if (nargin != 1) print_usage (); endif if (any (x < 0)) error ("pow2db: X must be non-negative"); endif y = 10 .* log10 (x); endfunction %!shared pow %! pow = [0, 10, 20, 60, 100]; %!assert (pow2db (pow), [-Inf, 10.000, 13.010, 17.782, 20.000], 0.01) %!assert (pow2db (pow'), [-Inf; 10.000; 13.010; 17.782; 20.000], 0.01) ## Test input validation %!error pow2db () %!error pow2db (1, 2) %!error <pow2db: X must be non-negative> pow2db (-5) %!error <pow2db: X must be non-negative> pow2db ([-5 7]) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/primitive.m�����������������������������������������������������������������������0000644�0000000�0000000�00000004703�14673270174�013107� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013 Juan Pablo Carbajal ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{F} =} primitive (@var{f}, @var{t}, @var{F0}) ## Calculate the primitive of a function. ## ## The function approximates the primitive (indefinite integral) of the ## univariate function handle @var{f} with constant of integration @var{F0}. ## The output is the primitive evaluated at the points @var{t}. The vector ## @var{t} must be ordered and ascending. ## ## This function is a fancy way of calculating the cumulative sum, ## ## @command{F = cumsum (f(t).*diff (t)([1 1:end]))}. ## ## Example: ## @example ## @group ## f = @@(t) sin (2 * pi * 3 * t); ## t = [0; sort(rand (100, 1))]; ## F = primitive (f, t, 0); ## t_true = linspace (0, 1, 1e3).'; ## F_true = (1 - cos (2 * pi * 3 * t_true)) / (2 * pi * 3); ## plot (t, F, 'o', t_true, F_true); ## @end group ## @end example ## ## @seealso{quadgk, cumsum} ## @end deftypefn function F = primitive (f, t, C = 0) if (nargin < 2 || nargin > 3) print_usage (); endif i_chunk (0, 0, []); F = arrayfun (@(x) i_chunk (f, x, C), t); endfunction function F = i_chunk (f, t, init) persistent F_prev t0 if isempty (init) F_prev = []; t0 = 0; elseif isempty (F_prev) F_prev = init; else F_prev += quadgk (f, t0, t); t0 = t; endif F = F_prev; endfunction %!demo %! f = @(t) sin (2*pi*3*t); %! t = [0; sort(rand (100, 1))]; %! F = primitive (f, t, 0); %! t_true = linspace (0, 1, 1e3).'; %! F_true = (1 - cos (2 * pi * 3 * t_true)) / (2 * pi * 3); %! h = plot (t, F, "o;Numerical primitive;", t_true, F_true, "-;True primitive;"); %! set (h, "linewidth", 2); %! title ("Numerical primitive evaluated at random time points"); ## Test input validation %!error primitive () %!error primitive (1) %!error primitive (1, 2, 3, 4) �������������������������������������������������������������signal-1.4.6/inst/private/��������������������������������������������������������������������������0000755�0000000�0000000�00000000000�14673270174�012367� 5����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/private/__fwht_opts__.m�����������������������������������������������������������0000644�0000000�0000000�00000004506�14673270174�015363� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{y}, @var{len}] =} __fwht_opts__ (@var{caller}, @var{x}, @var{n}, @var{order}) ## Undocumented internal function. ## @end deftypefn function [y, len] = __fwht_opts__ (caller, x, n, order) if (nargin < 1) print_usage (); elseif (nargin != 4) print_usage (caller); endif [nr, nc] = size (x); if (isempty (n)) if (nr == 1) n = 2^nextpow2 (nc); else n = 2^nextpow2 (nr); endif elseif (!(isscalar (n) && n == fix (n) && n > 0)) error ("%s: N must be a positive scalar", caller); else f = log2(n); if (f != fix (f)) error ("%s: N must be a power of 2", caller); endif endif if (isempty (order)) order = "sequency"; endif if (!(strncmp (order, "dyadic", 6) || strncmp (order, "hadamard", 8) || strncmp (order, "sequency", 8))) error ("%s: invalid order option", caller); endif if (nr == 1) nc = n; x = x(:); else nr = n; endif ## Zero-based index for normal Hadamard ordering idx = 0:n-1; ## Gray code permutation of index for alternate orderings idx_bin = dec2bin (idx) - "0"; idx_bin_a = idx_bin(:,1:end-1); idx_bin_b = idx_bin(:,2:end); idx_bin(:,2:end) = mod (idx_bin_a + idx_bin_b, 2); idx_bin = char (idx_bin + "0"); if (strncmp (order, "dyadic", 6)) idx = bin2dec (fliplr (dec2bin (idx))) + 1; elseif (strncmp (order, "sequency", 8)) idx = bin2dec (fliplr (idx_bin)) + 1; else idx += 1; endif len = n; x = postpad (x, len); if (len < 2) y = x; else y = __fwht__ (x); endif y = reshape (y(idx,:), nr, nc); endfunction ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/private/h1_z_deriv.m��������������������������������������������������������������0000644�0000000�0000000�00000004620�14673270174�014601� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 R.G.H. Eschauzier <reschauzier@yahoo.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{b} =} h1_z_deriv (@var{n}, @var{p}, @var{ts}) ## Undocumented internal function. This function is used by the impinvar ## and invimpinvar functions in the signal package. ## @end deftypefn ## Adapted by CarnĂ« Draug on 2011 <carandraug+dev@gmail.com> ## Find {-zd/dz}^n*H1(z). I.e., first differentiate, then multiply by -z, then differentiate, etc. ## The result is (ts^(n+1))*(b(1)*p/(z-p)^1 + b(2)*p^2/(z-p)^2 + b(n+1)*p^(n+1)/(z-p)^(n+1)). ## Works for n>0. function b = h1_z_deriv(n, p, ts) ## Build the vector d that holds coefficients for all the derivatives of H1(z) ## The results reads d(n)*z^(1)*(d/dz)^(1)*H1(z) + d(n-1)*z^(2)*(d/dz)^(2)*H1(z) +...+ d(1)*z^(n)*(d/dz)^(n)*H1(z) d = (-1)^n; # Vector with the derivatives of H1(z) for i= (1:n-1) d = [d 0]; # Shift result right (multiply by -z) d += prepad(polyder(d), i+1, 0, 2); # Add the derivative endfor ## Build output vector b = zeros (1, n + 1); for i = (1:n) b += d(i) * prepad(h1_deriv(n-i+1), n+1, 0, 2); endfor b *= ts^(n+1)/factorial(n); ## Multiply coefficients with p^i, where i is the index of the coeff. b.*=p.^(n+1:-1:1); endfunction ## Find (z^n)*(d/dz)^n*H1(z), where H1(z)=ts*z/(z-p), ts=sampling period, ## p=exp(sm*ts) and sm is the s-domain pole with multiplicity n+1. ## The result is (ts^(n+1))*(b(1)*p/(z-p)^1 + b(2)*p^2/(z-p)^2 + b(n+1)*p^(n+1)/(z-p)^(n+1)), ## where b(i) is the binomial coefficient bincoeff(n,i) times n!. Works for n>0. function b = h1_deriv(n) b = factorial(n)*bincoeff(n,0:n); # Binomial coefficients: [1], [1 1], [1 2 1], [1 3 3 1], etc. b *= (-1)^n; endfunction ����������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/private/inv_residue.m�������������������������������������������������������������0000644�0000000�0000000�00000004465�14673270174�015072� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 R.G.H. Eschauzier <reschauzier@yahoo.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{b_out}, @var{a_out}] =} inv_residue (@var{r_in}, @var{p_in}, @var{k_in}, @var{tol}) ## Undocumented internal function. This function is used by the impinvar ## and invimpinvar functions in the signal package. ## @end deftypefn ## Adapted by CarnĂ« Draug on 2011 <carandraug+dev@gmail.com> ## Inverse of Octave residue function function [b_out, a_out] = inv_residue(r_in, p_in, k_in, tol) n = length(r_in); # Number of poles/residues k = 0; # Capture constant term if (length(k_in)==1) # A single direct term (order N = order D) k = k_in(1); # Capture constant term elseif (length(k_in)>1) # Greater than one means non-physical system error("Order numerator > order denominator"); endif a_out = poly(p_in); b_out = zeros(1,n+1); b_out += k*a_out; # Constant term: add k times denominator to numerator i=1; while (i<=n) term = [1 -p_in(i)]; # Term to be factored out p = r_in(i)*deconv(a_out,term); # Residue times resulting polynomial p = prepad(p, n+1, 0, 2); # Pad for proper length b_out += p; m = 1; mterm = term; first_pole = p_in(i); while (i<n && abs(first_pole-p_in(i+1))<tol) # Multiple poles at p(i) i++; # Next residue m++; mterm = conv(mterm, term); # Next multiplicity to be factored out p = r_in(i) * deconv(a_out, mterm); # Resulting polynomial p = prepad(p, n+1, 0, 2); # Pad for proper length b_out += p; endwhile i++; endwhile endfunction �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/private/polyrev.m�����������������������������������������������������������������0000644�0000000�0000000�00000002175�14673270174�014252� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 R.G.H. Eschauzier <reschauzier@yahoo.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{p_out} =} polyrev (@var{p_in}) ## Undocumented internal function. This function is used by the impinvar ## and invimpinvar functions in the signal package. ## @end deftypefn ## Adapted by CarnĂ« Draug on 2011 <carandraug+dev@gmail.com> ## Reverse the coefficients of a polynomial function p_out = polyrev (p_in) p_out = p_in(end:-1:1); endfunction ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/private/to_real.m�����������������������������������������������������������������0000644�0000000�0000000�00000002216�14673270174�014173� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 R.G.H. Eschauzier <reschauzier@yahoo.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{p_out} =} to_real (@var{p_in}) ## Undocumented internal function. This function is used by the impinvar ## and invimpinvar functions in the signal package. ## @end deftypefn ## Adapted by CarnĂ« Draug on 2011 <carandraug+dev@gmail.com> ## Round complex number to nearest real number function p_out = to_real(p_in) p_out = abs(p_in) .* sign(real(p_in)); endfunction ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/private/validate_filter_bands.m���������������������������������������������������0000644�0000000�0000000�00000005242�14673270174�017055� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2014-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} validate_filter_bands (@var{func}, @var{wp}, @var{ws}) ## @deftypefnx {Function File} {} validate_filter_bands (@var{func}, @var{wp}, @var{ws}, "s") ## Validate filter design frequency response bands. This is an internal ## convenience function used by @code{buttord}, @code{cheb1ord}, ## @code{cheb2ord}, @code{ellipord}. ## @end deftypefn function validate_filter_bands (func, wp, ws, opt) if (nargin < 3 || nargin > 4) print_usage (); elseif (nargin == 4 && ! strcmp (opt, "s")) error ("validate_filter_bands: OPT must be the string \"s\""); elseif (! ischar (func)) error ("validate_filter_bands: FUNC must be a string"); endif if (nargin == 4 && strcmp (opt, "s")) s_domain = true; else s_domain = false; endif if (! (isvector (wp) && isvector (ws) && (numel (wp) == numel (ws)))) error ([func ": WP and WS must both be scalars or vectors of length 2\n"]); elseif (! ((numel (wp) == 1) || (numel (wp) == 2))) error ([func ": WP and WS must both be scalars or vectors of length 2\n"]); elseif (! s_domain && ! (isreal (wp) && all (wp >= 0) && all (wp <= 1))) error ([func ": all elements of WP must be in the range [0,1]\n"]); elseif (! s_domain && ! (isreal (ws) && all (ws >= 0) && all (ws <= 1))) error ([func ": all elements of WS must be in the range [0,1]\n"]); elseif (s_domain && ! (isreal (wp) && all (wp >= 0))) error ([func ": all elements of WP must be non-negative\n"]); elseif (s_domain && ! (isreal (ws) && all (ws >= 0))) error ([func ": all elements of WS must be non-negative\n"]); elseif ((numel (wp) == 2) && (wp(2) <= wp(1))) error ([func ": WP(1) must be less than WP(2)\n"]) elseif ((numel (ws) == 2) && (ws(2) <= ws(1))) error ([func ": WS(1) must be less than WS(2)\n"]) elseif ((numel (wp) == 2) && (all (wp > ws) || all (ws > wp))) error ([func ": WP must be contained by WS or WS must be contained by WP\n"]); endif endfunction ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/pulstran.m������������������������������������������������������������������������0000644�0000000�0000000�00000014074�14673270174�012751� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} pulstran (@var{t}, @var{d}, @var{func}, @dots{}) ## @deftypefnx {Function File} {@var{y} =} pulstran (@var{t}, @var{d}, @var{p}) ## @deftypefnx {Function File} {@var{y} =} pulstran (@var{t}, @var{d}, @var{p}, @var{Fs}) ## @deftypefnx {Function File} {@var{y} =} pulstran (@var{t}, @var{d}, @var{p}, @var{Fs}, @var{method}) ## ## Generate the signal y=sum(func(t+d,...)) for each d. If d is a ## matrix of two columns, the first column is the delay d and the second ## column is the amplitude a, and y=sum(a*func(t+d)) for each d,a. ## Clearly, func must be a function which accepts a vector of times. ## Any extra arguments needed for the function must be tagged on the end. ## ## Example: ## @example ## fs = 11025; # arbitrary sample rate ## f0 = 100; # pulse train sample rate ## w = 0.001; # pulse width of 1 millisecond ## auplot (pulstran (0:1/fs:0.1, 0:1/f0:0.1, "rectpuls", w), fs); ## @end example ## ## If instead of a function name you supply a pulse shape sampled at ## frequency Fs (default 1 Hz), an interpolated version of the pulse ## is added at each delay d. The interpolation stays within the the ## time range of the delayed pulse. The interpolation method defaults ## to linear, but it can be any interpolation method accepted by the ## function interp1. ## ## Example: ## @example ## fs = 11025; # arbitrary sample rate ## f0 = 100; # pulse train sample rate ## w = boxcar(10); # pulse width of 1 millisecond at 10 kHz ## auplot (pulstran (0:1/fs:0.1, 0:1/f0:0.1, w, 10000), fs); ## @end example ## @end deftypefn ## FIXME: Make it faster. It is currently unusable for anything real. ## It may not be possible to speed it up with the present interface. ## See speech/voice.m for a better way. ## Note that pulstran can be used for some pretty strange things such ## as simple band-limited interpolation: ## xf = 0:0.05:10; yf = sin(2*pi*xf/5); ## xp = 0:10; yp = sin(2*pi*xp/5); # .2 Hz sine sampled every second ## s = pulstran(xf, [xp, yp],'sinc'); ## plot(f, yf, ";original;", xf, s, ";sinc;",xp,yp,"*;;"); ## You wouldn't want to do this in practice since it is expensive, and ## since it works much better with a windowed sinc function, at least ## for short samples. function y = pulstran(t, d, pulse, varargin) if nargin<3 || (!ischar(pulse) && nargin>5) print_usage; endif y = zeros(size(t)); if isempty(y), return; endif if rows(d) == 1, d=d'; endif if columns(d) == 2, a=d(:,2); else a=ones(rows(d),1); endif if ischar(pulse) ## apply function t+d for all d for i=1:rows(d) y = y+a(i)*feval(pulse,t-d(i,1),varargin{:}); endfor else ## interpolate each pulse at the specified times Fs = 1; method = 'linear'; if nargin==4 arg=varargin{1}; if ischar(arg), method=arg; else Fs = arg; endif elseif nargin==5 Fs = varargin{1}; method = varargin{2}; endif span = (length(pulse)-1)/Fs; t_pulse = (0:length(pulse)-1)/Fs; for i=1:rows(d) dt = t-d(i,1); idx = find(dt>=0 & dt<=span); y(idx) = y(idx) + a(i)*interp1(t_pulse, pulse, dt(idx), method); endfor endif endfunction %!error pulstran %!error pulstran(1,2,3,4,5,6) %!## parameter size and shape checking %!shared t,d %! t = 0:0.01:1; d=0:0.1:1; %!assert (isempty(pulstran([], d, 'sin'))); %!assert (pulstran(t, [], 'sin'), zeros(size(t))); %!assert (isempty(pulstran([], d, boxcar(5)))); %!assert (pulstran(t, [], boxcar(5)), zeros(size(t))); %!assert (size(pulstran(t,d,'sin')), size(t)); %!assert (size(pulstran(t,d','sin')), size(t)); %!assert (size(pulstran(t',d,'sin')), size(t')); %!assert (size(pulstran(t,d','sin')), size(t)); %!demo %! fs = 11025; # arbitrary sample rate %! f0 = 100; # pulse train sample rate %! w = 0.003; # pulse width of 3 milliseconds %! t = 0:1/fs:0.1; d=0:1/f0:0.1; # define sample times and pulse times %! a = hanning(length(d)); # define pulse amplitudes %! %! subplot(221); %! x = pulstran(t', d', 'rectpuls', w); %! plot([0:length(x)-1]*1000/fs, x); %! hold on; plot(d*1000,ones(size(d)),'g*;pulse;'); hold off; %! ylabel("amplitude"); xlabel("time (ms)"); %! title("rectpuls"); %! %! subplot(223); %! x = pulstran(f0*t, [f0*d', a], 'sinc'); %! plot([0:length(x)-1]*1000/fs, x); %! hold on; plot(d*1000,a,'g*;pulse;'); hold off; %! ylabel("amplitude"); xlabel("time (ms)"); %! title("sinc => band limited interpolation"); %! %! subplot(222); %! pulse = boxcar(30); # pulse width of 3 ms at 10 kHz %! x = pulstran(t, d', pulse, 10000); %! plot([0:length(x)-1]*1000/fs, x); %! hold on; plot(d*1000,ones(size(d)),'g*;pulse;'); hold off; %! ylabel("amplitude"); xlabel("time (ms)"); %! title("interpolated boxcar"); %! %! subplot(224); %! pulse = sin(2*pi*[0:0.0001:w]/w).*[w:-0.0001:0]; %! x = pulstran(t', [d', a], pulse', 10000); %! plot([0:length(x)-1]*1000/fs, x); %! hold on; plot(d*1000,a*w,'g*;pulse;'); hold off; title(""); %! ylabel("amplitude"); xlabel("time (ms)"); %! title("interpolated asymmetric sin"); %! %! %---------------------------------------------------------- %! % Should see (1) rectangular pulses centered on *, %! % (2) rectangular pulses to the right of *, %! % (3) smooth interpolation between the *'s, and %! % (4) asymmetric sines to the right of * ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/pwelch.m��������������������������������������������������������������������������0000644�0000000�0000000�00000114252�14673270174�012362� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{spectra},@var{freq}] =} pwelch(@var{x}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}, @var{range}, @var{plot_type}, @var{detrend}, @var{sloppy}) ## Estimate power spectral density of data "x" by the Welch (1967) periodogram/FFT method. ## ## All arguments except "x" are optional. ## ## The data is divided into segments. If "window" is a vector, each ## segment has the same length as "window" and is multiplied by "window" ## before (optional) zero-padding and calculation of its periodogram. If ## "window" is a scalar, each segment has a length of "window" and a ## Hamming window is used. ## ## The spectral density is the mean of the periodograms, scaled so that ## area under the spectrum is the same as the mean square of the ## data. This equivalence is supposed to be exact, but in practice there ## is a mismatch of up to 0.5% when comparing area under a periodogram ## with the mean square of the data. ## ## [spectra,freq] = pwelch(x,y,window,overlap,Nfft,Fs, ## range,plot_type,detrend,sloppy,results) ## ## Two-channel spectrum analyser. Estimate power spectral density, cross- ## spectral density, transfer function and/or coherence functions of time- ## series input data "x" and output data "y" by the Welch (1967) ## periodogram/FFT method. ## ## pwelch treats the second argument as "y" if there is a control-string ## argument "cross", "trans", "coher" or "ypower"; "power" does not force ## the 2nd argument to be treated as "y". All other arguments are ## optional. All spectra are returned in matrix "spectra". ## ## [spectra,Pxx_ci,freq] = pwelch(x,window,overlap,Nfft,Fs,conf, ## range,plot_type,detrend,sloppy) ## ## [spectra,Pxx_ci,freq] = pwelch(x,y,window,overlap,Nfft,Fs,conf, ## range,plot_type,detrend,sloppy,results) ## ## Estimates confidence intervals for the spectral density. ## ## See Hint (7) below for compatibility options. ## ## Confidence level "conf" is the 6th or 7th numeric argument. If "results" control-string ## arguments are used, one of them must be "power" when the "conf" ## argument is present; pwelch can estimate confidence intervals only for ## the power spectrum of the "x" data. It does not know how to estimate ## confidence intervals of the cross-power spectrum, transfer function or ## coherence; if you can suggest a good method, please send a bug report. ## ## ARGUMENTS ## ## All but the first argument are optional and may be empty, except that ## the "results" argument may require the second argument to be "y". ## @table @asis ## @item x ## [non-empty vector] system-input time-series data ## @item y ## [non-empty vector] system-output time-series data ## @item window ## [real vector] of window-function values; the ## data segment has the same length as the window. ## Default window shape is Hamming. ## ## [integer scalar] length of each data segment. The default ## value is window=sqrt(length(x)) rounded up to the ## nearest integer power of 2; see 'sloppy' argument. ## ## @item overlap ## [real scalar] segment overlap expressed as a multiple of ## window or segment length. 0 <= overlap < 1, ## The default is overlap=0.5 . ## ## @item Nfft ## [integer scalar] Length of FFT. The default is the length ## of the "window" vector or has the same value as the ## scalar "window" argument. If Nfft is larger than the ## segment length, "seg_len", the data segment is padded ## with "Nfft-seg_len" zeros. The default is no padding. ## Nfft values smaller than the length of the data ## segment (or window) are ignored silently. ## ## @item Fs ## [real scalar] sampling frequency (Hertz); default=1.0 ## ## @item conf ## [real scalar] confidence level between 0 and 1. Confidence ## intervals of the spectral density are estimated from ## scatter in the periodograms and are returned as Pxx_ci. ## Pxx_ci(:,1) is the lower bound of the confidence ## interval and Pxx_ci(:,2) is the upper bound. If there ## are three return values, or conf is an empty matrix, ## confidence intervals are calculated for conf=0.95 . ## If conf is zero or is not given, confidence intervals ## are not calculated. Confidence intervals can be ## obtained only for the power spectral density of x; ## nothing else. ## @end table ## ## CONTROL-STRING ARGUMENTS -- each of these arguments is a character string. ## Control-string arguments must be after the other arguments but can be in ## any order. ## ## @table @asis ## @item range ## 'half', 'onesided' : frequency range of the spectrum is ## zero up to but not including Fs/2. Power from ## negative frequencies is added to the positive side of ## the spectrum, but not at zero or Nyquist (Fs/2) ## frequencies. This keeps power equal in time and ## spectral domains. See reference [2]. ## ## 'whole', 'twosided' : frequency range of the spectrum is ## -Fs/2 to Fs/2, with negative frequencies ## stored in "wrap around" order after the positive ## frequencies; e.g. frequencies for a 10-point 'twosided' ## spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 ## ## 'shift', 'centerdc' : same as 'whole' but with the first half ## of the spectrum swapped with second half to put the ## zero-frequency value in the middle. (See "help ## fftshift". ## ## If data (x and y) are real, the default range is 'half', ## otherwise default range is 'whole'. ## ## @item plot_type ## 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': ## specifies the type of plot. The default is 'plot', which ## means linear-linear axes. 'squared' is the same as 'plot'. ## 'dB' plots "10*log10(psd)". This argument is ignored and a ## spectrum is not plotted if the caller requires a returned ## value. ## ## @item detrend ## 'no-strip', 'none' -- do NOT remove mean value from the data ## ## 'short', 'mean' -- remove the mean value of each segment from ## each segment of the data. ## ## 'linear', -- remove linear trend from each segment of ## the data. ## ## 'long-mean' -- remove the mean value from the data before ## splitting it into segments. This is the default. ## ## @item sloppy ## 'sloppy': FFT length is rounded up to the nearest integer ## power of 2 by zero padding. FFT length is adjusted ## after addition of padding by explicit Nfft argument. ## The default is to use exactly the FFT and window/ ## segment lengths specified in argument list. ## ## @item results ## specifies what results to return (in the order specified ## and as many as desired). ## ## 'power' calculate power spectral density of "x" ## ## 'cross' calculate cross spectral density of "x" and "y" ## ## 'trans' calculate transfer function of a system with ## input "x" and output "y" ## ## 'coher' calculate coherence function of "x" and "y" ## ## 'ypower' calculate power spectral density of "y" ## ## The default is 'power', with argument "y" omitted. ## @end table ## ## RETURNED VALUES: ## ## If return values are not required by the caller, the results are ## plotted and nothing is returned. ## ## @table @asis ## @item spectra ## [real-or-complex matrix] columns of the matrix contain results ## in the same order as specified by "results" arguments. ## Each column contains one of the result vectors. ## ## @item Pxx_ci ## [real matrix] estimate of confidence interval for power ## spectral density of x. First column is the lower ## bound. Second column is the upper bound. ## ## @item freq ## [real column vector] frequency values ## @end table ## ## HINTS ## @enumerate ## @item EMPTY ARGS: ## if you don't want to use an optional argument you can leave it empty ## by writing its value as []. ## ## @item FOR BEGINNERS: ## The profusion of arguments may make pwelch difficult to use, and an ## unskilled user can easily produce a meaningless result or can easily ## mis-interpret the result. With real data "x" and sampling frequency ## "Fs", the easiest and best way for a beginner to use pwelch is ## probably "pwelch(x,[],[],[],Fs)". Use the "window" argument to ## control the length of the spectrum vector. For real data and integer ## scalar M, "pwelch(x,2*M,[],[],Fs)" gives an M+1 point spectrum. ## Run "demo pwelch" (octave only). ## ## @item WINDOWING FUNCTIONS: ## Without a window function, sharp spectral peaks can have strong ## sidelobes because the FFT of a data in a segment is in effect convolved ## with a rectangular window. A window function which tapers off ## (gradually) at the ends produces much weaker sidelobes in the FFT. ## Hann (hanning), hamming, bartlett, blackman, flattopwin etc are ## available as separate Matlab/sigproc or Octave functions. The sidelobes ## of the Hann window have a roll-off rate of 60dB/decade of frequency. ## The first sidelobe of the Hamming window is suppressed and is about 12dB ## lower than the first Hann sidelobe, but the roll-off rate is only ## 20dB/decade. You can inspect the FFT of a Hann window by plotting ## "abs(fft(postpad(hanning(256),4096,0)))". ## The default window is Hamming. ## ## @item ZERO PADDING: ## Zero-padding reduces the frequency step in the ## spectrum, and produces an artificially smoothed spectrum. For example, ## "Nfft=2*length(window)" gives twice as many frequency values, but ## adjacent PSD (power spectral density) values are not independent; ## adjacent PSD values are independent if "Nfft=length(window)", which is ## the default value of Nfft. ## ## @item REMOVING MEAN FROM SIGNAL: ## If the mean is not removed from the signal there is a large spectral ## peak at zero frequency and the sidelobes of this peak are likely to ## swamp the rest of the spectrum. For this reason, the default behavior ## is to remove the mean. However, the matlab pwelch does not do this. ## ## @item WARNING ON CONFIDENCE INTERVALS ## Confidence intervals are obtained by measuring the sample variance of ## the periodograms and assuming that the periodograms have a Gaussian ## probability distribution. This assumption is not accurate. If, for ## example, the data (x) is Gaussian, the periodogram has a Rayleigh ## distribution. However, the confidence intervals may still be useful. ## ## @item COMPATIBILITY WITH Matlab R11, R12, etc ## When used without the second data (y) argument, arguments are compatible ## with the pwelch of Matlab R12, R13, R14, 2006a and 2006b except that ## ## 1) overlap is expressed as a multiple of window length --- ## effect of overlap scales with window length ## ## 2) default values of length(window), Nfft and Fs are more sensible, and ## ## 3) Goertzel algorithm is not available so Nfft cannot be an array of ## frequencies as in Matlab 2006b. ## ## Pwelch has four persistent Matlab-compatibility levels. Calling pwelch ## with an empty first argument sets the order of arguments and defaults ## specified above in the USAGE and ARGUMENTS section of this documentation. ## @example ## prev_compat=pwelch([]); ## [Pxx,f]=pwelch(x,window,overlap,Nfft,Fs,conf,...); ## @end example ## Calling pwelch with a single string argument (as described below) gives ## compatibility with Matlab R11 or R12, or the R14 spectrum.welch ## defaults. The returned value is the PREVIOUS compatibility string. ## ## Matlab R11: For compatibility with the Matlab R11 pwelch: ## @example ## prev_compat=pwelch('R11-'); ## [Pxx,f]=pwelch(x,Nfft,Fs,window,overlap,conf,range,units); ## %% units of overlap are "number of samples" ## %% defaults: Nfft=min(length(x),256), Fs=2*pi, length(window)=Nfft, ## %% window=Hanning, do not detrend, ## %% N.B. "Sloppy" is not available. ## @end example ## ## Matlab R12: For compatibility with Matlab R12 to 2006a pwelch: ## @example ## prev_compat=pwelch('R12+'); ## [Pxx,f]=pwelch(x,window,overlap,nfft,Fs,...); ## %% units of overlap are "number of samples" ## %% defaults: length(window)==length(x)/8, window=Hamming, ## %% Nfft=max(256,NextPow2), Fs=2*pi, do not detrend ## %% NextPow2 is the next power of 2 greater than or equal to the ## %% window length. "Sloppy", "conf" are not available. Default ## %% window length gives very poor amplitude resolution. ## @end example ## ## To adopt defaults of the Matlab R14 "spectrum.welch" spectrum object ## associated "psd" method. ## @example ## prev_compat=pwelch('psd'); ## [Pxx,f] = pwelch(x,window,overlap,Nfft,Fs,conf,...); ## %% overlap is expressed as a percentage of window length, ## %% defaults: length(window)==64, Nfft=max(256,NextPow2), Fs=2*pi ## %% do not detrend ## %% NextPow2 is the next power of 2 greater than or equal to the ## %% window length. "Sloppy" is not available. ## %% Default window length gives coarse frequency resolution. ## @end example ## @end enumerate ## ## REFERENCES ## ## [1] Peter D. Welch (June 1967): ## "The use of fast Fourier transform for the estimation of power spectra: ## a method based on time averaging over short, modified periodograms." ## IEEE Transactions on Audio Electroacoustics, Vol AU-15(6), pp 70-73 ## ## [2] William H. Press and Saul A. Teukolsky and William T. Vetterling and ## Brian P. Flannery", ## "Numerical recipes in C, The art of scientific computing", 2nd edition, ## Cambridge University Press, 2002 --- Section 13.7. ## @end deftypefn function varargout = pwelch(x,varargin) ## ## COMPATIBILITY LEVEL ## Argument positions and defaults depend on compatibility level selected ## by calling pwelch without arguments or with a single string argument. ## native: compatib=1; prev_compat=pwelch(); prev_compat=pwelch([]); ## matlab R11: compatib=2; prev_compat=pwelch('R11-'); ## matlab R12: compatib=3; prev_compat=pwelch('R12+'); ## spectrum.welch defaults: compatib=4; prev_compat=pwelch('psd'); ## In each case, the returned value is the PREVIOUS compatibility string. ## compat_str = {[]; 'R11-'; 'R12+'; 'psd'}; persistent compatib; if ( isempty(compatib) || compatib<=0 || compatib>4 ) ## legal values are 1, 2, 3, 4 compatib = 1; endif if ( nargin <= 0 ) error( 'pwelch: Need at least 1 arg. Use "help pwelch".' ); elseif ( nargin==1 && (ischar(x) || isempty(x)) ) varargout{1} = compat_str{compatib}; if ( isempty(x) ) # native compatib = 1; elseif ( strcmp(x,'R11-') ) compatib = 2; elseif ( strcmp(x,'R12+') ) compatib = 3; elseif ( strcmp(x,'psd') ) compatib = 4; else error( 'pwelch: compatibility arg must be empty, R11-, R12+ or psd' ); endif ## return ## ## Check fixed argument elseif ( isempty(x) || ~isvector(x) ) error( 'pwelch: arg 1 (x) must be vector.' ); else ## force x to be COLUMN vector if ( size(x,1)==1 ) x=x(:); endif ## ## Look through all args to check if cross PSD, transfer function or ## coherence is required. If yes, the second arg is data vector "y". arg2_is_y = 0; x_len = length(x); nvarargin = length(varargin); for iarg=1:nvarargin arg = varargin{iarg}; if ( ~isempty(arg) && ischar(arg) && ... ( strcmp(arg,'cross') || strcmp(arg,'trans') || ... strcmp(arg,'coher') || strcmp(arg,'ypower') )) ## OK. Need "y". Grab it from 2nd arg. arg = varargin{1}; if ( nargin<2 || isempty(arg) || ~isvector(arg) || length(arg)~=x_len ) error( 'pwelch: arg 2 (y) must be vector, same length as x.' ); endif ## force COLUMN vector y = varargin{1}(:); arg2_is_y = 1; break; endif endfor ## ## COMPATIBILITY ## To select default argument values, "compatib" is used as an array index. ## Index values are 1=native, 2=R11, 3=R12, 4=spectrum.welch ## ## argument positions: ## arg_posn = varargin index of window, overlap, Nfft, Fs and conf ## args respectively, a value of zero ==>> arg does not exist arg_posn = [1 2 3 4 5; # native 3 4 1 2 5; # Matlab R11- pwelch 1 2 3 4 0; # Matlab R12+ pwelch 1 2 3 4 5]; # spectrum.welch defaults arg_posn = arg_posn(compatib,:) + arg2_is_y; ## ## SPECIFY SOME DEFAULT VALUES for (not all) optional arguments ## Use compatib as array index. ## Fs = sampling frequency Fs = [ 1.0 2*pi 2*pi 2*pi ]; Fs = Fs(compatib); ## plot_type: 1='plot'|'squared'; 5='db'|'dB' plot_type = [ 1 5 5 5 ]; plot_type = plot_type(compatib); ## rm_mean: 3='long-mean'; 0='no-strip'|'none' rm_mean = [ 3 0 0 0 ]; rm_mean = rm_mean(compatib); ## use max_overlap=x_len-1 because seg_len is not available yet ## units of overlap are different for each version: ## fraction, samples, or percent max_overlap = [ 0.95 x_len-1 x_len-1 95]; max_overlap = max_overlap(compatib); ## default confidence interval ## if there are more than 2 return values and if there is a "conf" arg conf = 0.95 * (nargout>2) * (arg_posn(5)>0); ## is_win = 0; # =0 means valid window arg is not provided yet Nfft = []; # default depends on segment length overlap = []; # WARNING: units can be #samples, fraction or percentage range = ~isreal(x) || ( arg2_is_y && ~isreal(y) ); is_sloppy = 0; n_results = 0; do_power = 0; do_cross = 0; do_trans = 0; do_coher = 0; do_ypower = 0; ## ## DECODE AND CHECK OPTIONAL ARGUMENTS end_numeric_args = 0; for iarg = 1+arg2_is_y:nvarargin arg = varargin{iarg}; if ( ischar(arg) ) ## first string arg ==> no more numeric args ## non-string args cannot follow a string arg end_numeric_args = 1; ## ## decode control-string arguments if ( strcmp(arg,'sloppy') ) is_sloppy = ~is_win || is_win==1; elseif ( strcmp(arg,'plot') || strcmp(arg,'squared') ) plot_type = 1; elseif ( strcmp(arg,'semilogx') ) plot_type = 2; elseif ( strcmp(arg,'semilogy') ) plot_type = 3; elseif ( strcmp(arg,'loglog') ) plot_type = 4; elseif ( strcmp(arg,'db') || strcmp(arg,'dB') ) plot_type = 5; elseif ( strcmp(arg,'half') || strcmp(arg,'onesided') ) range = 0; elseif ( strcmp(arg,'whole') || strcmp(arg,'twosided') ) range = 1; elseif ( strcmp(arg,'shift') || strcmp(arg,'centerdc') ) range = 2; elseif ( strcmp(arg,'long-mean') ) rm_mean = 3; elseif ( strcmp(arg,'linear') ) rm_mean = 2; elseif ( strcmp(arg,'short') || strcmp(arg,'mean') ) rm_mean = 1; elseif ( strcmp(arg,'no-strip') || strcmp(arg,'none') ) rm_mean = 0; elseif ( strcmp(arg, 'power' ) ) if ( ~do_power ) n_results = n_results+1; do_power = n_results; endif elseif ( strcmp(arg, 'cross' ) ) if ( ~do_cross ) n_results = n_results+1; do_cross = n_results; endif elseif ( strcmp(arg, 'trans' ) ) if ( ~do_trans ) n_results = n_results+1; do_trans = n_results; endif elseif ( strcmp(arg, 'coher' ) ) if ( ~do_coher ) n_results = n_results+1; do_coher = n_results; endif elseif ( strcmp(arg, 'ypower' ) ) if ( ~do_ypower ) n_results = n_results+1; do_ypower = n_results; endif else error( 'pwelch: string arg %d illegal value: %s', iarg+1, arg ); endif ## end of processing string args ## elseif ( end_numeric_args ) if ( ~isempty(arg) ) ## found non-string arg after a string arg ... oops error( 'pwelch: control arg must be string' ); endif ## ## first 4 optional arguments are numeric -- in fixed order ## ## deal with "Fs" and "conf" first because empty arg is a special default ## -- "Fs" arg -- sampling frequency elseif ( iarg == arg_posn(4) ) if ( isempty(arg) ) Fs = 1; elseif ( ~isscalar(arg) || ~isreal(arg) || arg<0 ) error( 'pwelch: arg %d (Fs) must be real scalar >0', iarg+1 ); else Fs = arg; endif ## ## -- "conf" arg -- confidence level ## guard against the "it cannot happen" iarg==0 elseif ( arg_posn(5) && iarg == arg_posn(5) ) if ( isempty(arg) ) conf = 0.95; elseif ( ~isscalar(arg) || ~isreal(arg) || arg < 0.0 || arg >= 1.0 ) error( 'pwelch: arg %d (conf) must be real scalar, >=0, <1',iarg+1 ); else conf = arg; endif ## ## skip all empty args from this point onward elseif ( isempty(arg) ) 1; ## ## -- "window" arg -- window function elseif ( iarg == arg_posn(1) ) if ( isscalar(arg) ) is_win = 1; elseif ( isvector(arg) ) is_win = length(arg); if ( size(arg,2)>1 ) # vector must be COLUMN vector arg = arg(:); endif else is_win = 0; endif if ( ~is_win ) error( 'pwelch: arg %d (window) must be scalar or vector', iarg+1 ); elseif ( is_win==1 && ( ~isreal(arg) || fix(arg)~=arg || arg<=3 ) ) error( 'pwelch: arg %d (window) must be integer >3', iarg+1 ); elseif ( is_win>1 && ( ~isreal(arg) ) ) error( 'pwelch: arg %d (window) vector must be real and >=0',iarg+1); endif window = arg; is_sloppy = 0; ## ## -- "overlap" arg -- segment overlap elseif ( iarg == arg_posn(2) ) if (~isscalar(arg) || ~isreal(arg) || arg<0 || arg>max_overlap ) error( 'pwelch: arg %d (overlap) must be real from 0 to %f', ... iarg+1, max_overlap ); endif overlap = arg; ## ## -- "Nfft" arg -- FFT length elseif ( iarg == arg_posn(3) ) if ( ~isscalar(arg) || ~isreal(arg) || fix(arg)~=arg || arg<0 ) error( 'pwelch: arg %d (Nfft) must be integer >=0', iarg+1 ); endif Nfft = arg; ## else error( 'pwelch: arg %d must be string', iarg+1 ); endif endfor if ( conf>0 && (n_results && ~do_power ) ) error('pwelch: can give confidence interval for x power spectrum only' ); endif ## ## end DECODE AND CHECK OPTIONAL ARGUMENTS. ## ## SETUP REMAINING PARAMETERS ## default action is to calculate power spectrum only if ( ~n_results ) n_results = 1; do_power = 1; endif need_Pxx = do_power || do_trans || do_coher; need_Pxy = do_cross || do_trans || do_coher; need_Pyy = do_coher || do_ypower; log_two = log(2); nearly_one = 0.99999999999; ## ## compatibility-options ## provides exact compatibility with Matlab R11 or R12 ## ## Matlab R11 compatibility if ( compatib==2 ) if ( isempty(Nfft) ) Nfft = min( 256, x_len ); endif if ( is_win > 1 ) seg_len = min( length(window), Nfft ); window = window(1:seg_len); else if ( is_win ) ## window arg is scalar seg_len = window; else seg_len = Nfft; endif ## make Hann window (don't depend on sigproc) xx = seg_len - 1; window = 0.5 - 0.5 * cos( (2*pi/xx)*[0:xx].' ); endif ## ## Matlab R12 compatibility elseif ( compatib==3 ) if ( is_win > 1 ) ## window arg provides window function seg_len = length(window); else ## window arg does not provide window function; use Hamming if ( is_win ) ## window arg is scalar seg_len = window; else ## window arg not available; use R12 default, 8 windows ## ignore overlap arg; use overlap=50% -- only choice that makes sense ## this is the magic formula for 8 segments with 50% overlap seg_len = fix( (x_len-3)*2/9 ); endif ## make Hamming window (don't depend on sigproc) xx = seg_len - 1; window = 0.54 - 0.46 * cos( (2*pi/xx)*[0:xx].' ); endif if ( isempty(Nfft) ) Nfft = max( 256, 2^ceil(log(seg_len)*nearly_one/log_two) ); endif ## ## Matlab R14 psd(spectrum.welch) defaults elseif ( compatib==4 ) if ( is_win > 1 ) ## window arg provides window function seg_len = length(window); else ## window arg does not provide window function; use Hamming if ( is_win ) ## window arg is scalar seg_len = window; else ## window arg not available; use default seg_len = 64 seg_len = 64; endif ## make Hamming window (don't depend on sigproc) xx = seg_len - 1; window = 0.54 - 0.46 * cos( (2*pi/xx)*[0:xx].' ); endif ## Now we know segment length, ## so we can set default overlap as number of samples if ( ~isempty(overlap) ) overlap = fix(seg_len * overlap / 100 ); endif if ( isempty(Nfft) ) Nfft = max( 256, 2^ceil(log(seg_len)*nearly_one/log_two) ); endif ## ## default compatibility level else # if ( compatib==1 ) ## calculate/adjust segment length, window function if ( is_win > 1 ) ## window arg provides window function seg_len = length(window); else ## window arg does not provide window function; use Hamming if ( is_win ) # window arg is scalar seg_len = window; else ## window arg not available; use default length: ## = sqrt(length(x)) rounded up to nearest integer power of 2 if ( isempty(overlap) ) overlap=0.5; endif seg_len = 2 ^ ceil( log(sqrt(x_len/(1-overlap)))*nearly_one/log_two ); endif ## make Hamming window (don't depend on sigproc) xx = seg_len - 1; window = 0.54 - 0.46 * cos( (2*pi/xx)*[0:xx].' ); endif ## Now we know segment length, ## so we can set default overlap as number of samples if ( ~isempty(overlap) ) overlap = fix(seg_len * overlap); endif ## ## calculate FFT length if ( isempty(Nfft) ) Nfft = seg_len; endif if ( is_sloppy ) Nfft = 2 ^ ceil( log(Nfft) * nearly_one / log_two ); endif endif ## end of compatibility options ## ## minimum FFT length is seg_len Nfft = max( Nfft, seg_len ); ## Mean square of window is required for normalizing PSD amplitude. win_meansq = (window.' * window) / seg_len; ## ## Set default or check overlap. if ( isempty(overlap) ) overlap = fix(seg_len /2); elseif ( overlap >= seg_len ) error( 'pwelch: arg (overlap=%d) too big. Must be <length(window)=%d',... overlap, seg_len ); endif ## ## Pad data with zeros if shorter than segment. This should not happen. if ( x_len < seg_len ) x = [x; zeros(seg_len-x_len,1)]; if ( arg2_is_y ) y = [y; zeros(seg_len-x_len,1)]; endif x_len = seg_len; endif ## end SETUP REMAINING PARAMETERS ## ## ## MAIN CALCULATIONS ## Remove mean from the data if ( rm_mean == 3 ) n_ffts = max( 0, fix( (x_len-seg_len)/(seg_len-overlap) ) ) + 1; x_len = min( x_len, (seg_len-overlap)*(n_ffts-1)+seg_len ); if ( need_Pxx || need_Pxy ) x = x - sum( x(1:x_len) ) / x_len; endif if ( arg2_is_y || need_Pxy) y = y - sum( y(1:x_len) ) / x_len; endif endif ## ## Calculate and accumulate periodograms ## xx and yy are padded data segments ## Pxx, Pyy, Pyy are periodogram sums, Vxx is for confidence interval xx = zeros(Nfft,1); yy = xx; Pxx = xx; Pxy = xx; Pyy = xx; if ( conf>0 ) Vxx = xx; else Vxx = []; endif n_ffts = 0; for start_seg = [1:seg_len-overlap:x_len-seg_len+1] end_seg = start_seg+seg_len-1; ## Don't truncate/remove the zero padding in xx and yy if ( need_Pxx || need_Pxy ) if ( rm_mean==1 ) # remove mean from segment xx(1:seg_len) = window .* ( ... x(start_seg:end_seg) - sum(x(start_seg:end_seg)) / seg_len); elseif ( rm_mean == 2 ) # remove linear trend from segment xx(1:seg_len) = window .* detrend( x(start_seg:end_seg) ); else # rm_mean==0 or 3 xx(1:seg_len) = window .* x(start_seg:end_seg); endif fft_x = fft(xx); endif if ( need_Pxy || need_Pyy ) if ( rm_mean==1 ) # remove mean from segment yy(1:seg_len) = window .* ( ... y(start_seg:end_seg) - sum(y(start_seg:end_seg)) / seg_len); elseif ( rm_mean == 2 ) # remove linear trend from segment yy(1:seg_len) = window .* detrend( y(start_seg:end_seg) ); else # rm_mean==0 or 3 yy(1:seg_len) = window .* y(start_seg:end_seg); endif fft_y = fft(yy); endif if ( need_Pxx ) ## force Pxx to be real; pgram = periodogram pgram = real(fft_x .* conj(fft_x)); Pxx = Pxx + pgram; ## sum of squared periodograms is required for confidence interval if ( conf>0 ) Vxx = Vxx + pgram .^2; endif endif if ( need_Pxy ) ## Pxy (cross power spectrum) is complex. Do not force to be real. Pxy = Pxy + fft_y .* conj(fft_x); endif if ( need_Pyy ) ## force Pyy to be real Pyy = Pyy + real(fft_y .* conj(fft_y)); endif n_ffts = n_ffts +1; endfor ## ## Calculate confidence interval ## -- incorrectly assumes that the periodogram has Gaussian probability ## distribution (actually, it has a single-sided (e.g. exponential) ## distribution. ## Sample variance of periodograms is (Vxx-Pxx.^2/n_ffts)/(n_ffts-1). ## This method of calculating variance is more susceptible to round-off ## error, but is quicker, and for double-precision arithmetic and the ## inherently noisy periodogram (variance==mean^2), it should be OK. if ( conf>0 && need_Pxx ) if ( n_ffts<2 ) Vxx = zeros(Nfft,1); else ## Should use student distribution here (for unknown variance), but tinv ## is not a core Matlab function (is in statistics toolbox. Grrr) Vxx = (erfinv(conf)*sqrt(2*n_ffts/(n_ffts-1))) * sqrt(Vxx-Pxx.^2/n_ffts); endif endif ## ## Convert two-sided spectra to one-sided spectra (if range == 0). ## For one-sided spectra, contributions from negative frequencies are added ## to the positive side of the spectrum -- but not at zero or Nyquist ## (half sampling) frequencies. This keeps power equal in time and spectral ## domains, as required by Parseval theorem. ## if ( range == 0 ) if ( ~ rem(Nfft,2) ) # one-sided, Nfft is even psd_len = Nfft/2+1; if ( need_Pxx ) Pxx = Pxx(1:psd_len) + [0; Pxx(Nfft:-1:psd_len+1); 0]; if ( conf>0 ) Vxx = Vxx(1:psd_len) + [0; Vxx(Nfft:-1:psd_len+1); 0]; endif endif if ( need_Pxy ) Pxy = Pxy(1:psd_len) + conj([0; Pxy(Nfft:-1:psd_len+1); 0]); endif if ( need_Pyy ) Pyy = Pyy(1:psd_len) + [0; Pyy(Nfft:-1:psd_len+1); 0]; endif else # one-sided, Nfft is odd psd_len = (Nfft+1)/2; if ( need_Pxx ) Pxx = Pxx(1:psd_len) + [0; Pxx(Nfft:-1:psd_len+1)]; if ( conf>0 ) Vxx = Vxx(1:psd_len) + [0; Vxx(Nfft:-1:psd_len+1)]; endif endif if ( need_Pxy ) Pxy = Pxy(1:psd_len) + conj([0; Pxy(Nfft:-1:psd_len+1)]); endif if ( need_Pyy ) Pyy = Pyy(1:psd_len) + [0; Pyy(Nfft:-1:psd_len+1)]; endif endif else # two-sided (and shifted) psd_len = Nfft; endif ## end MAIN CALCULATIONS ## ## SCALING AND OUTPUT ## Put all results in matrix, one row per spectrum ## Pxx, Pxy, Pyy are sums of periodograms, so "n_ffts" ## in the scale factor converts them into averages spectra = zeros(psd_len,n_results); spect_type = zeros(n_results,1); scale = n_ffts * seg_len * Fs * win_meansq; if ( do_power ) spectra(:,do_power) = Pxx / scale; spect_type(do_power) = 1; if ( conf>0 ) Vxx = [Pxx-Vxx Pxx+Vxx]/scale; endif endif if ( do_cross ) spectra(:,do_cross) = Pxy / scale; spect_type(do_cross) = 2; endif if ( do_trans ) spectra(:,do_trans) = Pxy ./ Pxx; spect_type(do_trans) = 3; endif if ( do_coher ) ## force coherence to be real spectra(:,do_coher) = real(Pxy .* conj(Pxy)) ./ Pxx ./ Pyy; spect_type(do_coher) = 4; endif if ( do_ypower ) spectra(:,do_ypower) = Pyy / scale; spect_type(do_ypower) = 5; endif freq = [0:psd_len-1].' * ( Fs / Nfft ); ## ## range='shift': Shift zero-frequency to the middle if ( range == 2 ) len2 = fix((Nfft+1)/2); spectra = [ spectra(len2+1:Nfft,:); spectra(1:len2,:)]; freq = [ freq(len2+1:Nfft)-Fs; freq(1:len2)]; if ( conf>0 ) Vxx = [ Vxx(len2+1:Nfft,:); Vxx(1:len2,:)]; endif endif ## ## RETURN RESULTS or PLOT if ( nargout>=2 && conf>0 ) varargout{2} = Vxx; endif if ( nargout>=(2+(conf>0)) ) ## frequency is 2nd or 3rd return value, ## depends on if 2nd is confidence interval varargout{2+(conf>0)} = freq; endif if ( nargout>=1 ) varargout{1} = spectra; else ## ## Plot the spectra if there are no return variables. plot_title=['power spectrum x '; 'cross spectrum '; 'transfer function'; 'coherence '; 'power spectrum y ' ]; for ii = 1: n_results if ( conf>0 && spect_type(ii)==1 ) Vxxxx = Vxx; else Vxxxx = []; endif if ( n_results > 1 ) figure(); endif if ( plot_type == 1 ) plot(freq,[abs(spectra(:,ii)) Vxxxx]); elseif ( plot_type == 2 ) semilogx(freq,[abs(spectra(:,ii)) Vxxxx]); elseif ( plot_type == 3 ) semilogy(freq,[abs(spectra(:,ii)) Vxxxx]); elseif ( plot_type == 4 ) loglog(freq,[abs(spectra(:,ii)) Vxxxx]); elseif ( plot_type == 5 ) # db ylabel( 'amplitude (dB)' ); plot(freq,[10*log10(abs(spectra(:,ii))) 10*log10(abs(Vxxxx))]); endif title( char(plot_title(spect_type(ii),:)) ); ylabel( 'amplitude' ); ## Plot phase of cross spectrum and transfer function if ( spect_type(ii)==2 || spect_type(ii)==3 ) figure(); if ( plot_type==2 || plot_type==4 ) semilogx(freq,180/pi*angle(spectra(:,ii))); else plot(freq,180/pi*angle(spectra(:,ii))); endif title( char(plot_title(spect_type(ii),:)) ); ylabel( 'phase' ); endif endfor endif endif endfunction %!demo %! a = [ 1.0 -1.6216505 1.1102795 -0.4621741 0.2075552 -0.018756746 ]; %! white = rand(1,16384); %! signal = detrend(filter(0.70181,a,white)); %! % frequency shift by modulating with exp(j.omega.t) %! skewed = signal.*exp(2*pi*i*2/25*[1:16384]); %! compat = pwelch ([]); %! hold on; %! pwelch(signal); %! pwelch(skewed); %! pwelch(signal,'shift','semilogy'); %! pwelch (compat); %! hold off; %!demo %! Fs = 25; %! a = [ 1.0 -1.6216505 1.1102795 -0.4621741 0.2075552 -0.018756746 ]; %! white = rand(1,16384); %! signal = detrend(filter(0.70181,a,white)); %! % frequency shift by modulating with exp(j.omega.t) %! skewed = signal.*exp(2*pi*i*2/25*[1:16384]); %! compat = pwelch ([]); %! pwelch(skewed,[],[],[],Fs,'shift','semilogy'); %! pwelch(skewed,[],[],[],Fs,0.95,'shift','semilogy'); %! pwelch('R12+'); %! pwelch(signal,'squared'); %! pwelch (compat); %!demo %! a = [ 1.0 -1.6216505 1.1102795 -0.4621741 0.2075552 -0.018756746 ]; %! white = rand(1,16384); %! signal = detrend(filter(0.70181,a,white)); %! compat = pwelch ([]); %! pwelch(signal,3640,[],4096,2*pi,[],'no-strip'); %! pwelch (compat); %!demo %! a = [ 1.0 -1.6216505 1.1102795 -0.4621741 0.2075552 -0.018756746 ]; %! white = rand(1,16384); %! signal = detrend(filter(0.70181,a,white)); %! compat = pwelch ([]); %! hold on; %! pwelch(signal,[],[],[],2*pi,0.95,'no-strip'); %! pwelch(signal,64,[],[],2*pi,'no-strip'); %! pwelch(signal,64,[],256,2*pi,'no-strip'); %! pwelch (compat); %! hold off; %!demo %! a = [ 1.0 -1.6216505 1.1102795 -0.4621741 0.2075552 -0.018756746 ]; %! white = rand(1,16384); %! signal = detrend(filter(0.70181,a,white)); %! compat = pwelch ('psd'); %! pwelch(signal,'squared'); %! pwelch({}); %! pwelch(white,signal,'trans','coher','short') %! pwelch (compat); ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/pyulear.m�������������������������������������������������������������������������0000644�0000000�0000000�00000011627�14673270174�012563� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[psd,f_out] =} pyulear(x,poles,freq,Fs,range,method,plot_type) ## Calculates a Yule-Walker autoregressive (all-pole) model of the data "x" ## and computes the power spectrum of the model. ## ## This is a wrapper for functions "aryule" and "ar_psd" which perform the ## argument checking. ## ## See "help aryule" and "help ar_psd" for further details. ## ## ARGUMENTS: ## ## All but the first two arguments are optional and may be empty. ## @table @asis ## @item x ## [vector] sampled data ## ## @item poles ## [integer scalar] required number of poles of the AR model ## ## @item freq ## [real vector] frequencies at which power spectral density ## is calculated ## ## [integer scalar] number of uniformly distributed frequency ## values at which spectral density is calculated. ## [default=256] ## ## @item Fs ## [real scalar] sampling frequency (Hertz) [default=1] ## @end table ## ## CONTROL-STRING ARGUMENTS -- each of these arguments is a character string. ## ## Control-string arguments can be in any order after the other arguments. ## ## @table @asis ## @item range ## 'half', 'onesided' : frequency range of the spectrum is ## from zero up to but not including sample_f/2. Power ## from negative frequencies is added to the positive ## side of the spectrum. ## ## 'whole', 'twosided' : frequency range of the spectrum is ## -sample_f/2 to sample_f/2, with negative frequencies ## stored in "wrap around" order after the positive ## frequencies; e.g. frequencies for a 10-point 'twosided' ## spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1 ## ## 'shift', 'centerdc' : same as 'whole' but with the first half ## of the spectrum swapped with second half to put the ## zero-frequency value in the middle. (See "help ## fftshift". If "freq" is vector, 'shift' is ignored. ## ## If model coefficients "ar_coeffs" are real, the default ## range is 'half', otherwise default range is 'whole'. ## ## @item method ## 'fft': use FFT to calculate power spectrum. ## ## 'poly': calculate power spectrum as a polynomial of 1/z ## N.B. this argument is ignored if the "freq" argument is a ## vector. The default is 'poly' unless the "freq" ## argument is an integer power of 2. ## ## @item plot_type ## 'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db': ## specifies the type of plot. The default is 'plot', which ## means linear-linear axes. 'squared' is the same as 'plot'. ## 'dB' plots "10*log10(psd)". This argument is ignored and a ## spectrum is not plotted if the caller requires a returned ## value. ## @end table ## ## RETURNED VALUES: ## ## If return values are not required by the caller, the spectrum ## is plotted and nothing is returned. ## ## @table @asis ## @item psd ## [real vector] power-spectrum estimate ## @item f_out ## [real vector] frequency values ## @end table ## ## HINTS ## ## This function is a wrapper for aryule and ar_psd. ## ## See "help aryule", "help ar_psd". ## @end deftypefn function [psd,f_out]=pyulear(x,poles,varargin) ## if ( nargin<2 ) error( 'pburg: need at least 2 args. Use "help pburg"' ); endif ## [ar_coeffs,residual,k]=aryule(x,poles); if ( nargout==0 ) ar_psd(ar_coeffs,residual,varargin{:}); elseif ( nargout==1 ) psd = ar_psd(ar_coeffs,residual,varargin{:}); elseif ( nargout>=2 ) [psd,f_out] = ar_psd(ar_coeffs,residual,varargin{:}); endif endfunction %!demo %! a = [1.0 -1.6216505 1.1102795 -0.4621741 0.2075552 -0.018756746]; %! Fs = 25; %! n = 16384; %! signal = detrend (filter (0.70181, a, rand (1, n))); %! % frequency shift by modulating with exp(j.omega.t) %! skewed = signal .* exp (2*pi*i*2/Fs*[1:n]); %! hold on; %! pyulear (signal, 3, [], Fs); %! pyulear (signal, 4, [], Fs, "whole"); %! pyulear (signal, 5, 128, Fs, "shift", "semilogy"); %! pyulear (skewed, 7, 128, Fs, "shift", "semilogy"); %! user_freq = [-0.2:0.02:0.2]*Fs; %! pyulear (skewed, 7, user_freq, Fs, "semilogy"); %! hold off; ���������������������������������������������������������������������������������������������������������signal-1.4.6/inst/qp_kaiser.m�����������������������������������������������������������������������0000644�0000000�0000000�00000005526�14673270174�013061� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2002 AndrĂ© Carezia <andre@carezia.eng.br> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} qp_kaiser (@var{nb}, @var{at}) ## @deftypefnx {Function File} {} qp_kaiser (@var{nb}, @var{at}, @var{linear}) ## ## Computes a finite impulse response (FIR) filter for use with a ## quasi-perfect reconstruction polyphase-network filter bank. This ## version utilizes a Kaiser window to shape the frequency response of ## the designed filter. Tha number nb of bands and the desired ## attenuation at in the stop-band are given as parameters. ## ## The Kaiser window is multiplied by the ideal impulse response ## h(n)=a.sinc(a.n) and converted to its minimum-phase version by means ## of a Hilbert transform. ## ## By using a third non-null argument, the minimum-phase calculation is ## omitted at all. ## @end deftypefn function h = qp_kaiser (nb, at, linear = 0) if (nargin < 2) print_usage; elseif !(isscalar (nb) && (nb == round(nb)) && (nb >= 0)) error ("qp_kaiser: nb has to be a positive integer"); elseif !(isscalar (at) && (at == real (at))) error ("qp_kaiser: at has to be a real constant"); endif ## Bandwidth bandwidth = pi/nb; ## Attenuation correction (empirically ## determined by M. Gerken ## <mgk@lcs.poli.usp.br>) corr = (1.4+0.6*(at-20)/80)^(20/at); at = corr * at; ## size of window (rounded to next odd ## integer) N = (at - 8) / (2.285*bandwidth); M = fix(N/2); N = 2*M + 1; ## Kaiser window if (at>50) beta = 0.1102 * (at - 8.7); elseif (at>21) beta = 0.5842 * (at - 21)^0.4 + 0.07886 * (at - 21); else beta = 0; endif w = kaiser(N,beta); ## squared in freq. domain wsquared = conv(w,w); ## multiplied by ideal lowpass filter n = -(N-1):(N-1); hideal = 1/nb * sinc(n/nb); hcomp = wsquared .* hideal; ## extract square-root of response and ## compute minimum-phase version Ndft = 2^15; Hsqr = sqrt(abs(fft(hcomp,Ndft))); if (linear) h = real(ifft(Hsqr)); h = h(2:N); h = [fliplr(h) h(1) h]; else Hmin = Hsqr .* exp(-j*imag(hilbert(log(Hsqr)))); h = real(ifft(Hmin)); h = h(1:N); endif ## truncate and fix amplitude scale ## (H(0)=1) h = h / sum(h); endfunction ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/rceps.m���������������������������������������������������������������������������0000644�0000000�0000000�00000011317�14673270174�012212� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{y}, @var{ym}] =} rceps (@var{x}) ## Return the cepstrum of the signal @var{x}. ## ## If @var{x} is a matrix, return the cepstrum of each column. ## ## If called with two output arguments, the minimum phase reconstruction of ## the signal @var{x} is returned in @var{ym}. ## ## For example: ## ## @example ## @group ## f0 = 70; Fs = 10000; # 100 Hz fundamental, 10kHz sampling rate ## a = poly (0.985 * exp (1i * pi * [0.1, -0.1, 0.3, -0.3])); # two formants ## s = 0.005 * randn (1024, 1); # Noise excitation signal ## s(1:Fs/f0:length(s)) = 1; # Impulse glottal wave ## x = filter (1, a, s); # Speech signal ## [y, ym] = rceps (x .* hanning (1024)); ## @end group ## @end example ## ## Reference: @cite{Programs for Digital Signal Processing}, IEEE Press, ## John Wiley & Sons, New York, 1979. ## @end deftypefn function [y, ym] = rceps (x) if (nargin != 1) print_usage (); endif f = abs (fft (x)); if (any (f == 0)) error ("rceps: the spectrum of x contains zeros, unable to compute real cepstrum"); endif y = real (ifft (log (f))); if (nargout == 2) n = length (x); if (rows (x) == 1) if (rem (n,2) == 1) ym = [y(1), 2 * y(2:fix (n/2) + 1), zeros(1, fix (n/2))]; else ym = [y(1), 2 * y(2:n/2), y(n/2 + 1), zeros(1, n/2 - 1)]; endif else if (rem (n,2) == 1) ym = [y(1,:); 2 * y(2:fix (n/2) + 1,:); zeros(fix (n/2), columns (y))]; else ym = [y(1,:); 2 * y(2:n/2,:); y(n/2 + 1,:); zeros(n/2 - 1, columns (y))]; endif endif ym = real (ifft (exp (fft (ym)))); endif endfunction %!test %! ## accepts matrices %! x = randn (32, 3); %! [y, xm] = rceps (x); %! ## check the mag-phase response of the reproduction %! hx = fft (x); %! hxm = fft (xm); %! assert (abs (hx), abs (hxm), 200*eps); # good magnitude response match %! ## FIXME: test for minimum phase? Stop using random datasets! %! #assert (arg (hx) != arg (hxm)); # phase mismatch %!test %! ## accepts column and row vectors %! x = randn (256, 1); %! [y, xm] = rceps (x); %! [yt, xmt] = rceps (x.'); %! assert (yt.', y, 1e-14); %! assert (xmt.', xm, 1e-14); ## Test that an odd-length input produces an odd-length output %!test %! x = randn (33, 4); %! [y, xm] = rceps (x); %! assert (size (y), size (x)); %! assert (size (xm), size (x)); ## Test input validation %!error rceps %!error rceps (1, 2) %!error rceps (0) %!error rceps (zeros (10, 1)) %!demo %! f0 = 70; Fs = 10000; # 100 Hz fundamental, 10 kHz sampling rate %! a = real (poly (0.985 * exp (1i * pi * [0.1, -0.1, 0.3, -0.3]))); # two formants %! s = 0.05 * randn (1024, 1); # Noise excitation signal %! s(floor (1:Fs/f0:length (s))) = 1; # Impulse glottal wave %! x = filter (1, a, s); # Speech signal in x %! [y, xm] = rceps (x); # cepstrum and minimum phase x %! [hx, w] = freqz (x, 1, [], Fs); %! hxm = freqz (xm); %! figure (1); %! subplot (311); %! len = 1000 * fix (min (length (x), length (xm)) / 1000); %! plot ([0:len-1] * 1000 / Fs, x(1:len), "b;signal;", ... %! [0:len-1] * 1000 / Fs, xm(1:len), "g;reconstruction;"); %! ylabel ("Amplitude"); %! xlabel ("Time (ms)"); %! subplot (312); %! axis ("ticy"); %! plot (w, log (abs (hx)), ";magnitude;", ... %! w, log (abs (hxm)), ";reconstruction;"); %! xlabel ("Frequency (Hz)"); %! subplot (313); %! axis ("on"); %! plot (w, unwrap (arg (hx)) / (2 * pi), ";phase;", ... %! w, unwrap (arg (hxm)) / (2 * pi), ";reconstruction;"); %! xlabel ("Frequency (Hz)"); %! len = 1000 * fix (length (y) / 1000); %! figure (2); %! plot ([0:len-1] * 1000 / Fs, y(1:len), ";cepstrum;"); %! ylabel ("Amplitude"); %! xlabel ("Quefrency (ms)"); %! %------------------------------------------------------------- %! % confirm the magnitude spectrum is identical in the signal %! % and the reconstruction and that there are peaks in the %! % cepstrum at 14 ms intervals corresponding to an F0 of 70 Hz. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/rectpuls.m������������������������������������������������������������������������0000644�0000000�0000000�00000004633�14673270174�012742� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Paul Kienzle ## Copyright (C) 2018-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} rectpuls (@var{t}) ## @deftypefnx {Function File} {@var{y} =} rectpuls (@var{t}, @var{w}) ## Generate a rectangular pulse over the interval [-@var{w}/2,@var{w}/2), ## sampled at times @var{t}. This is useful with the function @code{pulstran} ## for generating a series of pulses. ## ## Example: ## @example ## @group ## fs = 11025; # arbitrary sample rate ## f0 = 100; # pulse train sample rate ## w = 0.3/f0; # pulse width 3/10th the distance between pulses ## plot (pulstran (0:1/fs:4/f0, 0:1/f0:4/f0, "rectpuls", w)); ## @end group ## @end example ## ## @seealso{gauspuls, pulstran, tripuls} ## @end deftypefn function y = rectpuls (t, w = 1) if (nargin < 1 || nargin > 2) print_usage (); endif if (! isreal (w) || ! isscalar (w)) error ("rectpuls: W must be a real scalar"); endif y = zeros (size (t)); idx = find ((t >= -w/2) & (t < w/2)); y(idx) = 1; endfunction %!demo %! fs = 11025; # arbitrary sample rate %! f0 = 100; # pulse train sample rate %! w = 0.3/f0; # pulse width 1/10th the distance between pulses %! x = pulstran (0:1/fs:4/f0, 0:1/f0:4/f0, "rectpuls", w); %! plot ([0:length(x)-1]*1000/fs, x); %! xlabel ("Time (ms)"); %! ylabel ("Amplitude"); %! title ("Rectangular pulse train of 3 ms pulses at 10 ms intervals"); %!assert (rectpuls ([]), []) %!assert (rectpuls ([], 0.1), []) %!assert (rectpuls (zeros (10, 1)), ones (10, 1)) %!assert (rectpuls (-1:1), [0, 1, 0]) %!assert (rectpuls (-5:5, 9), [0, ones(1,9), 0]) %!assert (rectpuls (0:1/100:0.3, 0.1), rectpuls ([0:1/100:0.3]', 0.1)') ## Test input validation %!error rectpuls () %!error rectpuls (1, 2, 3) %!error rectpuls (1, 2j) �����������������������������������������������������������������������������������������������������signal-1.4.6/inst/rectwin.m�������������������������������������������������������������������������0000644�0000000�0000000�00000002600�14673270174�012544� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} rectwin (@var{m}) ## Return the filter coefficients of a rectangular window of length @var{m}. ## @seealso{boxcar, hamming, hanning} ## @end deftypefn function w = rectwin (m) if (nargin != 1) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("rectwin: M must be a positive integer"); endif w = ones (m, 1); endfunction %!assert (rectwin (1), 1) %!assert (rectwin (2), ones (2, 1)) %!assert (rectwin (100), ones (100, 1)) %% Test input validation %!error rectwin () %!error rectwin (0.5) %!error rectwin (-1) %!error rectwin (ones (1, 4)) %!error rectwin (1, 2) ��������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/resample.m������������������������������������������������������������������������0000644�0000000�0000000�00000012365�14673270174�012712� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2008 Eric Chassande-Mottin, CNRS (France) <ecm@apc.univ-paris7.fr> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{y}, @var{h}] =} resample (@var{x}, @var{p}, @var{q}) ## @deftypefnx {Function File} {@var{y} =} resample (@var{x}, @var{p}, @var{q}, @var{h}) ## Change the sample rate of @var{x} by a factor of @var{p}/@var{q}. This is ## performed using a polyphase algorithm. The impulse response @var{h} of ## the antialiasing filter is either specified or either designed with a ## Kaiser-windowed sinecard. ## ## Ref [1] J. G. Proakis and D. G. Manolakis, ## Digital Signal Processing: Principles, Algorithms, and Applications, ## 4th ed., Prentice Hall, 2007. Chap. 6 ## ## Ref [2] A. V. Oppenheim, R. W. Schafer and J. R. Buck, ## Discrete-time signal processing, Signal processing series, ## Prentice-Hall, 1999 ## @end deftypefn function [y, h] = resample( x, p, q, h ) if nargchk(3,4,nargin) print_usage; elseif any([p q]<=0) || any([p q]~=floor([p q])), error("resample.m: p and q must be positive integers"); endif ## simplify decimation and interpolation factors great_common_divisor=gcd(p,q); if (great_common_divisor>1) p = double (p) / double (great_common_divisor); q = double (q) / double (great_common_divisor); else p = double (p); q = double (q); endif ## filter design if required if (nargin < 4) ## properties of the antialiasing filter log10_rejection = -3.0; stopband_cutoff_f = 1 / (2 * max (p, q)); roll_off_width = stopband_cutoff_f / 10.0; ## determine filter length ## use empirical formula from [2] Chap 7, Eq. (7.63) p 476 rejection_dB = -20.0*log10_rejection; L = ceil((rejection_dB-8.0) / (28.714 * roll_off_width)); ## ideal sinc filter t=(-L:L)'; ideal_filter=2*p*stopband_cutoff_f*sinc(2*stopband_cutoff_f*t); ## determine parameter of Kaiser window ## use empirical formula from [2] Chap 7, Eq. (7.62) p 474 if ((rejection_dB>=21) && (rejection_dB<=50)) beta = 0.5842 * (rejection_dB-21.0)^0.4 + 0.07886 * (rejection_dB-21.0); elseif (rejection_dB>50) beta = 0.1102 * (rejection_dB-8.7); else beta = 0.0; endif ## apodize ideal filter response h=kaiser(2*L+1,beta).*ideal_filter; endif ## check if input is a row vector isrowvector=false; if ((rows(x)==1) && (columns(x)>1)) x=x(:); isrowvector=true; endif ## check if filter is a vector if ~isvector(h) error("resample.m: the filter h should be a vector"); endif Lx = rows(x); Lh = length(h); L = ( Lh - 1 )/2.0; Ly = ceil(Lx*p/q); ## pre and postpad filter response nz_pre = floor(q-mod(L,q)); hpad = prepad(h,Lh+nz_pre); offset = floor((L+nz_pre)/q); nz_post = 0; while ceil( ( (Lx-1)*p + nz_pre + Lh + nz_post )/q ) - offset < Ly nz_post++; endwhile hpad = postpad(hpad,Lh + nz_pre + nz_post); ## filtering xfilt = upfirdn(x,hpad,p,q); y = xfilt(offset+1:offset+Ly,:); if isrowvector, y=y.'; endif endfunction %!test %! N=512; %! p=3; q=5; %! r=p/q; %! NN=ceil(r*N); %! t=0:N-1; %! tt=0:NN-1; %! err=zeros(N/2,1); %! for n = 0:N/2-1, %! phi0=2*pi*rand; %! f0=n/N; %! x=sin(2*pi*f0*t' + phi0); %! [y,h]=resample(x,p,q); %! xx=sin(2*pi*f0/r*tt' + phi0); %! t0=ceil((length(h)-1)/2/q); %! idx=t0+1:NN-t0; %! err(n+1)=max(abs(y(idx)-xx(idx))); %! endfor; %! rolloff=.1; %! rejection=10^-3; %! idx_inband=1:ceil((1-rolloff/2)*r*N/2)-1; %! assert(max(err(idx_inband))<rejection); %!test %! N=512; %! p=3; q=5; %! r=p/q; %! NN=ceil(r*N); %! t=0:N-1; %! tt=0:NN-1; %! reject=zeros(N/2,1); %! for n = 0:N/2-1, %! phi0=2*pi*rand; %! f0=n/N; %! x=sin(2*pi*f0*t' + phi0); %! [y,h]=resample(x,p,q); %! xx=sin(2*pi*f0/r*tt' + phi0); %! t0=ceil((length(h)-1)/2/q); %! idx=t0+1:NN-t0; %! reject(n+1)=max(abs(y(idx))); %! endfor; %! rolloff=.1; %! rejection=10^-3; %! idx_stopband=ceil((1+rolloff/2)*r*N/2)+1:N/2; %! assert(max(reject(idx_stopband))<=rejection); %!test %! N=1024; %! p=2; q=7; %! r=p/q; %! NN=ceil(r*N); %! t=0:N-1; %! tt=0:NN-1; %! err=zeros(N/2,1); %! for n = 0:N/2-1, %! phi0=2*pi*rand; %! f0=n/N; %! x=sin(2*pi*f0*t' + phi0); %! [y,h]=resample(x,p,q); %! xx=sin(2*pi*f0/r*tt' + phi0); %! t0=ceil((length(h)-1)/2/q); %! idx=t0+1:NN-t0; %! err(n+1)=max(abs(y(idx)-xx(idx))); %! endfor; %! rolloff=.1; %! rejection=10^-3; %! idx_inband=1:ceil((1-rolloff/2)*r*N/2)-1; %! assert(max(err(idx_inband))<rejection); %% Test integer-type arguments %!test %! N = 512; %! f = 0.1; %! x = sin (2*pi*f*[0:N-1]); %! y1 = resample (x, 3, 2); %! y2 = resample (x, uint8 (3), 2); %! assert (y1, y2); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/residued.m������������������������������������������������������������������������0000644�0000000�0000000�00000012367�14673270174�012710� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2005 Julius O. Smith III <jos@ccrma.stanford.edu> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{r}, @var{p}, @var{f}, @var{m}] =} residued (@var{b}, @var{a}) ## Compute the partial fraction expansion (PFE) of filter ## @math{H(z) = B(z)/A(z)}. In the usual PFE function @code{residuez}, the ## IIR part (poles @var{p} and residues @var{r}) is driven @emph{in parallel} ## with the FIR part (@var{f}). In this variant, the IIR part is driven by ## the @emph{output} of the FIR part. This structure can be more accurate in ## signal modeling applications. ## ## INPUTS: ## @var{b} and @var{a} are vectors specifying the digital filter ## @math{H(z) = B(z)/A(z)}. See @code{help filter} for documentation of the ## @var{b} and @var{a} filter coefficients. ## ## RETURNED: ## @itemize ## @item @var{r} = column vector containing the filter-pole residues ## @item @var{p} = column vector containing the filter poles ## @item @var{f} = row vector containing the FIR part, if any ## @item @var{m} = column vector of pole multiplicities ## @end itemize ## ## EXAMPLES: ## @example ## See @code{test residued verbose} to see a number of examples. ## @end example ## ## For the theory of operation, see ## @indicateurl{http://ccrma.stanford.edu/~jos/filters/residued.html} ## ## @seealso{residue, residued} ## @end deftypefn function [r, p, f, m] = residued(b, a, toler) ## RESIDUED - return residues, poles, and FIR part of B(z)/A(z) ## ## Let nb = length(b), na = length(a), and N=na-1 = no. of poles. ## If nb<na, then f will be empty, and the returned filter is ## ## r(1) r(N) ## H(z) = ---------------- + ... + ----------------- = R(z) ## [ 1-p(1)/z ]^e(1) [ 1-p(N)/z ]^e(N) ## ## This is the same result as returned by RESIDUEZ. ## Otherwise, the FIR part f will be nonempty, ## and the returned filter is ## ## H(z) = f(1) + f(2)/z + f(3)/z^2 + ... + f(nf)/z^M + R(z)/z^M ## ## where R(z) is the parallel one-pole filter bank defined above, ## and M is the order of F(z) = length(f)-1 = nb-na. ## ## Note, in particular, that the impulse-response of the parallel ## (complex) one-pole filter bank starts AFTER that of the the FIR part. ## In the result returned by RESIDUEZ, R(z) is not divided by z^M, ## so its impulse response starts at time 0 in parallel with f(n). ## ## J.O. Smith, 9/19/05 if nargin==3, warning("tolerance ignored"); endif NUM = b(:)'; DEN = a(:)'; nb = length(NUM); na = length(DEN); f = []; if na<=nb f = filter(NUM,DEN,[1,zeros(nb-na)]); NUM = NUM - conv(DEN,f); NUM = NUM(nb-na+2:end); endif [r,p,f2,m] = residuez(NUM,DEN); if f2, error('f2 not empty as expected'); endif endfunction %!test %! B=1; A=[1 -1]; %! [r,p,f,m] = residued(B,A); %! assert({r,p,f,m},{1,1,[],1},100*eps); %! [r2,p2,f2,m2] = residuez(B,A); %! assert({r,p,f,m},{r2,p2,f2,m2},100*eps); % residuez and residued should be identical when length(B)<length(A) %!test %! B=[1 -2 1]; A=[1 -1]; %! [r,p,f,m] = residued(B,A); %! assert({r,p,f,m},{0,1,[1 -1],1},100*eps); %!test %! B=[1 -2 1]; A=[1 -0.5]; %! [r,p,f,m] = residued(B,A); %! assert({r,p,f,m},{0.25,0.5,[1 -1.5],1},100*eps); %!test %! B=1; A=[1 -0.75 0.125]; %! [r,p,f,m] = residued(B,A); %! [r2,p2,f2,m2] = residuez(B,A); %! assert({r,p,f,m},{r2,p2,f2,m2},100*eps); % residuez and residued should be identical when length(B)<length(A) %!test %! B=1; A=[1 -2 1]; %! [r,p,f,m] = residued(B,A); %! [r2,p2,f2,m2] = residuez(B,A); %! assert({r,p,f,m},{r2,p2,f2,m2},100*eps); % residuez and residued should be identical when length(B)<length(A) %!test %! B=[6,2]; A=[1 -2 1]; %! [r,p,f,m] = residued(B,A); %! [r2,p2,f2,m2] = residuez(B,A); %! assert({r,p,f,m},{r2,p2,f2,m2},100*eps); % residuez and residued should be identical when length(B)<length(A) %!test %! B=[1 1 1]; A=[1 -2 1]; %! [r,p,f,m] = residued(B,A); %! assert(r,[0;3],1e-7); %! assert(p,[1;1],1e-8); %! assert(f,1,100*eps); %! assert(m,[1;2],100*eps); %!test %! B=[2 6 6 2]; A=[1 -2 1]; %! [r,p,f,m] = residued(B,A); %! assert(r,[8;16],3e-7); %! assert(p,[1;1],1e-8); %! assert(f,[2,10],100*eps); %! assert(m,[1;2],100*eps); %!test %! B=[1,6,2]; A=[1 -2 1]; %! [r,p,f,m] = residued(B,A); %! assert(r,[-1;9],3e-7); %! assert(p,[1;1],1e-8); %! assert(f,1,100*eps); %! assert(m,[1;2],100*eps); %!test %! B=[1 0 0 0 1]; A=[1 0 0 0 -1]; %! [r,p,f,m] = residued(B,A); %! [~,is] = sort(angle(p)); %! assert(r(is),[-1/2;-j/2;1/2;j/2],100*eps); %! assert(p(is),[-1;-j;1;j],100*eps); %! assert(f,1,100*eps); %! assert(m,[1;1;1;1],100*eps); % Verified in maxima: ratsimp(%I/2/(1-%I * d) - %I/2/(1+%I * d)); etc. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/residuez.m������������������������������������������������������������������������0000644�0000000�0000000�00000014553�14673270174�012735� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2005 Julius O. Smith III <jos@ccrma.stanford.edu> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{r}, @var{p}, @var{f}, @var{m}] =} residuez (@var{b}, @var{a}) ## Compute the partial fraction expansion of filter @math{H(z) = B(z)/A(z)}. ## ## INPUTS: ## @var{b} and @var{a} are vectors specifying the digital filter ## @math{H(z) = B(z)/A(z)}. See @code{help filter} for documentation of the ## @var{b} and @var{a} filter coefficients. ## ## RETURNED: ## @itemize ## @item @var{r} = column vector containing the filter-pole residues ## @item @var{p} = column vector containing the filter poles ## @item @var{f} = row vector containing the FIR part, if any ## @item @var{m} = column vector of pole multiplicities ## @end itemize ## ## EXAMPLES: ## @example ## See @code{test residuez verbose} to see a number of examples. ## @end example ## ## For the theory of operation, see ## @indicateurl{http://ccrma.stanford.edu/~jos/filters/residuez.html} ## ## @seealso{residue, residued} ## @end deftypefn function [r, p, f, m] = residuez(B, A, tol) ## RESIDUEZ - return residues, poles, and FIR part of B(z)/A(z) ## ## Let nb = length(b), na = length(a), and N=na-1 = no. of poles. ## If nb<na, then f will be empty, and the returned filter is ## ## r(1) r(N) ## H(z) = ---------------- + ... + ----------------- = R(z) ## [ 1-p(1)/z ]^m(1) [ 1-p(N)/z ]^m(N) ## ## If, on the other hand, nb >= na, the FIR part f will not be empty. ## Let M = nb-na+1 = order of f = length(f)-1). Then the returned filter is ## ## H(z) = f(1) + f(2)/z + f(3)/z^2 + ... + f(M+1)/z^M + R(z) ## ## where R(z) is the parallel one-pole filter bank defined above. ## Note, in particular, that the impulse-response of the one-pole ## filter bank is in parallel with that of the the FIR part. This can ## be wasteful when matching the initial impulse response is important, ## since F(z) can already match the first N terms of the impulse ## response. To obtain a decomposition in which the impulse response of ## the IIR part R(z) starts after that of the FIR part F(z), use RESIDUED. ## ## J.O. Smith, 9/19/05 if nargin==3 warning("tolerance ignored"); endif NUM = B(:)'; DEN = A(:)'; ## Matlab's residue does not return m (since it is implied by p): [r,p,f,m]=residue(conj(fliplr(NUM)),conj(fliplr(DEN))); p = 1 ./ p; r = r .* ((-p) .^m); f = fliplr(f); endfunction %!test %! B=[1 -2 1]; A=[1 -1]; %! [r,p,f,m] = residuez(B,A); %! assert(r,0,100*eps); %! assert(p,1,100*eps); %! assert(f,[1 -1],100*eps); %! assert(m,1,100*eps); %!test %! B=1; A=[1 -1j]; %! [r,p,f,m] = residuez(B,A); %! assert(r,1,100*eps); %! assert(p,1j,100*eps); %! assert(f,[],100*eps); %! assert(m,1,100*eps); %!test %! B=1; A=[1 -1 .25]; %! [r,p,f,m] = residuez(B,A); %! [rs,is] = sort(r); %! assert(rs,[0;1],1e-7); %! assert(p(is),[0.5;0.5],1e-8); %! assert(f,[],100*eps); %! assert(m(is),[1;2],100*eps); %!test %! B=1; A=[1 -0.75 .125]; %! [r,p,f,m] = residuez(B,A); %! [rs,is] = sort(r); %! assert(rs,[-1;2],100*eps); %! assert(p(is),[0.25;0.5],100*eps); %! assert(f,[],100*eps); %! assert(m(is),[1;1],100*eps); %!test %! B=[1,6,2]; A=[1,-2,1]; %! [r,p,f,m] = residuez(B,A); %! [rs,is] = sort(r); %! assert(rs,[-10;9],1e-7); %! assert(p(is),[1;1],1e-8); %! assert(f,[2],100*eps); %! assert(m(is),[1;2],100*eps); %!test %! B=[6,2]; A=[1,-2,1]; %! [r,p,f,m] = residuez(B,A); %! [rs,is] = sort(r); %! assert(rs,[-2;8],1e-7); %! assert(p(is),[1;1],1e-8); %! assert(f,[],100*eps); %! assert(m(is),[1;2],100*eps); %!test %! B=[1,6,6,2]; A=[1,-2,1]; %! [r,p,f,m] = residuez(B,A); %! [rs,is] = sort(r); %! assert(rs,[-24;15],2e-7); %! assert(p(is),[1;1],1e-8); %! assert(f,[10,2],100*eps); %! assert(m(is),[1;2],100*eps); %!test %! B=[1,6,6,2]; A=[1,-(2+j),(1+2j),-j]; %! [r,p,f,m] = residuez(B,A); %! [rs,is] = sort(r); %! assert(rs,[-2+2.5j;7.5+7.5j;-4.5-12j],1E-6); %! assert(p(is),[1j;1;1],1E-6); %! assert(f,2j,1E-6); %! assert(m(is),[1;2;1],1E-6); %!test %! B=[1,0,1]; A=[1,0,0,0,0,-1]; %! [r,p,f,m] = residuez(B,A); %! [as,is] = sort(angle(p)); %! rise = [ ... %! 0.26180339887499 - 0.19021130325903i; ... %! 0.03819660112501 + 0.11755705045849i; ... %! 0.4; ... %! 0.03819660112501 - 0.11755705045849i; ... %! 0.26180339887499 + 0.19021130325903i;]; %! pise = [ ... %! -0.80901699437495 - 0.58778525229247i; ... %! 0.30901699437495 - 0.95105651629515i; ... %! 1; ... %! 0.30901699437495 + 0.95105651629515i; ... %! -0.80901699437495 + 0.58778525229247i]; %! assert(r(is),rise,100*eps); %! assert(p(is),pise,100*eps); %! assert(f,[],100*eps); %! assert(m,[1;1;1;1;1],100*eps); %!test # bug 57359 %! [r,p,k] = residuez([1 1 1.5 .5],[1 1.5 .5]); %! [rs,is] = sort(r); %! assert(r(is), [-1; 2], 100*eps); %! assert(p(is), [-0.5; -1], 100*eps); %! assert(k, [0 1], 100*eps); %!test %! # matlab example %! b0 = 0.05634; %! b1 = [1 1]; %! b2 = [1 -1.0166 1]; %! a1 = [1 -0.683]; %! a2 = [1 -1.4461 0.7957]; %! %! b = b0*conv(b1,b2); %! a = conv(a1,a2); %! %! [r,p,k] = residuez(b,a); %! expected_r = [ ... %! -0.115252473987042 - 0.018151109860883i; ... %! -0.115252473987042 + 0.018151109860883i; ... %! 0.390513439910336 - 0.000000000000000i; ... %! ]; %! expected_p = [ ... %! 0.723050000000000 + 0.522397068808775i; ... %! 0.723050000000000 - 0.522397068808775i; ... %! 0.683000000000000 + 0.000000000000000i; ... %! ]; %! expected_k = -0.103668491936251; %! %! # sort doesnt use i in the sort, so order of real is only thing can count on %! [rs,is] = sort(r); %! assert(real(r(is)), real(expected_r), 1e-5); %! assert(abs(imag(r(is))), abs(imag(expected_r)), 1e-5); %! assert(real(p(is)), real(expected_p), 1e-5); %! assert(abs(imag(p(is))), abs(imag(expected_p)), 1e-5); %! assert(k, expected_k, 100*eps); �����������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/rms.m�����������������������������������������������������������������������������0000644�0000000�0000000�00000003442�14673270174�011677� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2015 Andreas Weber <octave@tech-chat.de> ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} rms (@var{x}) ## @deftypefnx {Function File} {@var{y} =} rms (@var{x}, @var{dim}) ## Compute the root-mean-square (RMS) of the vector @var{x}. ## ## The root-mean-square is defined as ## ## @tex ## $$ {\rm rms}(x) = {\sqrt{\sum_{i=1}^N {x_i}^2 \over N}} $$ ## @end tex ## @ifnottex ## ## @example ## rms (@var{x}) = SQRT (1/N SUM_i @var{x}(i)^2) ## @end example ## ## @end ifnottex ## If @var{x} is a matrix, compute the root-mean-square for each column and ## return them in a row vector. ## ## If the optional argument @var{dim} is given, operate along this dimension. ## @seealso{mean, meansq, peak2rms, rssq, sumsq} ## @end deftypefn function y = rms (varargin) if (nargin < 1 || nargin > 2) print_usage (); endif y = sqrt (meansq (varargin{:})); endfunction %!assert (rms (0), 0) %!assert (rms (1), 1) %!assert (rms ([1 2 -1]), sqrt (2)) %!assert (rms ([1 2 -1]'), sqrt (2)) %!assert (rms ([1 2], 3), [1 2]) ## Test input validation %!error rms () %!error rms (1, 2, 3) %!error rms (1, 1.5) %!error rms (1, -1) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/rssq.m����������������������������������������������������������������������������0000644�0000000�0000000�00000003370�14673270174�012066� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2018-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} rssq (@var{x}) ## @deftypefnx {Function File} {@var{y} =} rssq (@var{x}, @var{dim}) ## Compute the root-sum-of-squares (RSS) of the vector @var{x}. ## ## The root-sum-of-squares is defined as ## ## @tex ## $$ {\rm rssq}(x) = {\sqrt{\sum_{i=1}^N {x_i}^2}} $$ ## @end tex ## @ifnottex ## ## @example ## rssq (@var{x}) = SQRT (SUM_i @var{x}(i)^2) ## @end example ## ## @end ifnottex ## If @var{x} is a matrix, compute the root-sum-of-squares for each column and ## return them in a row vector. ## ## If the optional argument @var{dim} is given, operate along this dimension. ## @seealso{mean, meansq, sumsq, rms} ## @end deftypefn function y = rssq (varargin) if (nargin < 1 || nargin > 2) print_usage (); endif y = sqrt (sumsq (varargin{:})); endfunction %!assert (rssq ([]), 0) %!assert (rssq ([1 2 -1]), sqrt (6)) %!assert (rssq ([1 2 -1]'), sqrt (6)) %!assert (rssq ([1 2], 3), [1 2]) ## Test input validation %!error rssq () %!error rssq (1, 2, 3) %!error rssq (1, 1.5) %!error rssq (1, -1) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/sampled2continuous.m��������������������������������������������������������������0000644�0000000�0000000�00000002712�14673270174�014733� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2009 Muthiah Annamalai <muthiah.annamalai@uta.edu> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{xt} =} sampled2continuous (@var{xn}, @var{T}, @var{t}) ## ## Calculate the x(t) reconstructed ## from samples x[n] sampled at a rate 1/T samples ## per unit time. ## ## t is all the instants of time when you need x(t) ## from x[n]; this time is relative to x[0] and not ## an absolute time. ## ## This function can be used to calculate sampling rate ## effects on aliasing, actual signal reconstruction ## from discrete samples. ## @end deftypefn function xt = sampled2continuous( xn , T, t ) if ( nargin < 3 ) print_usage() endif N = length( xn ); xn = reshape( xn, N, 1 ); [TT,tt]= meshgrid(T*(0:N-1)',t); S = sinc((tt -TT)./T); xt = S*xn; return endfunction ������������������������������������������������������signal-1.4.6/inst/sawtooth.m������������������������������������������������������������������������0000644�0000000�0000000�00000004012�14673270174�012740� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Juan Aguado ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} sawtooth (@var{t}) ## @deftypefnx {Function File} {@var{y} =} sawtooth (@var{t}, @var{width}) ## Generates a sawtooth wave of period @code{2 * pi} with limits @code{+1/-1} ## for the elements of @var{t}. ## ## @var{width} is a real number between @code{0} and @code{1} which specifies ## the point between @code{0} and @code{2 * pi} where the maximum is. The ## function increases linearly from @code{-1} to @code{1} in @code{[0, 2 * ## pi * @var{width}]} interval, and decreases linearly from @code{1} to ## @code{-1} in the interval @code{[2 * pi * @var{width}, 2 * pi]}. ## ## If @var{width} is 0.5, the function generates a standard triangular wave. ## ## If @var{width} is not specified, it takes a value of 1, which is a standard ## sawtooth function. ## @end deftypefn function y = sawtooth (t,width) if (nargin < 1 || nargin > 2) print_usage (); endif if (nargin == 1) width = 1; else if (width < 0 || width > 1 || ! isreal (width)) error ("width must be a real number between 0 and 1."); endif endif t = mod (t / (2 * pi), 1); y = zeros (size (t)); if (width != 0) y (t < width) = 2 * t (t < width) / width - 1; endif if (width != 1) y( t >= width) = -2 * (t (t >= width) - width) / (1 - width) + 1; endif endfunction ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/schtrig.m�������������������������������������������������������������������������0000644�0000000�0000000�00000010070�14673270174�012534� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2012 Juan Pablo Carbajal <carbajal@ifi.uzh.ch> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {@var{v} =} schtrig (@var{x},@var{lvl},@var{rst}=1) ## @deftypefnx {[@var{v},@var{rng}] =} schtrig (@dots{}) ## Implements a multisignal Schmitt trigger with levels @var{lvl}. ## ## The triger works along the first dimension of the 2-dimensional array @var{x}. ## It compares each column in @var{x} to the levels in @var{lvl}, when the ## value is higher @code{max (@var{lvl})} the output @var{v} is high (i.e. 1); when the ## value is below @code{min (@var{lvl})} the output is low (i.e. 0); and when ## the value is between the two levels the output retains its value. ## ## The threshold levels are passed in the array @var{lvl}. If this is a scalar, ## the thresholds are symmetric around 0, i.e. @code{[-lvl lvl]}. ## ## The second output argument stores the ranges in which the output is high, so ## the indexes @var{rng(1,i):rng(2,i)} point to the i-th segment of 1s in @var{v}. ## See @code{clustersegment} for a detailed explanation. ## ## The function conserves the state of the trigger across calls (persistent variable). ## If the reset flag is active, i.e. @code{@var{rst}== true}, then the state of ## the trigger for all signals is set to the low state (i.e. 0). ## ## Example: ## @example ## x = [0 0.5 1 1.5 2 1.5 1.5 1.2 1 0 0].'; ## y = schtrig (x, [1.3 1.6]); ## disp ([x y]); ## 0.0 0 ## 0.5 0 ## 1.0 0 ## 1.5 0 ## 2.0 1 ## 1.5 1 ## 1.5 1 ## 1.2 0 ## 1.0 0 ## 0.0 0 ## 0.0 0 ## @end example ## ## Run @code{demo schtrig} to see further examples. ## ## @seealso{clustersegment} ## @end deftypefn function [v rg] = schtrig (x, lvl, rst = true) if (length (ndims (x)) > 2) error ('Octave:invalid-input-arg', 'The input should be two dimensional.'); endif if (length (ndims (lvl)) > 2) error ('Octave:invalid-input-arg', 'Only a maximum of two threshold levels accepted.'); endif [nT nc] = size (x); persistent st0; if (rst || isempty (st0)) st0 = zeros (1,nc); endif if (length(lvl) == 1) lvl = abs (lvl) .* [1 -1]; else lvl = sort (lvl,'descend'); endif v = NA (nT, nc); v(1,:) = st0; ## Signal is above up level up = x > lvl(1); v(up) = 1; ## Signal is below down level dw = x < lvl(2); v(dw) = 0; ## Resolve intermediate states ## Find data between the levels idx = isnan (v); ranges = clustersegment (idx'); if (nc == 1) ranges = {ranges}; endif for i=1:nc ## Record the state at the beginning of the interval between levels if (!isempty (ranges{i})) prev = ranges{i}(1,:)-1; prev(prev<1) = 1; st0 = v(prev,i); ## Copy the initial state to the interval ini_idx = ranges{i}(1,:); end_idx = ranges{i}(2,:); for j =1:length(ini_idx) v(ini_idx(j):end_idx(j),i) = st0(j); endfor endif endfor st0 = v(end,:); endfunction %!demo %! t = linspace(0,1,100)'; %! x = sin (2*pi*2*t) + sin (2*pi*5*t).*[0.8 0.3]; %! %! lvl = [0.8 0.25]'; %! v = schtrig (x,lvl); %! %! subplot(2,1,1) %! h = plot (t, x(:,1), t, v(:,1)); %! set (h, 'linewidth',2); %! line([0; 1],lvl([1; 1]),'color','g'); %! line([0;1],lvl([2;2]),'color','k') %! axis tight %! %! subplot(2,1,2) %! h = plot (t, x(:,2), t, v(:,2)); %! set (h,'linewidth',2); %! line([0; 1],lvl([1; 1]),'color','g'); %! line([0;1],lvl([2;2]),'color','k') %! axis tight # TODO add tests ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/sftrans.m�������������������������������������������������������������������������0000644�0000000�0000000�00000017274�14673270174�012566� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999-2001 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{Sz}, @var{Sp}, @var{Sg}] =} sftrans (@var{Sz}, @var{Sp}, @var{Sg}, @var{W}, @var{stop}) ## ## Transform band edges of a generic lowpass filter (cutoff at W=1) ## represented in splane zero-pole-gain form. W is the edge of the ## target filter (or edges if band pass or band stop). Stop is true for ## high pass and band stop filters or false for low pass and band pass ## filters. Filter edges are specified in radians, from 0 to pi (the ## nyquist frequency). ## ## Theory: Given a low pass filter represented by poles and zeros in the ## splane, you can convert it to a low pass, high pass, band pass or ## band stop by transforming each of the poles and zeros individually. ## The following table summarizes the transformation: ## ## @example ## Transform Zero at x Pole at x ## ---------------- ------------------------- ------------------------ ## Low Pass zero: Fc x/C pole: Fc x/C ## S -> C S/Fc gain: C/Fc gain: Fc/C ## ---------------- ------------------------- ------------------------ ## High Pass zero: Fc C/x pole: Fc C/x ## S -> C Fc/S pole: 0 zero: 0 ## gain: -x gain: -1/x ## ---------------- ------------------------- ------------------------ ## Band Pass zero: b +- sqrt(b^2-FhFl) pole: b +- sqrt(b^2-FhFl) ## S^2+FhFl pole: 0 zero: 0 ## S -> C -------- gain: C/(Fh-Fl) gain: (Fh-Fl)/C ## S(Fh-Fl) b=x/C (Fh-Fl)/2 b=x/C (Fh-Fl)/2 ## ---------------- ------------------------- ------------------------ ## Band Stop zero: b +- sqrt(b^2-FhFl) pole: b +- sqrt(b^2-FhFl) ## S(Fh-Fl) pole: +-sqrt(-FhFl) zero: +-sqrt(-FhFl) ## S -> C -------- gain: -x gain: -1/x ## S^2+FhFl b=C/x (Fh-Fl)/2 b=C/x (Fh-Fl)/2 ## ---------------- ------------------------- ------------------------ ## Bilinear zero: (2+xT)/(2-xT) pole: (2+xT)/(2-xT) ## 2 z-1 pole: -1 zero: -1 ## S -> - --- gain: (2-xT)/T gain: (2-xT)/T ## T z+1 ## ---------------- ------------------------- ------------------------ ## @end example ## ## where C is the cutoff frequency of the initial lowpass filter, Fc is ## the edge of the target low/high pass filter and [Fl,Fh] are the edges ## of the target band pass/stop filter. With abundant tedious algebra, ## you can derive the above formulae yourself by substituting the ## transform for S into H(S)=S-x for a zero at x or H(S)=1/(S-x) for a ## pole at x, and converting the result into the form: ## ## @example ## H(S)=g prod(S-Xi)/prod(S-Xj) ## @end example ## ## The transforms are from the references. The actual pole-zero-gain ## changes I derived myself. ## ## Please note that a pole and a zero at the same place exactly cancel. ## This is significant for High Pass, Band Pass and Band Stop filters ## which create numerous extra poles and zeros, most of which cancel. ## Those which do not cancel have a "fill-in" effect, extending the ## shorter of the sets to have the same number of as the longer of the ## sets of poles and zeros (or at least split the difference in the case ## of the band pass filter). There may be other opportunistic ## cancellations but I will not check for them. ## ## Also note that any pole on the unit circle or beyond will result in ## an unstable filter. Because of cancellation, this will only happen ## if the number of poles is smaller than the number of zeros and the ## filter is high pass or band pass. The analytic design methods all ## yield more poles than zeros, so this will not be a problem. ## ## References: ## ## Proakis & Manolakis (1992). Digital Signal Processing. New York: ## Macmillan Publishing Company. ## @end deftypefn function [Sz, Sp, Sg] = sftrans(Sz, Sp, Sg, W, stop) if (nargin != 5) print_usage; endif C = 1; p = length(Sp); z = length(Sz); if z > p || p == 0 error("sftrans: must have at least as many poles as zeros in s-plane"); endif if length(W)==2 Fl = W(1); Fh = W(2); if stop ## ---------------- ------------------------- ------------------------ ## Band Stop zero: b ± sqrt(b^2-FhFl) pole: b ± sqrt(b^2-FhFl) ## S(Fh-Fl) pole: ±sqrt(-FhFl) zero: ±sqrt(-FhFl) ## S -> C -------- gain: -x gain: -1/x ## S^2+FhFl b=C/x (Fh-Fl)/2 b=C/x (Fh-Fl)/2 ## ---------------- ------------------------- ------------------------ if (isempty(Sz)) Sg = Sg * real (1./ prod(-Sp)); elseif (isempty(Sp)) Sg = Sg * real(prod(-Sz)); else Sg = Sg * real(prod(-Sz)/prod(-Sp)); endif b = (C*(Fh-Fl)/2)./Sp; Sp = [b+sqrt(b.^2-Fh*Fl), b-sqrt(b.^2-Fh*Fl)]; extend = [sqrt(-Fh*Fl), -sqrt(-Fh*Fl)]; if isempty(Sz) Sz = [extend(1+rem([1:2*p],2))]; else b = (C*(Fh-Fl)/2)./Sz; Sz = [b+sqrt(b.^2-Fh*Fl), b-sqrt(b.^2-Fh*Fl)]; if (p > z) Sz = [Sz, extend(1+rem([1:2*(p-z)],2))]; endif endif else ## ---------------- ------------------------- ------------------------ ## Band Pass zero: b ± sqrt(b^2-FhFl) pole: b ± sqrt(b^2-FhFl) ## S^2+FhFl pole: 0 zero: 0 ## S -> C -------- gain: C/(Fh-Fl) gain: (Fh-Fl)/C ## S(Fh-Fl) b=x/C (Fh-Fl)/2 b=x/C (Fh-Fl)/2 ## ---------------- ------------------------- ------------------------ Sg = Sg * (C/(Fh-Fl))^(z-p); b = Sp*((Fh-Fl)/(2*C)); Sp = [b+sqrt(b.^2-Fh*Fl), b-sqrt(b.^2-Fh*Fl)]; if isempty(Sz) Sz = zeros(1,p); else b = Sz*((Fh-Fl)/(2*C)); Sz = [b+sqrt(b.^2-Fh*Fl), b-sqrt(b.^2-Fh*Fl)]; if (p>z) Sz = [Sz, zeros(1, (p-z))]; endif endif endif else Fc = W; if stop ## ---------------- ------------------------- ------------------------ ## High Pass zero: Fc C/x pole: Fc C/x ## S -> C Fc/S pole: 0 zero: 0 ## gain: -x gain: -1/x ## ---------------- ------------------------- ------------------------ if (isempty(Sz)) Sg = Sg * real (1./ prod(-Sp)); elseif (isempty(Sp)) Sg = Sg * real(prod(-Sz)); else Sg = Sg * real(prod(-Sz)/prod(-Sp)); endif Sp = C * Fc ./ Sp; if isempty(Sz) Sz = zeros(1,p); else Sz = [C * Fc ./ Sz]; if (p > z) Sz = [Sz, zeros(1,p-z)]; endif endif else ## ---------------- ------------------------- ------------------------ ## Low Pass zero: Fc x/C pole: Fc x/C ## S -> C S/Fc gain: C/Fc gain: Fc/C ## ---------------- ------------------------- ------------------------ Sg = Sg * (C/Fc)^(z-p); Sp = Fc * Sp / C; Sz = Fc * Sz / C; endif endif endfunction ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/sgolay.m��������������������������������������������������������������������������0000644�0000000�0000000�00000010426�14673270174�012374� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2004 Pascal Dupuis <Pascal.Dupuis@esat.kuleuven.ac.be> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{f} =} sgolay (@var{p}, @var{n}) ## @deftypefnx {Function File} {@var{f} =} sgolay (@var{p}, @var{n}, @var{m}) ## @deftypefnx {Function File} {@var{f} =} sgolay (@var{p}, @var{n}, @var{m}, @var{ts}) ## Computes the filter coefficients for all Savitzsky-Golay smoothing ## filters of order p for length n (odd). m can be used in order to ## get directly the mth derivative. In this case, ts is a scaling factor. ## ## The early rows of F smooth based on future values and later rows ## smooth based on past values, with the middle row using half future ## and half past. In particular, you can use row i to estimate x(k) ## based on the i-1 preceding values and the n-i following values of x ## values as y(k) = F(i,:) * x(k-i+1:k+n-i). ## ## Normally, you would apply the first (n-1)/2 rows to the first k ## points of the vector, the last k rows to the last k points of the ## vector and middle row to the remainder, but for example if you were ## running on a realtime system where you wanted to smooth based on the ## all the data collected up to the current time, with a lag of five ## samples, you could apply just the filter on row n-5 to your window ## of length n each time you added a new sample. ## ## Reference: Numerical recipes in C. p 650 ## ## @seealso{sgolayfilt} ## @end deftypefn ## Based on smooth.m by E. Farhi <manuf@ldv.univ-montp2.fr> function F = sgolay (p, n, m = 0, ts = 1) if (nargin < 2 || nargin > 4) print_usage; elseif rem(n,2) != 1 error ("sgolay needs an odd filter length n"); elseif p >= n error ("sgolay needs filter length n larger than polynomial order p"); else if length(m) > 1, error("weight vector unimplemented"); endif ## Construct a set of filters from complete causal to completely ## noncausal, one filter per row. For the bulk of your data you ## will use the central filter, but towards the ends you will need ## a filter that doesn't go beyond the end points. F = zeros (n, n); k = floor (n/2); for row = 1:k+1 ## Construct a matrix of weights Cij = xi ^ j. The points xi are ## equally spaced on the unit grid, with past points using negative ## values and future points using positive values. C = ( [(1:n)-row]'*ones(1,p+1) ) .^ ( ones(n,1)*[0:p] ); ## A = pseudo-inverse (C), so C*A = I; this is constructed from the SVD A = pinv(C); ## Take the row of the matrix corresponding to the derivative ## you want to compute. F(row,:) = A(1+m,:); endfor ## The filters shifted to the right are symmetric with those to the left. F(k+2:n,:) = (-1)^m*F(k:-1:1,n:-1:1); endif F = F * ( prod(1:m) / (ts^m) ); endfunction %!test %! N=2^12; %! t=[0:N-1]'/N; %! dt=t(2)-t(1); %! w = 2*pi*50; %! offset = 0.5; # 50 Hz carrier %! # exponential modulation and its derivatives %! d = 1+exp(-3*(t-offset)); %! dd = -3*exp(-3*(t-offset)); %! d2d = 9*exp(-3*(t-offset)); %! d3d = -27*exp(-3*(t-offset)); %! # modulated carrier and its derivatives %! x = d.*sin(w*t); %! dx = dd.*sin(w*t) + w*d.*cos(w*t); %! d2x = (d2d-w^2*d).*sin(w*t) + 2*w*dd.*cos(w*t); %! d3x = (d3d-3*w^2*dd).*sin(w*t) + (3*w*d2d-w^3*d).*cos(w*t); %! %! y = sgolayfilt(x,sgolay(8,41,0,dt)); %! assert(norm(y-x)/norm(x),0,5e-6); %! %! y = sgolayfilt(x,sgolay(8,41,1,dt)); %! assert(norm(y-dx)/norm(dx),0,5e-6); %! %! y = sgolayfilt(x,sgolay(8,41,2,dt)); %! assert(norm(y-d2x)/norm(d2x),0,1e-5); %! %! y = sgolayfilt(x,sgolay(8,41,3,dt)); %! assert(norm(y-d3x)/norm(d3x),0,1e-4); ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/sgolayfilt.m����������������������������������������������������������������������0000644�0000000�0000000�00000011613�14673270174�013252� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2004 Pascal Dupuis <Pascal.Dupuis@esat.kuleuven.ac.be> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} sgolayfilt (@var{x}) ## @deftypefnx {Function File} {@var{y} =} sgolayfilt (@var{x}, @var{p}) ## @deftypefnx {Function File} {@var{y} =} sgolayfilt (@var{x}, @var{p}, @var{n}) ## @deftypefnx {Function File} {@var{y} =} sgolayfilt (@var{x}, @var{p}, @var{n}, @var{m}) ## @deftypefnx {Function File} {@var{y} =} sgolayfilt (@var{x}, @var{p}, @var{n}, @var{m}, @var{ts}) ## @deftypefnx {Function File} {@var{y} =} sgolayfilt (@var{x}, @var{p}, @var{n}, @var{m}, @var{ts}) ## @deftypefnx {Function File} {@var{y} =} sgolayfilt (@var{x}, @var{f}) ## Smooth the data in x with a Savitsky-Golay smoothing filter of ## polynomial order p and length n, n odd, n > p. By default, p=3 ## and n=p+2 or n=p+3 if p is even. ## ## If @var{f} is given as a matrix, it is expected to be a filter as ## computed by @code{sgolay}. ## ## These filters are particularly good at preserving lineshape while ## removing high frequency squiggles. Particularly, compare a 5 sample ## averager, an order 5 butterworth lowpass filter (cutoff 1/3) and ## sgolayfilt(x, 3, 5), the best cubic estimated from 5 points: ## ## @example ## @group ## [b, a] = butter (5, 1/3); ## x = [zeros(1,15), 10*ones(1,10), zeros(1,15)]; ## plot (sgolayfilt (x), "r;sgolayfilt;", ... ## filtfilt (ones (1,5)/5, 1, x), "g;5 sample average;", ... ## filtfilt (b, a, x), "c;order 5 butterworth;", ... ## x, "+b;original data;"); ## @end group ## @end example ## ## @seealso{sgolay} ## @end deftypefn ## FIXME: Patch filter.cc so that it accepts matrix arguments function y = sgolayfilt (x, p = 3, n, m = 0, ts = 1) if nargin < 1 || nargin > 5 print_usage; endif if (nargin >= 3) F = sgolay(p, n, m, ts); elseif (prod(size(p)) == 1) n = p+3-rem(p,2); F = sgolay(p, n); else F = p; n = size(F,1); if (size(F,1) != size(F,2)) error("sgolayfilt(x,F): F is not a Savitzsky-Golay filter set"); endif endif transpose = (size(x,1) == 1); if (transpose) x = x.'; endif; len = size(x,1); if (len < n) error("sgolayfilt: insufficient data for filter"); endif ## The first k rows of F are used to filter the first k points ## of the data set based on the first n points of the data set. ## The last k rows of F are used to filter the last k points ## of the data set based on the last n points of the dataset. ## The remaining data is filtered using the central row of F. ## As the filter coefficients are used in the reverse order of what ## seems the logical notation, reverse F(k+1, :) so that antisymmetric ## sequences are used with the right sign. k = floor(n/2); z = filter(F(k+1,n:-1:1), 1, x); y = [ F(1:k,:)*x(1:n,:) ; z(n:len,:) ; F(k+2:n,:)*x(len-n+1:len,:) ]; if (transpose) y = y.'; endif endfunction %!demo %! [b, a] = butter(5,1/3); %! x=[zeros(1,15), 10*ones(1,10), zeros(1,15)]; %! subplot(121); %! plot(sgolayfilt(x),"r;sgolay(3,5);",... %! filtfilt(ones(1,5)/5,1,x),"g;5 sample average;",... %! filtfilt(b,a,x),"c;order 5 butterworth;",... %! x,"+b;original data;"); %! axis([1 40 -2 15]); %! title("boxcar"); %! %! x=x+randn(size(x))/2; %! subplot(122); %! plot(sgolayfilt(x,3,5),"r;sgolay(3,5);",... %! filtfilt(ones(1,5)/5,1,x),"g;5 sample average;",... %! filtfilt(b,a,x),"c;order 5 butterworth;",... %! x,"+b;original data;"); %! axis([1 40 -2 15]); %! title("boxcar+noise"); %!demo %! [b, a] = butter(5,1/3); %! t = 0:0.01:1.0; % 1 second sample %! x=cos(2*pi*t*3); % 3 Hz sinusoid %! subplot(121); %! plot(t,sgolayfilt(x,3,5),"r;sgolay(3,5);",... %! t,filtfilt(ones(1,5)/5,1,x),"g;5 sample average;",... %! t,filtfilt(b,a,x),"c;order 5 butterworth;",... %! t,x,"+b;original data;"); %! axis([0 1 -1.5 2.5]); %! title("sinusoid"); %! %! x=x+0.2*randn(size(x)); % signal+noise %! subplot(122); %! plot(t,sgolayfilt(x',3,5),"r;sgolay(3,5);",... %! t,filtfilt(ones(1,5)/5,1,x),"g;5 sample average;",... %! t,filtfilt(b,a,x),"c;order 5 butterworth;",... %! t,x,"+b;original data;"); %! axis([0 1 -1.5 2.5]); %! title("sinusoid+noise"); ���������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/shanwavf.m������������������������������������������������������������������������0000644�0000000�0000000�00000002407�14673270174�012713� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{psi}, @var{x}] =} shanwavf (@var{lb}, @var{ub}, @var{n}, @var{fb}, @var{fc}) ## Compute the Complex Shannon wavelet. ## @end deftypefn function [psi,x] = shanwavf (lb,ub,n,fb,fc) if (nargin < 5) print_usage; elseif (n <= 0 || floor(n) ~= n) error("n must be an integer strictly positive"); elseif (fc <= 0 || fb <= 0) error("fc and fb must be strictly positive"); endif x = linspace(lb,ub,n); psi = (fb.^0.5).*(sinc(fb.*x).*exp(2.*i.*pi.*fc.*x)); endfunction ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/shiftdata.m�����������������������������������������������������������������������0000644�0000000�0000000�00000004570�14673270174�013050� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2014 Georgios Ouzounis <ouzounis_georgios@hotmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{out perm shifts}] =} shiftdata (@var{in}) ## @deftypefnx {Function File} {[@var{out perm shifts}] =} shiftdata (@var{in}, @var{dim}) ## Shift data @var{in} to permute the dimension @var{dim} to the first column. ## @seealso{unshiftdata} ## @end deftypefn function [out, perm, shifts] = shiftdata (in, dim) if (nargin < 1 || nargin > 2) print_usage (); elseif (nargin == 1 || (nargin == 2 && isempty (dim))) idx = find (size (in) - 1); dim = idx(1); shiftsflag = true; else shiftsflag = false; endif if (dim != fix (dim)) error ("shiftdata: DIM must be an integer"); endif perm = [dim 1: (dim - 1) (dim + 1): (length (size (in)))]; out = permute (in, perm); if (shiftsflag == true) perm = []; shifts = dim - 1; else shifts = []; endif endfunction %!test %! X = [1 2 3; 4 5 6; 7 8 9]; %! [Y, perm, shifts] = shiftdata (X, 2); %! assert (Y, [1 4 7; 2 5 8; 3 6 9]); %! assert (perm, [2 1]); %!test %! X = [27 42 11; 63 48 5; 67 74 93]; %! X(:, :, 2) = [15 23 81; 34 60 28; 70 54 38]; %! [Y, perm, shifts] = shiftdata(X, 2); %! T = [27 63 67; 42 48 74; 11 5 93]; %! T(:, :, 2) = [15 34 70; 23 60 54; 81 28 38]; %! assert(Y, T); %! assert(perm, [2 1 3]); %!test %! X = fix (rand (4, 4, 4, 4) * 100); %! [Y, perm, shifts] = shiftdata (X, 3); %! T = 0; %! for i = 1:3 %! for j = 1:3 %! for k = 1:2 %! for l = 1:2 %! T = [T Y(k, i, j, l) - X(i, j, k ,l)]; %! endfor %! endfor %! endfor %! endfor %! assert (T, zeros (size (T))); ## Test input validation %!error shiftdata () %!error shiftdata (1, 2, 3) %!error shiftdata (1, 2.5) ����������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/sigmoid_train.m�������������������������������������������������������������������0000644�0000000�0000000�00000011352�14673270174�013725� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2011-2013 Juan Pablo Carbajal <carbajal@ifi.uzh.ch> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{y} @var{s}] =} sigmoid_train (@var{t}, @var{ranges}, @var{rc}) ## ## Evaluate a train of sigmoid functions at @var{t}. ## ## The number and duration of each sigmoid is determined from @var{ranges}. ## Each row of @var{ranges} represents a real interval, e.g. if sigmoid ## @code{i} starts at @code{t=0.1} and ends at @code{t=0.5}, then ## @code{@var{ranges}(i,:) = [0.1 0.5]}. ## The input @var{rc} is an array that defines the rising and falling time ## constants of each sigmoid. Its size must equal the size of @var{ranges}. ## ## The individual sigmoids are returned in @var{s}. The combined sigmoid train ## is returned in the vector @var{y} of length equal to @var{t}, and such that ## @code{Y = max (S)}. ## ## Run @code{demo sigmoid_train} to some examples of the use of this function. ## ## @end deftypefn function [envelope Y] = sigmoid_train (t, range, timeconstant) ## number of sigmoids nRanges = size (range, 1); ## Parse time constants if isscalar (timeconstant) ## All bumps have the same time constant and are symmetric timeconstant = timeconstant * ones (nRanges,2); elseif any (size(timeconstant) == [1 1]) && nRanges > 1 ## All bumps have different time constant but are symmetric if isrow (timeconstant) timeconstant = timeconstant.'; endif if size (timeconstant, 1) != nRanges error('signalError','Length of time constant must equal number of ranges.') endif timeconstant = repmat (timeconstant,1,2); endif ## Make sure t is horizontal flag_transposed = false; if iscolumn (t) t = t.'; flag_transposed = true; endif [ncol nrow] = size (t); ## Compute arguments of each sigmoid # T = repmat (t, nRanges, 1); # RC1 = repmat (timeconstant(:,1), 1, nrow); # RC2 = repmat (timeconstant(:,2), 1, nrow); # a_up = (repmat (range(:,1), 1 ,nrow) - T) ./ RC1; # a_dw = (repmat (range(:,2), 1 ,nrow) - T) ./ RC2; # Using broadcasting a_up = bsxfun (@rdivide, bsxfun (@minus, range(:,1), t), timeconstant(:,1)); a_dw = bsxfun (@rdivide, bsxfun (@minus, range(:,2), t), timeconstant(:,2)); ## Evaluate the sigmoids and mix them Y = 1 ./ ( 1 + exp (a_up) ) .* (1 - 1 ./ ( 1 + exp (a_dw) ) ); envelope = max(Y,[],1); if flag_transposed envelope = envelope.'; Y = Y.'; endif endfunction %!demo %! # Vectorized %! t = linspace (0, 2, 500); %! range = [0.1 0.4; 0.6 0.8; 1 2]; %! rc = [1e-2 1e-3; 1e-3 2e-2; 2e-2 1e-2]; %! y = sigmoid_train (t, range, rc); %! for i=1:3 %! patch ([range(i,[2 2]) range(i,[1 1])], [0 1 1 0],... %! 'facecolor', [1 0.8 0.8],'edgecolor','none'); %! endfor %! hold on; plot (t, y, 'b;Sigmoid train;','linewidth',2); hold off %! xlabel('time'); ylabel('S(t)') %! title ('Vectorized use of sigmoid train') %! axis tight %! #------------------------------------------------------------------------- %! # The colored regions show the limits defined in range. %!demo %! # Varaible amplitude %! t = linspace (0, 2, 500); %! range = [0.1 0.4; 0.6 0.8; 1 2]; %! rc = [1e-2 1e-3; 1e-3 2e-2; 2e-2 1e-2]; %! amp = [4 2 3]; %! [~, S] = sigmoid_train (t, range, rc); %! y = amp * S; %! h = plot (t, y, '-b', t, S, '-'); %! set (h(1), "linewidth", 2); %! legend (h(1:2), {"Sigmoid train", "Components"}); %! xlabel('time'); ylabel('signal') %! title ('Varying amplitude sigmoid train') %! axis tight %!demo %! # On demand %! t = linspace(0,2,200).'; %! ran = [0.5 1; 1.5 1.7]; %! rc = 3e-2; %! dxdt = @(x_,t_) [ x_(2); sigmoid_train(t_, ran, rc) ]; %! y = lsode(dxdt,[0 0],t); %! for i=1:2 %! patch ([ran(i,[2 2]) ran(i,[1 1])], [0 1 1 0],... %! 'facecolor', [1 0.8 0.8],'edgecolor','none'); %! endfor %! hold on; plot (t, y(:,2), 'b;Speed;','linewidth',2); hold off %! xlabel('time'); ylabel('V(t)') %! title ('On demand use of sigmoid train') %! axis tight %! #------------------------------------------------------------------------- %! # The colored regions show periods when the force is active. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/sos2ss.m��������������������������������������������������������������������������0000644�0000000�0000000�00000002331�14673270174�012326� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2018 John W. Eaton ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} sos2ss (@var{sos}) ## Convert series second-order sections to state-space. ## ## @seealso{sos2ss, ss2tf} ## @end deftypefn function [a, b, c, d] = sos2ss (sos, g = 1) if (nargin < 1 || nargin > 2) print_usage (); endif [num, den] = sos2tf (sos, g); [a, b, c, d] = tf2ss (num, den); endfunction %!test %! sos = [1, 1, 0, 1, 0.5, 0]; %! g = 1; %! [a, b, c, d] = sos2ss (sos, g); %! assert ({a, b, c, d}, {-0.5, 0.5, 1, 1}); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/sos2tf.m��������������������������������������������������������������������������0000644�0000000�0000000�00000012667�14673270174�012327� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2005 Julius O. Smith III <jos@ccrma.stanford.edu> ## Copyright (C) 2021-2022 Charles Praplan ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{b}, @var{a}] =} sos2tf (@var{sos}) ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} sos2tf (@var{sos}, @var{g}) ## Convert series second-order sections to transfer function. ## ## INPUTS: ## @itemize ## ## @item ## @var{sos} = matrix of series second-order sections, one per row: ## @example ## @var{sos} = [@var{B1}.' @var{A1}.'; ...; @var{BN}.' @var{AN}.'] ## @end example ## where ## @code{@var{B1}.' = [b0 b1 b2] and @var{A1}.' = [a0 a1 a2]} for ## section 1, etc. ## ## a0 is usually equal to 1 because all 2nd order transfer functions ## can be scaled so that a0 = 1. ## However, this is not mandatory for this implementation, which supports ## all kinds of transfer functions, including first order transfer functions. ## See @code{filter} for documentation of the second-order direct-form filter ## coefficients @var{B}i and @var{A}i. ## ## @item ## @var{g} is an overall gain factor that effectively scales ## the output @var{b} vector (or any one of the input @var{B}i vectors). ## If not given the gain is assumed to be 1. ## @end itemize ## ## RETURNED: ## @var{b} and @var{a} are vectors specifying the analog or digital filter ## @math{H(s) = B(s)/A(s)} or @math{H(z) = B(z)/A(z)}. ## See @code{filter} for further details. ## ## @seealso{tf2sos, zp2sos, sos2pz, zp2tf, tf2zp} ## @end deftypefn function [B,A] = sos2tf(sos, g = 1) if (nargin < 1 || nargin > 2) print_usage; endif [N,M] = size(sos); if M~=6 error('sos2tf: sos matrix should be N by 6'); endif A = 1; B = 1; for i=1:N B = conv(B, sos(i,1:3)); A = conv(A, sos(i,4:6)); endfor nA = length (A); nB = length (B); if nA ~= nB error('Internal error: length (A) not equal to length (B)'); # This error cannot occur (if the above calls to the conv function # are not modified and if the conv function is also not modified) endif; clear nA; # Removing trailing zeros if present in numerator and denominator while nB && B(nB)==0 && A(nB)==0 B = B(1:nB-1); A = A(1:nB-1); nB = length (B); endwhile # Removing leading zeros if present in numerator and denominator while nB && B(1)==0 && A(1)==0 A = A(2:end); B = B(2:end); nB--; endwhile B = B .* prod (g); endfunction %!test %! B = [1, 1]; %! A = [1, 0.5]; %! [sos, g] = tf2sos (B, A); %! [Bh, Ah] = sos2tf (sos, g); %! assert (g, 1); %! assert (Bh, B, 10*eps); %! assert (Ah, A, 10*eps); %!test %! B = [1, 0, 0, 0, 0, 1]; %! A = [1, 0, 0, 0, 0, 0.9]; %! [sos, g] = tf2sos (B, A); %! [Bh, Ah] = sos2tf (sos, g); %! assert (g, 1); %! assert (Bh, B, 100*eps); %! assert (Ah, A, 100*eps); ## Test that gain is applied to the B vector %!test %! B = [1, 1]; %! A = [1, 0.5]; %! [sos, g] = tf2sos (B, A); %! [Bh, Ah] = sos2tf (sos, 2); %! assert (g, 1); %! assert (Bh, 2 * B, 10*eps); %! assert (Ah, A, 10*eps); ## Test that a vector of gain is applied as the total product %!test %! B = [1, 1]; %! A = [1, 0.5]; %! [sos, g] = tf2sos (B, A); %! [Bh, Ah] = sos2tf (sos, [2, 2, 2]); %! assert (g, 1); %! assert (Bh, 8 * B, 10*eps); %! assert (Ah, A, 10*eps); ## Test with trailing zero in numerator %!test %! sos = [1, 1, 0, 0, 1, 0.5]; %! [Bh, Ah] = sos2tf (sos); %! assert (Bh, sos(1,1:3) , 10*eps); %! assert (Ah, sos(1,4:6), 10*eps); ## Test with trailing zero in denominator %!test %! sos = [0, 1, 1, 1, 0.5, 0]; %! [Bh, Ah] = sos2tf (sos); %! assert (Bh, sos(1,1:3) , 10*eps); %! assert (Ah, sos(1,4:6), 10*eps); ## Test with trailing zero both in numerator and in denominator %!test %! sos = [1, 1, 0, 1, 0.5, 0]; %! [Bh, Ah] = sos2tf (sos); %! assert (Bh, [1, 1] , 10*eps); %! assert (Ah, [1, 0.5], 10*eps); ## Test with leading zero in numerator %!test %! sos = [0, 1, 1, 1, 1, 0.5]; %! [Bh, Ah] = sos2tf (sos); %! assert (Bh, sos(1,1:3) , 10*eps); %! assert (Ah, sos(1,4:6), 10*eps); ## Test with leading zero in denominator %!test %! sos = [1, 1, 0, 0, 1, 0.5]; %! [Bh, Ah] = sos2tf (sos); %! assert (Bh, sos(1,1:3) , 10*eps); %! assert (Ah, sos(1,4:6), 10*eps); ## Test with leading zero both in numerator and in denominator %!test %! sos = [0, 1, 1, 0, 1, 0.5]; %! [Bh, Ah] = sos2tf (sos); %! assert (Bh, [1, 1] , 10*eps); %! assert (Ah, [1, 0.5], 10*eps); ## Test with 3 trailing zeros both in numerator and in denominator %!test %! sos = [1, 1, 0, 1, 0.5, 0; 1, 1, 0, 1, 0.5, 0; 1, 1, 0, 1, 0.5, 0]; %! [Bh, Ah] = sos2tf (sos); %! assert (Bh, [1, 3, 3, 1] , 10*eps); %! assert (Ah, [1, 1.5 0.75 0.125], 10*eps); ## Test with 3 leading zeros both in numerator and in denominator %!test %! sos = [0, 1, 1, 0, 1, 0.5; 0, 1, 1, 0, 1, 0.5;0, 1, 1, 0, 1, 0.5]; %! [Bh, Ah] = sos2tf (sos); %! assert (Bh, [1, 3, 3, 1] , 10*eps); %! assert (Ah, [1, 1.5 0.75 0.125], 10*eps); �������������������������������������������������������������������������signal-1.4.6/inst/sos2zp.m��������������������������������������������������������������������������0000644�0000000�0000000�00000011550�14673270174�012335� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2005 Julius O. Smith III <jos@ccrma.stanford.edu> ## Copyright (C) 2021 Charles Praplan ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{z}, @var{p}, @var{k}] =} sos2zp (@var{sos}) ## @deftypefnx {Function File} {[@var{z}, @var{p}, @var{k}] =} sos2zp (@var{sos}, @var{g}) ## Convert series second-order sections to zeros, poles, and gains ## (pole residues). ## ## INPUTS: ## @itemize ## ## @item ## @var{sos} = matrix of series second-order sections, one per row: ## @example ## @var{sos} = [@var{B1}.' @var{A1}.'; ...; @var{BN}.' @var{AN}.'] ## @end example ## where ## @code{@var{B1}.' = [b0 b1 b2] and @var{A1}.' = [a0 a1 a2]} for ## section 1, etc. ## ## a0 is usually equal to 1 because all 2nd order transfer functions can ## be scaled so that a0 = 1. ## However, this is not mandatory for this implementation, which supports ## all kinds of transfer functions, including first order transfer functions. ## See @code{filter} for documentation of the second-order direct-form filter ## coefficients @var{B}i and @var{A}i. ## ## @item ## @var{g} is an overall gain factor that effectively scales ## any one of the input @var{B}i vectors. ## If not given the gain is assumed to be 1. ## @end itemize ## ## RETURNED: ## @itemize ## @item ## @var{z} = column-vector containing all zeros (roots of B(z)) ## @item ## @var{p} = column-vector containing all poles (roots of A(z)) ## @item ## @var{k} = overall gain = @var{B}(Inf) ## @end itemize ## ## EXAMPLE: ## @example ## [z, p, k] = sos2zp ([1 0 1, 1 0 -0.81; 1 0 0, 1 0 0.49]) ## @result{} z = ## 0 + 1i ## 0 - 1i ## 0 + 0i ## 0 + 0i ## @result{} p = ## -0.9000 + 0i ## 0.9000 + 0i ## 0 + 0.7000i ## 0 - 0.7000i ## @result{} k = 1 ## @end example ## ## @seealso{zp2sos, sos2tf, tf2sos, zp2tf, tf2zp} ## @end deftypefn function [z,p,k] = sos2zp (sos, g = 1) if (nargin < 1 || nargin > 2) print_usage; endif [N,m] = size(sos); if m~=6, error('sos2zp: sos matrix should be N by 6'); endif k = g; for i = 1:N b = sos(i,1:3); N2 = 3; while N2 && b(1)==0 # Removing leading zeros b = b(2:end); N2 = N2 - 1; endwhile a = sos(i,4:6); N2 = 3; while N2 && a(1)==0 # Removing leading zeros a = a(2:end); N2--; endwhile if isempty (a) warning ('Infinite gain detected'); k = Inf; elseif a(1) == 0 warning ('Infinite gain detected'); k = Inf; elseif isempty (b) k = 0; else k = k * b(1) / a(1); endif endfor z = []; p = []; for i=1:N z=[z; roots(sos(i,1:3))]; p=[p; roots(sos(i,4:6))]; endfor endfunction %!test %! b1t=[1 2 3]; a1t=[1 .2 .3]; %! b2t=[4 5 6]; a2t=[1 .4 .5]; %! sos=[b1t a1t; b2t a2t]; %! z = [-1-1.41421356237310i;-1+1.41421356237310i;... %! -0.625-1.05326872164704i;-0.625+1.05326872164704i]; %! p = [-0.2-0.678232998312527i;-0.2+0.678232998312527i;... %! -0.1-0.538516480713450i;-0.1+0.538516480713450i]; %! k = 4; %! [z2,p2,k2] = sos2zp(sos,1); %! assert({cplxpair(z2),cplxpair(p2),k2},{z,p,k},100*eps); ## Test with trailing zero in numerator %!test %! sos = [1, 1, 0, 1, 1, 0.5]; %! [Z, P] = sos2zp (sos); %! assert (Z, roots (sos(1,1:3)), 10*eps); %! assert (P, roots (sos(1,4:6)), 10*eps); ## Test with trailing zero in denominator %!test %! sos = [0, 1, 1, 1, 0.5, 0]; %! [Z, P] = sos2zp (sos); %! assert (Z, roots (sos(1,1:3)), 10*eps); %! assert (P, roots (sos(1,4:6)), 10*eps); ## Test with trailing zero both in numerator and in denominator %!test %! sos = [1, 1, 0, 1, 0.5, 0]; %! [Z, P] = sos2zp (sos); %! assert (Z, roots (sos(1,1:3)), 10*eps); %! assert (P, roots (sos(1,4:6)), 10*eps); ## Test with leading zero in numerator %!test %! sos = [0, 1, 1, 1, 1, 0.5]; %! [Z, P] = sos2zp (sos); %! assert (Z, roots (sos(1,1:3)), 10*eps); %! assert (P, roots (sos(1,4:6)), 10*eps); ## Test with leading zero in denominator %!test %! sos = [1, 1, 0, 0, 1, 0.5]; %! [Z, P] = sos2zp (sos); %! assert (Z, roots (sos(1,1:3)), 10*eps); %! assert (P, roots (sos(1,4:6)), 10*eps); ## Test with leading zero both in numerator and in denominator %!test %! sos = [0, 1, 1, 0, 1, 0.5]; %! [Z, P] = sos2zp (sos); %! assert (Z, roots (sos(1,1:3)), 10*eps); %! assert (P, roots (sos(1,4:6)), 10*eps); ��������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/specgram.m������������������������������������������������������������������������0000644�0000000�0000000�00000022314�14673270174�012676� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999-2001 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} specgram (@var{x}) ## @deftypefnx {Function File} {} specgram (@var{x}, @var{n}) ## @deftypefnx {Function File} {} specgram (@var{x}, @var{n}, @var{Fs}) ## @deftypefnx {Function File} {} specgram (@var{x}, @var{n}, @var{Fs}, @var{window}) ## @deftypefnx {Function File} {} specgram (@var{x}, @var{n}, @var{Fs}, @var{window}, @var{overlap}) ## @deftypefnx {Function File} {[@var{S}, @var{f}, @var{t}] =} specgram (@dots{}) ## ## Generate a spectrogram for the signal @var{x}. The signal is chopped into ## overlapping segments of length @var{n}, and each segment is windowed and ## transformed into the frequency domain using the FFT. The default segment ## size is 256. If @var{fs} is given, it specifies the sampling rate of the ## input signal. The argument @var{window} specifies an alternate window to ## apply rather than the default of @code{hanning (@var{n})}. The argument ## @var{overlap} specifies the number of samples overlap between successive ## segments of the input signal. The default overlap is ## @code{length (@var{window})/2}. ## ## If no output arguments are given, the spectrogram is displayed. Otherwise, ## @var{S} is the complex output of the FFT, one row per slice, @var{f} is the ## frequency indices corresponding to the rows of @var{S}, and @var{t} is the ## time indices corresponding to the columns of @var{S}. ## ## Example: ## @example ## @group ## x = chirp([0:0.001:2],0,2,500); # freq. sweep from 0-500 over 2 sec. ## Fs=1000; # sampled every 0.001 sec so rate is 1 kHz ## step=ceil(20*Fs/1000); # one spectral slice every 20 ms ## window=ceil(100*Fs/1000); # 100 ms data window ## specgram(x, 2^nextpow2(window), Fs, window, window-step); ## ## ## Speech spectrogram ## [x, Fs] = auload(file_in_loadpath("sample.wav")); # audio file ## step = fix(5*Fs/1000); # one spectral slice every 5 ms ## window = fix(40*Fs/1000); # 40 ms data window ## fftn = 2^nextpow2(window); # next highest power of 2 ## [S, f, t] = specgram(x, fftn, Fs, window, window-step); ## S = abs(S(2:fftn*4000/Fs,:)); # magnitude in range 0<f<=4000 Hz. ## S = S/max(S(:)); # normalize magnitude so that max is 0 dB. ## S = max(S, 10^(-40/10)); # clip below -40 dB. ## S = min(S, 10^(-3/10)); # clip above -3 dB. ## imagesc (t, f, log(S)); # display in log scale ## set (gca, "ydir", "normal"); # put the 'y' direction in the correct direction ## @end group ## @end example ## ## The choice of window defines the time-frequency resolution. In ## speech for example, a wide window shows more harmonic detail while a ## narrow window averages over the harmonic detail and shows more ## formant structure. The shape of the window is not so critical so long ## as it goes gradually to zero on the ends. ## ## Step size (which is window length minus overlap) controls the ## horizontal scale of the spectrogram. Decrease it to stretch, or ## increase it to compress. Increasing step size will reduce time ## resolution, but decreasing it will not improve it much beyond the ## limits imposed by the window size (you do gain a little bit, ## depending on the shape of your window, as the peak of the window ## slides over peaks in the signal energy). The range 1-5 msec is good ## for speech. ## ## FFT length controls the vertical scale. Selecting an FFT length ## greater than the window length does not add any information to the ## spectrum, but it is a good way to interpolate between frequency ## points which can make for prettier spectrograms. ## ## After you have generated the spectral slices, there are a number of ## decisions for displaying them. First the phase information is ## discarded and the energy normalized: ## ## S = abs(S); S = S/max(S(:)); ## ## Then the dynamic range of the signal is chosen. Since information in ## speech is well above the noise floor, it makes sense to eliminate any ## dynamic range at the bottom end. This is done by taking the max of ## the magnitude and some minimum energy such as minE=-40dB. Similarly, ## there is not much information in the very top of the range, so ## clipping to a maximum energy such as maxE=-3dB makes sense: ## ## S = max(S, 10^(minE/10)); S = min(S, 10^(maxE/10)); ## ## The frequency range of the FFT is from 0 to the Nyquist frequency of ## one half the sampling rate. If the signal of interest is band ## limited, you do not need to display the entire frequency range. In ## speech for example, most of the signal is below 4 kHz, so there is no ## reason to display up to the Nyquist frequency of 10 kHz for a 20 kHz ## sampling rate. In this case you will want to keep only the first 40% ## of the rows of the returned S and f. More generally, to display the ## frequency range [minF, maxF], you could use the following row index: ## ## idx = (f >= minF & f <= maxF); ## ## Then there is the choice of colormap. A brightness varying colormap ## such as copper or bone gives good shape to the ridges and valleys. A ## hue varying colormap such as jet or hsv gives an indication of the ## steepness of the slopes. The final spectrogram is displayed in log ## energy scale and by convention has low frequencies on the bottom of ## the image: ## ## imagesc(t, f, flipud(log(S(idx,:)))); ## @end deftypefn function [S_r, f_r, t_r] = specgram(x, n = min(256, length(x)), Fs = 2, window = hanning(n), overlap = ceil(length(window)/2)) if (nargin < 1 || nargin > 5) print_usage (); endif if (! isnumeric (x) || ! isvector (x)) error ("specgram: X must be a numeric vector"); endif x = x(:); ## if only the window length is given, generate hanning window if (isscalar (window)) window = hanning (window); endif ## should be extended to accept a vector of frequencies at which to ## evaluate the Fourier transform (via filterbank or chirp ## z-transform) if (! isscalar (n)) error ("specgram: N must be a scalar, vector of frequencies not supported"); endif if (length (x) <= length (window)) error ("specgram: segment length must be less than the size of X"); endif ## compute window offsets win_size = length(window); if (win_size > n) n = win_size; warning ("specgram fft size adjusted to %d", n); endif step = win_size - overlap; ## build matrix of windowed data slices offset = [ 1 : step : length(x)-win_size ]; S = zeros (n, length(offset)); for i=1:length(offset) S(1:win_size, i) = x(offset(i):offset(i)+win_size-1) .* window; endfor ## compute Fourier transform S = fft (S); ## extract the positive frequency components if rem(n,2)==1 ret_n = (n+1)/2; else ret_n = n/2; endif S = S(1:ret_n, :); f = [0:ret_n-1]*Fs/n; t = offset/Fs; if nargout==0 imagesc(t, f, 20*log10(abs(S))); set (gca (), "ydir", "normal"); xlabel ("Time") ylabel ("Frequency") endif if nargout>0, S_r = S; endif if nargout>1, f_r = f; endif if nargout>2, t_r = t; endif endfunction %!shared S,f,t,x %! Fs=1000; %! x = chirp([0:1/Fs:2],0,2,500); # freq. sweep from 0-500 over 2 sec. %! step=ceil(20*Fs/1000); # one spectral slice every 20 ms %! window=ceil(100*Fs/1000); # 100 ms data window %! [S, f, t] = specgram(x); %! ## test of returned shape %!assert (rows(S), 128) %!assert (columns(f), rows(S)) %!assert (columns(t), columns(S)) %!test [S, f, t] = specgram(x'); %!assert (rows(S), 128) %!assert (columns(f), rows(S)); %!assert (columns(t), columns(S)); %!error (isempty(specgram([]))); %!error (isempty(specgram([1, 2 ; 3, 4]))); %!error (specgram) %!demo %! Fs=1000; %! x = chirp([0:1/Fs:2],0,2,500); # freq. sweep from 0-500 over 2 sec. %! step=ceil(20*Fs/1000); # one spectral slice every 20 ms %! window=ceil(100*Fs/1000); # 100 ms data window %! %! ## test of automatic plot %! [S, f, t] = specgram(x); %! specgram(x, 2^nextpow2(window), Fs, window, window-step); %!#demo # FIXME: Enable once we have an audio file to demo %! ## Speech spectrogram %! [x, Fs] = auload(file_in_loadpath("sample.wav")); # audio file %! step = fix(5*Fs/1000); # one spectral slice every 5 ms %! window = fix(40*Fs/1000); # 40 ms data window %! fftn = 2^nextpow2(window); # next highest power of 2 %! [S, f, t] = specgram(x, fftn, Fs, window, window-step); %! S = abs(S(2:fftn*4000/Fs,:)); # magnitude in range 0<f<=4000 Hz. %! S = S/max(max(S)); # normalize magnitude so that max is 0 dB. %! S = max(S, 10^(-40/10)); # clip below -40 dB. %! S = min(S, 10^(-3/10)); # clip above -3 dB. %! imagesc(flipud(20*log10(S))); %! %! % The image contains a spectrogram of 'sample.wav' ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/square.m��������������������������������������������������������������������������0000644�0000000�0000000�00000001534�14673270174�012376� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Author: Paul Kienzle <paulkienzle@Avocado.local> (2006) ## This program is granted to the public domain. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{s} =} square (@var{t}, @var{duty}) ## @deftypefnx {Function File} {@var{s} =} square (@var{t}) ## Generate a square wave of period 2 pi with limits +1/-1. ## ## If @var{duty} is specified, it is the percentage of time the square ## wave is "on". The square wave is +1 for that portion of the time. ## ## @verbatim ## on time * 100 ## duty cycle = ------------------ ## on time + off time ## @end verbatim ## ## @seealso{cos, sawtooth, sin, tripuls} ## @end deftypefn function v = square (t, duty = 50) if (nargin < 1 || nargin > 2) print_usage; endif duty /= 100; t /= 2*pi; v = ones(size(t)); v(t-floor(t) >= duty) = -1; endfunction ��������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/ss2tf.m���������������������������������������������������������������������������0000644�0000000�0000000�00000003342�14673270174�012136� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1994, 1996, 2000, 2004, 2005, 2007 Auburn University <btenison@eng.auburn.edu> ## Copyright (C) 2012 Lukas F. Reichlin <lukas.reichlin@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{num}, @var{den}] =} ss2tf (@var{a}, @var{b}, @var{c}, @var{d}) ## Conversion from state-space to transfer function representation. ## The state space system: ## @tex ## $$ \dot x = Ax + Bu $$ ## $$ y = Cx + Du $$ ## @end tex ## @ifnottex ## @example ## @group ## . ## x = Ax + Bu ## y = Cx + Du ## @end group ## @end example ## @end ifnottex ## ## is converted to a transfer function: ## @tex ## $$ G(s) = { { \rm num }(s) \over { \rm den }(s) } $$ ## @end tex ## @ifnottex ## @example ## @group ## num(s) ## G(s)=------- ## den(s) ## @end group ## @end example ## @end ifnottex ## ## @end deftypefn ## Author: R. Bruce Tenison <btenison@eng.auburn.edu> function [num, den] = ss2tf (varargin) if (nargin == 0) print_usage (); endif [num, den] = tfdata (ss (varargin{:}), "vector"); endfunction ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/ss2zp.m���������������������������������������������������������������������������0000644�0000000�0000000�00000002350�14673270174�012154� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1994, 1996, 2000, 2004, 2005, 2006, 2007 Auburn University ## Copyright (C) 2012 Lukas F. Reichlin <lukas.reichlin@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{z}, @var{p}, @var{k}] =} ss2zp (@var{a}, @var{b}, @var{c}, @var{d}) ## Converts a state space representation to a set of poles and zeros; ## @var{k} is a gain associated with the zeros. ## ## @end deftypefn ## Author: David Clem function [z, p, k] = ss2zp (varargin) if (nargin == 0) print_usage (); endif [z, p, k] = zpkdata (ss (varargin{:}), "vector"); endfunction ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/statelevels.m���������������������������������������������������������������������0000644�0000000�0000000�00000017226�14673270174�013436� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2016 Chris Adams <octave@chrisada.co.uk> ## ## 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 <http://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{levels} =} statelevels (@var{A}) ## @deftypefnx {Function File} {@var{levels} =} statelevels (@var{A}, @var{nbins}) ## @deftypefnx {Function File} {@var{levels} =} statelevels (@var{A}, @var{nbins}, @var{method}) ## @deftypefnx {Function File} {@var{levels} =} statelevels (@var{A}, @var{nbins}, @var{method}, @var{bounds}) ## @deftypefnx {Function File} {[@var{levels}, @var{histograms}] =} statelevels (@dots{}) ## @deftypefnx {Function File} {[@var{levels}, @var{histograms}, @var{binlevels}] =} statelevels (@dots{}) ## @deftypefnx {Function File} {} statelevels (@dots{}) ## Estimate state-level for bilevel waveform @var{A} using histogram method ## ## INPUTS: ## ## @table @var ## @item A ## Bylevel waveform ## @item nbins ## Number of histogram bins (100 default) ## @item method ## State-level estimation method 'mode' (default) or 'mean'. ## @item bounds ## 2 element vector for histogram lower and upper bounds. Values outside of this will be ignored. ## @end table ## ## OUTPUTS: ## ## @table @var ## @item levels ## Levels of high and low states ## @item histograms ## Histogram counts ## @item binlevels ## Histogram bincenters ## @end table ## ## If no outputs are provided, the signal and histogram will be plotted, and display the levels. ## ## @end deftypefn function varargout = statelevels (A, varargin) if nargin == 0 || nargin > 4 || nargout > 3 print_usage() endif # Setup arguments based on number of given arguments nBins = 100; method = 1; if nargin > 1 if !isnumeric (varargin{1}) error ('statelevels expects a number for argument 2'); endif nBins = varargin{1}; endif if nargin > 2 if !ischar(varargin{2}) error ("Expected method of 'mode' or 'mean'") endif if strcmp(varargin{2}, 'mode') method = 1; elseif strcmp(varargin{2}, 'mean') method = 0; else error ("Expected method of 'mode' or 'mean'") endif endif # Get size first for various uses sz = size(A); # Row column vector checking # Are any of the columns of size one? if (sz(1) != 1 && sz(2) != 1) || (sz(1) == 1 && sz(2) == 1) error ('statelevels expects a numeric vector for waveform'); endif if !isnumeric(A) || !isreal(A) error ('statelevels expects a numeric vector for waveform'); endif # Switch to row if it's a column vector if sz(2) == 1 X = A'; else X = A; endif if nargin > 3 b = varargin{3}; if !isnumeric(b) || !isreal(b) || length(b) != 2 error ('statelevels expects a 2 element numeric vector for bounds'); endif lower = b(1); upper = b(2); if upper < lower error ('Upper bound should be greater than lower bound'); endif else upper = max(X)+eps; lower = min(X)-eps; endif # Generate hist vector based on the bounds in the histogram histVec = lower + ((1:nBins) - 0.5)' * (upper - lower) / nBins; # Get a histogram # Generate indexes for the histogram idx = ceil(nBins * (X-lower)/(upper-lower)); # Pick only indexes in the range idx = idx(idx>=1 & idx<=nBins); # Initialise the histogram with zeros histogram = zeros(nBins, 1); # For every valid index increment the value if it hits for i = 1:size (idx,2) histogram(idx(i)) = histogram(idx(i)) + 1; endfor # Find the bounds, lowest non zero and highest iLow = 0; iHigh = 0; for i = 1:nBins if histogram(i) > 0 iLow = i; break; endif endfor for i = nBins:-1:1 if histogram(i) > 0 iHigh = i; break; endif endfor # Define index pairs that define the lower and upper histogram slices. # We'll need these later lLow = iLow; lHigh = iLow + floor ((iHigh - iLow)/2); uLow = iLow + floor ((iHigh - iLow)/2); uHigh = iHigh; lHist = histogram(iLow:lHigh, 1); uHist = histogram(uLow:uHigh, 1); # What's the amplitude, size ratio (see ref) dy = (upper-lower) / size (histogram,1); # If mode (default) if method == 1 [~, iMax] = max (lHist); [~, iMin] = max (uHist); S1 = lower + dy * (lLow + iMax(1) - 1.5); S2 = lower + dy * (uLow + iMin(1) - 1.5); elseif (method==0) S1 = lower + dy * dot ((lLow:lHigh)-0.5, lHist) / sum (lHist); S2 = lower + dy * dot ((uLow:uHigh)-0.5, uHist) / sum (uHist); endif varargout{1} = [S1 S2]; if nargout == 0 f = figure(); subplot (2, 1, 1); plot(A) title('Signal'); xlabel('Samples'); ylabel('Level'); subplot (2, 1, 2); plot(histVec, histogram); title(sprintf('Histogram of signal levels (%d bins)', nBins)); xlabel('Level'); ylabel('Count'); endif if nargout > 1 varargout{2} = histogram; endif if nargout > 2 varargout{3} = histVec; endif endfunction %! ## test input validation %!error l = statelevels() %!error l = statelevels("test") %!error l = statelevels(1) %!error l = statelevels([1 2 3], 'test') %!error l = statelevels([1 2 3], 3, 'test') %!error l = statelevels([1 2 3], 3, 'mode', 1) %!error l = statelevels([1 2 3], 3, 'mode', [1 -1]) %!shared X %! t = linspace(0,2*pi*10,100); %! X = square(t) + cos(t); %!test %! l = statelevels(X); %! assert(l, [-1.9795 1.9800], 1e5) %!test %! [l, h] = statelevels(X); %! assert(l, [-1.9795 1.9800], 1e5) %! assert(sum(h), 100) %! assert(length(h), 100) %!test %! [l, h, b] = statelevels(X); %! assert(l, [-1.9795 1.9800], 1e5) %! assert(sum(h), 100) %! assert(length(h), 100) %! assert(h(1), 4) %! assert(h(2), 2) %! assert(h(4), 1) %! assert(h(11), 0) %! assert(b(1), -1.9795, 1e5) %! assert(b(2), -1.9395, 1e5) %!test %! [l, h, b] = statelevels(X, 100); %! assert(l, [-1.9795 1.9800], 1e5) %! assert(sum(h), 100) %! assert(length(h), 100) %! assert(h(1), 4) %! assert(h(2), 2) %! assert(h(4), 1) %! assert(h(11), 0) %! assert(b(1), -1.9795, 1e5) %! assert(b(2), -1.9395, 1e5) %!test %! [l, h, b] = statelevels(X, 50); %! assert(l, [-1.9595 1.9600], 1e5) %! assert(sum(h), 100) %! assert(length(h), 50) %! assert(h(1), 6) %! assert(h(2), 3) %! assert(h(4), 2) %! assert(h(11), 1) %! assert(b(1), -1.9595, 1e5) %! assert(b(2), -1.8795, 1e5) %!test %! [l, h, b] = statelevels(X, 100, 'mode'); %! assert(l, [-1.9795 1.9800], 1e5) %! assert(sum(h), 100) %! assert(length(h), 100) %! assert(h(1), 4) %! assert(h(2), 2) %! assert(h(4), 1) %! assert(h(11), 0) %! assert(b(1), -1.9795, 1e5) %! assert(b(2), -1.9395, 1e5) %!test %! [l, h, b] = statelevels(X, 100, 'mean'); %! assert(l, [-1.0090 0.9532], 1e5) %! assert(sum(h), 100) %! assert(length(h), 100) %! assert(h(1), 4) %! assert(h(2), 2) %! assert(h(4), 1) %! assert(h(11), 0) %! assert(b(1), -1.9795, 1e5) %! assert(b(2), -1.9395, 1e5) %!test %! [l, h, b] = statelevels(X, 100, 'mode', [-1.8 1.0]); %! assert(l, [-1.7860 0.0060], 1e5) %! assert(sum(h), 64) %! assert(length(h), 100) %! assert(h(1), 1) %! assert(h(2), 1) %! assert(h(3), 0) %! assert(b(1), -1.7860, 1e5) %! assert(b(2), -1.7580, 1e5) %!demo %! # Generate test signal %! t = linspace(0,2*pi*10,100); %! X = square(t) + cos(t); %! # plot the waveform and provide the levels %! statelevels(X) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/taylorwin.m�����������������������������������������������������������������������0000644�0000000�0000000�00000010006�14673270174�013120� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2023 The Octave Project Developers ## ## See the file COPYRIGHT.md in the top-level directory of this ## distribution or <https://octave.org/copyright/>. ## ## This file is part of Octave. ## ## Octave 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. ## ## Octave 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 Octave; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} taylorwin (@var{m}) ## @deftypefnx {Function File} taylorwin (@var{m}, @var{nbar}) ## @deftypefnx {Function File} taylorwin (@var{m}, @var{nbar}, @var{sll}) ## @deftypefnx {Function File} taylorwin (@var{m}, @var{nbar}, @var{sll}, @var{plots}) ## Return the coefficients of a Taylor window of length @var{m}, whose ## Fourier transform has @var{nbar} (default 4) quasi-equiripple side-lobes ## adjacent to the main-lobe, at a nominal level of @var{sll} (default ## @minus{}30) dBc. ## ## If @var{plots} is non-zero then time and frequency domains plots of the ## resultant window are shown. ## ## Reference: ## Doerry, `Catalog of Window Taper Functions for Sidelobe Control', 2017. ## @seealso{chebwin} ## @end deftypefn function W = taylorwin (m, nbar=4, sll=-30, plots=0) if (nargin<1 || nargin>4) print_usage (); elseif (!isscalar (m) || imag (m) || mod (m,1) || m<1) error ('taylorwin: M must be a positive integer'); elseif (!isscalar (nbar) || imag (nbar) || mod (nbar,1) || nbar<1) error ('taylorwin: NBAR must be a positive integer'); elseif (!isscalar (sll) || imag (sll)) error ('taylorwin: SLL must be a real scalar'); elseif (!isscalar (plots)) error ('taylorwin: PLOTS must be a scalar'); endif a2 = (acosh (10^(sll/-20))/pi)^2; N = 1:nbar-1; M = (a2+(nbar-.5)^2)./(nbar^2*(a2+(N-.5).^2)); T = pi/m*[1:2:m]; W = T>0; for n=N W -= prod (1-n*n*M)/prod (nonzeros (1-(n./N).^2))*cos (T*n); endfor W = [W W(m-length (W):-1:1)]'; if plots && m>2 clf subplot (311); ifelse (m>100,@plot,@stem) (linspace (-.5,.5,m),W); axis ([-.51 .51 min([W' 0]) max(W)/.9]); grid on; title (sprintf ('Taylor window: M = %i, NBAR = %i, SLL = %g', m, nbar, sll)); [h f] = freqz (W/sum (W),1,2^(ceil (log2 (m))+7)); x = f/pi*m/2; y = 20*log10 (abs (h)); subplot (312); plot (x,y); axis ([0 min([m/2 nbar+4]) sll-25 ym=max([0 sll])+4]); ylabel ('dBc'); xlabel ('Nominal bins'); grid on; subplot (313); semilogx (x(2:end), y(2:end)); axis ([.1 m/2 sll-40 ym]); ylabel ('dBc'); xlabel ('Nominal bins'); grid on; endif endfunction %!test % odd M; even NBAR: %! w = [.2035 .272 .4013 .5717 .7626 .9644 1.1683 1.3598 1.5254 1.6541 1.7354 1.7629]; %! assert (taylorwin (23, 8, -40), [w w(end-1:-1:1)]', 51e-6); %!test % even M; odd NBAR: %! w = [.4025 .4488 .5367 .6576 .8004 .9528 1.1028 1.2402 1.3573 1.4484 1.5105 1.5419]; %! assert (taylorwin (24, 3), [w flip(w)]', 51e-6); %% Test input validation: %!error taylorwin %!error taylorwin (0) %!error taylorwin (30.5) %!error taylorwin (30i) %!error taylorwin (30:31) %!error taylorwin ({30}) %!error taylorwin (30, 0) %!error taylorwin (30, 4.5) %!error taylorwin (30, 4i) %!error taylorwin (30, 2:3) %!error taylorwin (30, {4}) %!error taylorwin (30, 4, -30i) %!error taylorwin (30, 4, -30:-20) %!error taylorwin (30, 4, {-30}) %!error taylorwin (30, 4, -30, 0:1) %!error taylorwin (30, 4, -30, {}) %!error taylorwin (30, 4, -30, 1, 0) %% Demonstrations per Doerry: %!demo taylorwin (2000, 4, -35, 1); %!demo taylorwin (2000, 5, -40, 1); %!demo taylorwin (2000, 7, -50, 1); %!demo taylorwin (2000, 11, -70, 1); ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/tf2sos.m��������������������������������������������������������������������������0000644�0000000�0000000�00000004753�14673270174�012324� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2005 Julius O. Smith III <jos@ccrma.stanford.edu> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{sos}, @var{g}] =} tf2sos (@var{b}, @var{a}) ## @deftypefnx {Function File} {@var{sos} =} tf2sos (@var{b}, @var{a}) ## Convert direct-form filter coefficients to series second-order sections. ## ## INPUTS: ## ## @var{b} and @var{a} are vectors specifying the digital filter ## @math{H(z) = B(z)/A(z)}. See @code{filter} for documentation of the @var{b} ## and @var{a} filter coefficients. ## ## RETURNED: ## @itemize ## @item ## @var{sos} = matrix of series second-order sections, one per row: ## @example ## @var{sos} = [@var{b1}.' @var{a1}.'; ...; @var{bn}.' @var{an}.'] ## @end example ## where ## @code{@var{B1}.' = [b0 b1 b2] and @var{A1}.' = [1 a1 a2]} for ## section 1, etc. The b0 entry must be nonzero for each section (zeros at ## infinity not supported). ## @item ## @var{g} is an overall gain factor that effectively scales ## any one of the @var{B}i vectors. ## @end itemize ## ## If called with only one output argument, the overall filter gain is ## applied to the first second-order section in the matrix @var{sos}. ## ## EXAMPLE: ## @example ## B = [1 0 0 0 0 1]; ## A = [1 0 0 0 0 .9]; ## [sos, g] = tf2sos (B, A) ## ## sos = ## ## 1.00000 0.61803 1.00000 1.00000 0.60515 0.95873 ## 1.00000 -1.61803 1.00000 1.00000 -1.58430 0.95873 ## 1.00000 1.00000 -0.00000 1.00000 0.97915 -0.00000 ## ## g = 1 ## @end example ## ## @seealso{sos2tf, zp2sos, sos2pz, zp2tf, tf2zp} ## @end deftypefn function [sos,g] = tf2sos (B, A) [z,p,k] = tf2zp(B(:)',A(:)'); if (nargout < 2) sos = zp2sos(z,p,k); else [sos,g] = zp2sos(z,p,k); endif endfunction %!test %! B=[1 0 0 0 0 1]; A=[1 0 0 0 0 .9]; %! [sos,g] = tf2sos(B,A); %! [Bh,Ah] = sos2tf(sos,g); %! assert({Bh,Ah},{B,A},100*eps); ���������������������signal-1.4.6/inst/tf2ss.m���������������������������������������������������������������������������0000644�0000000�0000000�00000003545�14673270174�012143� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1994-1996, 1998, 2000, 2002, 2004, 2005, 2007 Auburn University ## Copyright (C) 2012 Lukas F. Reichlin <lukas.reichlin@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} tf2ss (@var{num}, @var{den}) ## Conversion from transfer function to state-space. ## The state space system: ## @tex ## $$ \dot x = Ax + Bu $$ ## $$ y = Cx + Du $$ ## @end tex ## @ifnottex ## @example ## @group ## . ## x = Ax + Bu ## y = Cx + Du ## @end group ## @end example ## @end ifnottex ## is obtained from a transfer function: ## @tex ## $$ G(s) = { { \rm num }(s) \over { \rm den }(s) } $$ ## @end tex ## @ifnottex ## @example ## @group ## num(s) ## G(s)=------- ## den(s) ## @end group ## @end example ## @end ifnottex ## ## The state space system matrices obtained from this function ## will be in observable companion form as Wolovich's Observable ## Structure Theorem is used. ## @end deftypefn ## Author: R. Bruce Tenison <btenison@eng.auburn.edu> function [a, b, c, d, e] = tf2ss (varargin) if (nargin == 0) print_usage (); endif [a, b, c, d, e] = dssdata (tf (varargin{:}), []); endfunction �����������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/tf2zp.m���������������������������������������������������������������������������0000644�0000000�0000000�00000002516�14673270174�012144� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1996, 1998, 2000, 2003, 2004, 2005, 2006, 2007 Auburn University ## Copyright (C) 2012 Lukas F. Reichlin <lukas.reichlin@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{z}, @var{p}, @var{k}] =} tf2zp (@var{num}, @var{den}) ## Convert transfer functions to poles-and-zero representations. ## ## Returns the zeros and poles of the system defined ## by @var{num}/@var{den}. ## @var{k} is a gain associated with the system zeros. ## @end deftypefn ## Author: A. S. Hodel <a.s.hodel@eng.auburn.edu> function [z, p, k] = tf2zp (varargin) if (nargin == 0) print_usage (); endif [z, p, k] = zpkdata (tf (varargin{:}), "vector"); endfunction ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/tfe.m�����������������������������������������������������������������������������0000644�0000000�0000000�00000004003�14673270174�011646� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[Pxx,freq] =} tfe(x,y,Nfft,Fs,window,overlap,range,plot_type,detrend) ## Estimate transfer function of system with input "x" and output "y". ## ## Use the Welch (1967) periodogram/FFT method. ## ## Compatible with Matlab R11 tfe and earlier. ## ## See "help pwelch" for description of arguments, hints and references ## --- especially hint (7) for Matlab R11 defaults. ## @end deftypefn function varargout = tfe(varargin) ## ## Check fixed argument if ( nargin<2 ) error( 'tfe: Need at least 2 args. Use help tfe.' ); endif nvarargin = length(varargin); ## remove any pwelch RESULT args and add 'trans' for iarg=1:nvarargin arg = varargin{iarg}; if ( ~isempty(arg) && ischar(arg) && ( strcmp(arg,'power') || ... strcmp(arg,'cross') || strcmp(arg,'trans') || ... strcmp(arg,'coher') || strcmp(arg,'ypower') )) varargin{iarg} = []; endif endfor varargin{nvarargin+1} = 'trans'; ## saved_compatib = pwelch('R11-'); if ( nargout==0 ) pwelch(varargin{:}); elseif ( nargout==1 ) Pxx = pwelch(varargin{:}); varargout{1} = Pxx; elseif ( nargout>=2 ) [Pxx,f] = pwelch(varargin{:}); varargout{1} = Pxx; varargout{2} = f; endif pwelch(saved_compatib); endfunction �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/tfestimate.m����������������������������������������������������������������������0000644�0000000�0000000�00000004523�14673270174�013244� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} tfestimate (@var{x}, @var{y}) ## @deftypefnx {Function File} {} tfestimate (@var{x}, @var{y}, @var{window}) ## @deftypefnx {Function File} {} tfestimate (@var{x}, @var{y}, @var{window}, @var{overlap}) ## @deftypefnx {Function File} {} tfestimate (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}) ## @deftypefnx {Function File} {} tfestimate (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}) ## @deftypefnx {Function File} {} tfestimate (@var{x}, @var{y}, @var{window}, @var{overlap}, @var{Nfft}, @var{Fs}, @var{range}) ## @deftypefnx {Function File} {[@var{Pxx}, @var{freq}] =} tfestimate (@dots{}) ## ## Estimate transfer function of system with input @var{x} and output @var{y}. ## Use the Welch (1967) periodogram/FFT method. ## @seealso{pwelch} ## @end deftypefn function varargout = tfestimate(varargin) ## ## Check fixed argument if (nargin < 2 || nargin > 7) print_usage (); endif nvarargin = length(varargin); ## remove any pwelch RESULT args and add 'cross' for iarg=1:nvarargin arg = varargin{iarg}; if ( ~isempty(arg) && ischar(arg) && ( strcmp(arg,'power') || ... strcmp(arg,'cross') || strcmp(arg,'trans') || ... strcmp(arg,'coher') || strcmp(arg,'ypower') )) varargin{iarg} = []; endif endfor varargin{nvarargin+1} = 'trans'; ## if ( nargout==0 ) pwelch(varargin{:}); elseif ( nargout==1 ) Pxx = pwelch(varargin{:}); varargout{1} = Pxx; elseif ( nargout>=2 ) [Pxx,f] = pwelch(varargin{:}); varargout{1} = Pxx; varargout{2} = f; endif endfunction �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/triang.m��������������������������������������������������������������������������0000644�0000000�0000000�00000004723�14673270174�012365� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000-2002 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} triang (@var{m}) ## ## Return the filter coefficients of a triangular window of length @var{m}. ## Unlike the Bartlett window, @code{triang} does not go to zero at the edges ## of the window. For odd @var{m}, @code{triang (@var{m})} is equal to ## @code{bartlett (@var{m} + 2)} except for the zeros at the edges of the ## window. ## @seealso{bartlett} ## @end deftypefn function w = triang (m) if (nargin != 1) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("triang: M must be a positive integer"); endif w = 1 - abs ([-(m-1):2:(m-1)]' / (m+rem(m,2))); endfunction %!assert (triang (1), 1) %!assert (triang (2), [1; 1]/2) %!assert (triang (3), [1; 2; 1]/2) %!assert (triang (4), [1; 3; 3; 1]/4) %!test %! x = bartlett (5); %! assert (triang (3), x(2:4)); %% Test input validation %!error triang () %!error triang (0.5) %!error triang (-1) %!error triang (ones (1, 4)) %!error triang (1, 2) %!demo %! subplot(221); %! n=7; k=(n-1)/2; t=[-k:0.1:k]/(k+1); %! plot(t,1-abs(t),";continuous;",[-k:k]/(k+1),triang(n),"g*;discrete;"); %! axis([-1, 1, 0, 1.3]); grid("on"); %! title("comparison with continuous for odd n"); %! %! subplot(222); %! n=8; k=(n-1)/2; t=[-k:0.1:k]/(k+1/2); %! plot(t,1+1/n-abs(t),";continuous;",[-k:k]/(k+1/2),triang(n),"g*;discrete;"); %! axis([-1, 1, 0, 1.3]); grid("on"); %! title("note the higher peak for even n"); %! %! subplot(223); %! n=7; %! plot(0:n+1,bartlett(n+2),"g-*;bartlett;",triang(n),"r-+;triang;"); %! axis; grid("off"); %! title("n odd, triang(n)==bartlett(n+2)"); %! %! subplot(224); %! n=8; %! plot(0:n+1,bartlett(n+2),"g-*;bartlett;",triang(n),"r-+;triang;"); %! axis; grid("off"); %! title("n even, triang(n)!=bartlett(n+2)"); ���������������������������������������������signal-1.4.6/inst/tripuls.m�������������������������������������������������������������������������0000644�0000000�0000000�00000006770�14673270174�012607� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2001 Paul Kienzle ## Copyright (C) 2018-2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} tripuls (@var{t}) ## @deftypefnx {Function File} {@var{y} =} tripuls (@var{t}, @var{w}) ## @deftypefnx {Function File} {@var{y} =} tripuls (@var{t}, @var{w}, @var{skew}) ## Generate a triangular pulse over the interval [-@var{w}/2,@var{w}/2), ## sampled at times @var{t}. This is useful with the function @code{pulstran} ## for generating a series of pulses. ## ## @var{skew} is a value between -1 and 1, indicating the relative placement ## of the peak within the width. -1 indicates that the peak should be ## at -@var{w}/2, and 1 indicates that the peak should be at @var{w}/2. The ## default value is 0. ## ## Example: ## @example ## @group ## fs = 11025; # arbitrary sample rate ## f0 = 100; # pulse train sample rate ## w = 0.3/f0; # pulse width 3/10th the distance between pulses ## plot (pulstran (0:1/fs:4/f0, 0:1/f0:4/f0, "tripuls", w)); ## @end group ## @end example ## ## @seealso{gauspuls, pulstran, rectpuls} ## @end deftypefn function y = tripuls (t, w = 1, skew = 0) if (nargin < 1 || nargin > 3) print_usage (); endif if (! isreal (w) || ! isscalar (w)) error ("tripuls: W must be a real scalar"); endif if (! isreal (skew) || ! isscalar (skew) || skew < -1 || skew > 1) error ("tripuls: SKEW must be a real scalar in the range [-1, 1]"); endif y = zeros (size (t)); peak = skew * w/2; idx = find ((t >= -w/2) & (t <= peak)); if (idx) y(idx) = (t(idx) + w/2) / (peak + w/2); endif idx = find ((t > peak) & (t < w/2)); if (idx) y(idx) = (t(idx) - w/2) / (peak - w/2); endif endfunction %!demo %! fs = 11025; # arbitrary sample rate %! f0 = 100; # pulse train sample rate %! w = 0.5/f0; # pulse width 1/10th the distance between pulses %! x = pulstran (0:1/fs:4/f0, 0:1/f0:4/f0, "tripuls", w); %! plot ([0:length(x)-1]*1000/fs, x); %! xlabel ("Time (ms)"); %! ylabel ("Amplitude"); %! title ("Triangular pulse train of 5 ms pulses at 10 ms intervals"); %!demo %! fs = 11025; # arbitrary sample rate %! f0 = 100; # pulse train sample rate %! w = 0.5/f0; # pulse width 1/10th the distance between pulses %! x = pulstran (0:1/fs:4/f0, 0:1/f0:4/f0, "tripuls", w, -0.5); %! plot ([0:length(x)-1]*1000/fs, x); %! xlabel ("Time (ms)"); %! ylabel ("Amplitude"); %! title ("Triangular pulse train of 5 ms pulses at 10 ms intervals, skew = -0.5"); %!assert (tripuls ([]), []) %!assert (tripuls ([], 0.1), []) %!assert (tripuls (zeros (10, 1)), ones (10, 1)) %!assert (tripuls (-1:1), [0, 1, 0]) %!assert (tripuls (-5:5, 9), [0, 1, 3, 5, 7, 9, 7, 5, 3, 1, 0] / 9) %!assert (tripuls (0:1/100:0.3, 0.1), tripuls ([0:1/100:0.3]', 0.1)') ## Test input validation %!error tripuls () %!error tripuls (1, 2, 3, 4) %!error tripuls (1, 2j) %!error tripuls (1, 2, 2) %!error tripuls (1, 2, -2) ��������signal-1.4.6/inst/tukeywin.m������������������������������������������������������������������������0000644�0000000�0000000�00000005224�14673270174�012755� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Laurent Mazet <mazet@crm.mot.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} tukeywin (@var{m}) ## @deftypefnx {Function File} {} tukeywin (@var{m}, @var{r}) ## Return the filter coefficients of a Tukey window (also known as the ## cosine-tapered window) of length @var{m}. @var{r} defines the ratio ## between the constant section and and the cosine section. It has to be ## between 0 and 1. The function returns a Hanning window for @var{r} ## equal to 1 and a rectangular window for @var{r} equal to 0. ## The default value of @var{r} is 1/2. ## ## For a definition of the Tukey window, see e.g. Fredric J. Harris, ## "On the Use of Windows for Harmonic Analysis with the Discrete Fourier ## Transform, Proceedings of the IEEE", Vol. 66, No. 1, January 1978, ## Page 67, Equation 38. ## @seealso{hanning} ## @end deftypefn function w = tukeywin (m, r = 1/2) if (nargin < 1 || nargin > 2) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("tukeywin: M must be a positive integer"); elseif (nargin == 2) ## check that 0 < r < 1 if r > 1 r = 1; elseif r < 0 r = 0; endif endif ## generate window switch r case 0, ## full box w = ones (m, 1); case 1, ## Hanning window w = hanning (m); otherwise ## cosine-tapered window t = linspace(0,1,m)(1:end/2)'; w = (1 + cos(pi*(2*t/r-1)))/2; w(floor(r*(m-1)/2)+2:end) = 1; w = [w; ones(mod(m,2)); flipud(w)]; endswitch endfunction %!demo %! m = 100; %! r = 1/3; %! w = tukeywin (m, r); %! title(sprintf("%d-point Tukey window, R = %d/%d", m, [p, q] = rat(r), q)); %! plot(w); %!assert (tukeywin (1), 1) %!assert (tukeywin (2), zeros (2, 1)) %!assert (tukeywin (3), [0; 1; 0]) %!assert (tukeywin (16, 0), rectwin (16)) %!assert (tukeywin (16, 1), hanning (16)) %% Test input validation %!error tukeywin () %!error tukeywin (0.5) %!error tukeywin (-1) %!error tukeywin (ones (1, 4)) %!error tukeywin (1, 2, 3) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/udecode.m�������������������������������������������������������������������������0000644�0000000�0000000�00000007141�14673270174�012506� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2014 Georgios Ouzounis <ouzounis_georgios@hotmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{out} =} udecode (@var{in}, @var{n}) ## @deftypefnx {Function File} {@var{out} =} udecode (@var{in}, @var{n}, @var{v}) ## @deftypefnx {Function File} {@var{out} =} udecode (@var{in}, @var{n}, @var{v}, @var{overflows}) ## Invert the operation of uencode. ## @seealso{uencode} ## @end deftypefn function out = udecode (in, n, v = 1, overflows = "saturate") if (nargin < 2 || nargin > 4) print_usage (); endif if (in != fix (in)) error ("udecode: IN must be matrix of integers"); endif if (n < 2 || n > 32 || n != fix (n)) error ("udecode: N must be an integer in the range [2, 32]"); endif if (v <= 0) error ("udecode: V must be a positive integer"); endif if (! (strcmp (overflows, "saturate") || strcmp (overflows, "wrap"))) error ("uencode: OVERFLOWS must be either \"saturate\" or \"wrap\""); endif if ( all (in >= 0)) signed = "unsigned"; lowerlevel = 0; upperlevel = (2 ^ n) - 1; else signed = "signed"; lowerlevel = - 2 ^ (n - 1); upperlevel = (2 ^ (n - 1)) - 1; endif if (strcmp (overflows, "saturate")) if (strcmp (signed, "unsigned")) in(in > upperlevel) = upperlevel; elseif (strcmp (signed, "signed")) in(in < lowerlevel) = lowerlevel; in(in > upperlevel) = upperlevel; endif elseif (strcmp (overflows, "wrap")) if (strcmp (signed, "unsigned")) idx = in > upperlevel; in(idx) = mod (in(idx), 2 ^ n); elseif (strcmp (signed, "signed")) idx = in < lowerlevel; in(idx) = mod (in(idx) + 2 ^ (n - 1), 2 ^ n) - 2 ^ (n - 1); idx = in > upperlevel; in(idx) = mod (in(idx) + 2 ^ (n - 1), 2 ^ n) - 2 ^ (n - 1); endif endif width = 2 * v / 2 ^ n; out = double (in) .* width; if (strcmp (signed, "unsigned")) out = out - v; endif endfunction %!test %! u = [0 0 0 0 0 1 2 3 3 3 3 3 3]; %! y = udecode(u, 2); %! assert(y, [-1 -1 -1 -1 -1 -0.5 0 0.5 0.5 0.5 0.5 0.5 0.5]); %!test %! u = [0 1 2 3 4 5 6 7 8 9 10]; %! y = udecode(u, 2, 1, "saturate"); %! assert(y, [-1 -0.5 0 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5]); %!test %! u = [0 1 2 3 4 5 6 7 8 9 10]; %! y = udecode(u, 2, 1, "wrap"); %! assert(y, [-1 -0.5 0 0.5 -1 -0.5 0 0.5 -1 -0.5 0]); %!test %! u = [-4 -3 -2 -1 0 1 2 3]; %! y = udecode(u, 3, 2); %! assert(y, [-2, -1.5 -1 -0.5 0 0.5 1 1.5]); %!test %! u = [-7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7]; %! y = udecode(u, 3, 2, "saturate"); %! assert(y, [-2 -2 -2 -2 -1.5 -1 -0.5 0 0.5 1 1.5 1.5 1.5 1.5 1.5]); %!test %! u = [-7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7]; %! y = udecode(u, 3, 2, "wrap"); %! assert(y, [0.5 1 1.5 -2 -1.5 -1 -0.5 0 0.5 1 1.5 -2 -1.5 -1 -0.5]); ## Test input validation %!error udecode () %!error udecode (1) %!error udecode (1, 2, 3, 4, 5) %!error udecode (1.5) %!error udecode (1, 100) %!error udecode (1, 4, 0) %!error udecode (1, 4, -1) %!error udecode (1, 4, 2, "invalid") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/uencode.m�������������������������������������������������������������������������0000644�0000000�0000000�00000005020�14673270174�012512� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2014 Georgios Ouzounis <ouzounis_georgios@hotmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{out} =} uencode (@var{in}, @var{n}) ## @deftypefnx {Function File} {@var{out} =} uencode (@var{in}, @var{n}, @var{v}) ## @deftypefnx {Function File} {@var{out} =} uencode (@var{in}, @var{n}, @var{v}, @var{signed}) ## Quantize the entries of the array @var{in} using 2^@var{n} quantization levels. ## @seealso{udecode} ## @end deftypefn function out = uencode (in, n, v = 1, signed = "unsigned") if (nargin < 2 || nargin > 4) print_usage (); endif if (n < 2 || n > 32 || n != fix (n)) error ("uencode: N must be an integer in the range [2, 32]"); endif if (v <= 0) error ("uencode: V must be a positive integer"); endif if (! (strcmp (signed, "signed") || strcmp (signed, "unsigned"))) error ("uencode: SIGNED must be either \"signed\" or \"unsigned\""); endif out = zeros (size (in)); width = 2 * v / 2 ^ n; out(in >= v) = (2 ^ n) - 1; idx = (in > -v) & (in < v); out(idx) = floor ((in(idx) + v) ./ width); if (strcmp (signed, "signed")) out = out - 2 ^ (n - 1); endif endfunction %!test %! u = [-3:0.5:3]; %! y = uencode (u, 2); %! assert (y, [0 0 0 0 0 1 2 3 3 3 3 3 3]); %!test %! u = [-4:0.5:4]; %! y = uencode (u, 3, 4); %! assert (y, [0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 7]); %!test %! u = [-8:0.5:8]; %! y = uencode(u, 4, 8, "unsigned"); %! assert (y, [0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 15]); %!test %! u = [-8:0.5:8]; %! y = uencode(u, 4, 8, "signed"); %! assert (y, [-8 -8 -7 -7 -6 -6 -5 -5 -4 -4 -3 -3 -2 -2 -1 -1 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 7]); ## Test input validation %!error uencode () %!error uencode (1) %!error uencode (1, 2, 3, 4, 5) %!error uencode (1, 100) %!error uencode (1, 4, 0) %!error uencode (1, 4, -1) %!error uencode (1, 4, 2, "invalid") ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/ultrwin.m�������������������������������������������������������������������������0000644�0000000�0000000�00000020257�14673270174�012605� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013 Rob Sykes <robs@users.sourceforge.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{w}, @var{xmu}] =} ultrwin (@var{m}, @var{mu}, @var{beta}) ## @deftypefnx {Function File} {[@var{w}, @var{xmu}] =} ultrwin (@var{m}, @var{mu}, @var{att}, "att") ## @deftypefnx {Function File} {[@var{w}, @var{xmu}] =} ultrwin (@var{m}, @var{mu}, @var{latt}, "latt") ## @deftypefnx {Function File} {@var{w} =} ultrwin (@var{m}, @var{mu}, @var{xmu}, "xmu") ## Return the coefficients of an Ultraspherical window of length @var{m}. ## The parameter @var{mu} controls the window's Fourier transform's side-lobe ## to side-lobe ratio, and the third given parameter controls the transform's ## main-lobe width/side-lobe-ratio; normalize @var{w} such that the central ## coefficient(s) value is unitary. ## ## By default, the third parameter is @var{beta}, which sets the main lobe width ## to @var{beta} times that of a rectangular window. Alternatively, giving ## @var{att} or @var{latt} sets the ripple ratio at the first or last side-lobe ## respectively, or giving @var{xmu} sets the (un-normalized) window's Fourier ## transform according to its canonical definition: ## ## @verbatim ## (MU) ## W(k) = C [ XMU cos(pi k/M) ], k = 0, 1, ..., M-1, ## M-1 ## @end verbatim ## ## where C is the Ultraspherical (a.k.a. Gegenbauer) polynomial, which can be ## defined using the recurrence relationship: ## ## @verbatim ## (l) 1 (l) (l) ## C (x) = - [ 2x(m + l - 1) C (x) - (m + 2l - 2) C (x) ] ## m m m-1 m-2 ## ## (l) (l) ## for m an integer > 1, and C (x) = 1, C (x) = 2lx. ## 0 1 ## @end verbatim ## ## For given @var{beta}, @var{att}, or @var{latt}, the corresponding ## (determined) value of @var{xmu} is also returned. ## ## The Dolph-Chebyshev and Saramaki windows are special cases of the ## Ultraspherical window, with @var{mu} set to 0 and 1 respectively. Note that ## when not giving @var{xmu}, stability issues may occur with @var{mu} <= -1.5. ## For further information about the window, see ## ## @itemize @bullet ## @item ## Kabal, P., 2009: Time Windows for Linear Prediction of Speech. ## Technical Report, Dept. Elec. & Comp. Eng., McGill University. ## @item ## Bergen, S., Antoniou, A., 2004: Design of Ultraspherical Window ## Functions with Prescribed Spectral Characteristics. Proc. JASP, 13/13, ## pp. 2053-2065. ## @item ## Streit, R., 1984: A two-parameter family of weights for nonrecursive ## digital filters and antennas. Trans. ASSP, 32, pp. 108-118. ## @end itemize ## @seealso{chebwin, kaiser} ## @end deftypefn function [w, xmu] = ultrwin (m, mu, par, key = "beta", norm = 0) ## This list of parameter types must be kept in sync with the enum order. types = {"xmu", "beta", "att", "latt"}; type = []; if (ischar (key)) type = find (strncmpi (key, types, numel (key))); endif if (nargin < 3 || nargin > 5) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("ultrwin: M must be a positive integer"); elseif (! (isscalar (mu) && isreal (mu))) error ("ultrwin: MU must be a real scalar"); elseif (! ischar (key)) error ("ultrwin: parameter type must be a string"); elseif (isempty (type)) error ("ultrwin: invalid parameter type '%s'", key); elseif (! (isscalar (par) && isreal (par))) error (["ultrwin: ", upper (types(type)), " must be a real scalar"]); elseif (! (isscalar (norm) && norm == fix (norm) && norm >= 0)) # Alt. norms; WIP error ("ultrwin: NORM must be a non-negative integer"); endif [w, xmu] = __ultrwin__(m, mu, par, type-1, norm); endfunction %!test %! assert(ultrwin(100, 1, 1), ones(100, 1), 1e-14); %!test %! L = 201; xmu = 1.01; m = L-1; %! for mu = -1.35:.3:1.35 %! x = xmu*cos([0:m]*pi/L); %! C(2,:) = 2*mu*x; C(1,:) = 1; %! for k = 2:m; C(k+1,:) = 2*(k+mu-1)/k*x.*C(k,:) - (k+2*mu-2)/k*C(k-1,:); end %! b = real(ifft(C(m+1,:))); b = b(m/2+2:L)/b(1); %! assert(ultrwin(L, mu, xmu, "x")', [b 1 fliplr(b)], 1e-12); %! end %!test %! b = [ %! 5.7962919401511820e-03 %! 1.6086991349967078e-02 %! 3.6019014684117417e-02 %! 6.8897525451558125e-02 %! 1.1802364384553447e-01 %! 1.8566749737411145e-01 %! 2.7234740630826737e-01 %! 3.7625460141456091e-01 %! 4.9297108901880221e-01 %! 6.1558961695849457e-01 %! 7.3527571856983598e-01 %! 8.4222550739092694e-01 %! 9.2688779484512085e-01 %! 9.8125497127708561e-01]'; %! [w xmu] = ultrwin(29, 0, 3); %! assert(w', [b 1 fliplr(b)], 1e-14); %! assert(xmu, 1.053578297819277, 1e-14); %!test %! b = [ %! 2.9953636903962466e-02 %! 7.6096450051659603e-02 %! 1.5207129867916891e-01 %! 2.5906995366355179e-01 %! 3.9341065451220536e-01 %! 5.4533014012036929e-01 %! 6.9975915071207051e-01 %! 8.3851052636906720e-01 %! 9.4345733548690369e-01]'; %! assert(ultrwin(20, .5, 50, "a")', [b 1 1 fliplr(b)], 1e-14); %!test %! b = [ %! 1.0159906492322712e-01 %! 1.4456358609406283e-01 %! 2.4781689516201011e-01 %! 3.7237015168857646e-01 %! 5.1296973026690407e-01 %! 6.5799041448113671e-01 %! 7.9299087042967320e-01 %! 9.0299778924260576e-01 %! 9.7496213649820296e-01]'; %! assert(ultrwin(19, -.4, 40, "l")', [b 1 fliplr(b)], 1e-14); %!demo %! w=ultrwin(120, -1, 40, "l"); [W,f]=freqz(w); clf %! subplot(2,1,1); plot(f/pi, 20*log10(W/abs(W(1)))); grid; axis([0 1 -90 0]) %! subplot(2,1,2); plot(0:length(w)-1, w); grid %! %----------------------------------------------------------- %! % Figure shows an Ultraspherical window with MU=-1, LATT=40: %! % frequency domain above, time domain below. %!demo %! c="krbm"; clf; subplot(2, 1, 1) %! for beta=2:5 %! w=ultrwin(80, -.5, beta); [W,f]=freqz(w); %! plot(f/pi, 20*log10(W/abs(W(1))), c(1+mod(beta, length(c)))); hold on %! end; grid; axis([0 1 -140 0]); hold off %! subplot(2, 1, 2); %! for n=2:10 %! w=ultrwin(n*20, 1, 3); [W,f]=freqz(w,1,2^11); %! plot(f/pi, 20*log10(W/abs(W(1))), c(1+mod(n, length(c)))); hold on %! end; grid; axis([0 .2 -100 0]); hold off %! %-------------------------------------------------- %! % Figure shows transfers of Ultraspherical windows: %! % above: varying BETA with fixed N & MU, %! % below: varying N with fixed MU & BETA. %!demo %! c="krbm"; clf; subplot(2, 1, 1) %! for j=0:4 %! w=ultrwin(80, j*.6-1.2, 50, "a"); [W,f]=freqz(w); %! plot(f/pi, 20*log10(W/abs(W(1))), c(1+mod(j, length(c)))); hold on %! end; grid; axis([0 1 -100 0]); hold off %! subplot(2, 1, 2); %! for j=4:-1:0 %! w=ultrwin(80, j*.75-1.5, 50, "l"); [W,f]=freqz(w); %! plot(f/pi, 20*log10(W/abs(W(1))), c(1+mod(j, length(c)))); hold on %! end; grid; axis([0 1 -100 0]); hold off %! %-------------------------------------------------- %! % Figure shows transfers of Ultraspherical windows: %! % above: varying MU with fixed N & ATT, %! % below: varying MU with fixed N & LATT. %!demo %! clf; a=[.8 2 -115 5]; fc=1.1/pi; l="labelxy"; %! for k=1:3; switch (k); case 1; w=kaiser(L=159, 7.91); %! case 2; w=ultrwin(L=165, 0, 2.73); case 3; w=ultrwin(L=153, .5, 2.6); end %! subplot(3, 1, 4-k); f=[1:(L-1)/2]*pi;f=sin(fc*f)./f; f=[fliplr(f) fc f]'; %! [h,f]=freqz(w.*f,1,2^14); plot(f,20*log10(h)); grid; axis(a,l); l="labely"; %! end %! %----------------------------------------------------------- %! % Figure shows example lowpass filter design (Fp=1, Fs=1.2 %! % rad/s, att=80 dB) and comparison with other windows. From %! % top to bottom: Ultraspherical, Dolph-Chebyshev, and Kaiser %! % windows, with lengths 153, 165, and 159 respectively. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/unshiftdata.m���������������������������������������������������������������������0000644�0000000�0000000�00000004310�14673270174�013403� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2014 Georgios Ouzounis <ouzounis_georgios@hotmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{out}] =} unshiftdata (@var{in}, @var{perm}, @var{shifts}) ## Reverse what is done by shiftdata. ## @seealso{shiftdata} ## @end deftypefn function out = unshiftdata (in, perm, shifts) if (nargin != 3) print_usage (); endif if (! isempty (perm)) if (perm != fix (perm)) error ("unshiftdata: PERM must be a vector of integers"); endif dim = perm(1); elseif (! isempty (shifts)) if (shifts != fix (shifts)) error ("unshiftdata: SHIFTS must be an integer"); endif dim = shifts + 1; else error ("unshiftdata: Either PERM or SHIFTS must not be empty"); endif out = ipermute (in, [dim 1: (dim - 1) (dim + 1): (length (size (in)))]); endfunction %!test %! x = 1:5; %! [y, perm, shifts] = shiftdata (x); %! x2 = unshiftdata (y, perm, shifts); %! assert (x, x2); %!test %! X = fix (rand (3, 3) * 100); %! [Y, perm, shifts] = shiftdata (X, 2); %! X2 = unshiftdata (Y, perm, shifts); %! assert (X, X2); %!test %! X = fix (rand (4, 4, 4, 4) * 100); %! [Y, perm, shifts] = shiftdata (X, 3); %! X2 = unshiftdata (Y, perm, shifts); %! assert (X, X2); %!test %! X = fix (rand (1, 1, 3, 4) * 100); %! [Y, perm, shifts] = shiftdata (X); %! X2 = unshiftdata (Y, perm, shifts); %! assert (X, X2); ## Test input validation %!error unshiftdata () %!error unshiftdata (1, 2) %!error unshiftdata (1, 2, 3, 4) %!error unshiftdata (1, 2.5) %!error unshiftdata (1, [], 2.5) %!error unshiftdata (1, [], []) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/upsample.m������������������������������������������������������������������������0000644�0000000�0000000�00000002422�14673270174�012721� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Author: Paul Kienzle <pkienzle@users.sf.net> (2007) ## This program is granted to the public domain. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} upsample (@var{x}, @var{n}) ## @deftypefnx {Function File} {@var{y} =} upsample (@var{x}, @var{n}, @var{offset}) ## Upsample the signal, inserting @var{n}-1 zeros between every element. ## ## If @var{x} is a matrix, upsample every column. ## ## If @var{offset} is specified, control the position of the inserted sample in ## the block of @var{n} zeros. ## @seealso{decimate, downsample, interp, resample, upfirdn} ## @end deftypefn function y = upsample (x, n, phase = 0) if nargin<2 || nargin>3, print_usage; endif if phase > n - 1 warning("This is incompatible with Matlab (phase = 0:n-1). See octave-forge signal package release notes for details." ) endif [nr,nc] = size(x); if any([nr,nc]==1), y = zeros(n*nr*nc,1); y(phase + 1:n:end) = x; if nr==1, y = y.'; endif else y = zeros(n*nr,nc); y(phase + 1:n:end,:) = x; endif endfunction %!assert(upsample([1,3,5],2),[1,0,3,0,5,0]); %!assert(upsample([1;3;5],2),[1;0;3;0;5;0]); %!assert(upsample([1,2;5,6;9,10],2),[1,2;0,0;5,6;0,0;9,10;0,0]); %!assert(upsample([2,4],2,1),[0,2,0,4]); %!assert(upsample([3,4;7,8],2,1),[0,0;3,4;0,0;7,8]); ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/upsamplefill.m��������������������������������������������������������������������0000644�0000000�0000000�00000005374�14673270174�013601� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013 Juan Pablo Carbajal ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} upsamplefill (@var{x}, @var{v}) ## @deftypefnx {Function File} {@var{y} =} upsamplefill (@dots{}, @var{copy}) ## Upsamples a vector interleaving given values or copies of the vector elements. ## ## The values in the vector @var{v} are placed between the elements of @var{x}. ## ## If the optional argument @var{copy} is @var{true} then @var{v} should be a ## scalar and each value in @var{x} are repeat @var{v} times. ## ## Example: ## @example ## @group ## upsamplefill (eye (2), 2, true) ## @result{} 1 0 ## 1 0 ## 1 0 ## 0 1 ## 0 1 ## 0 1 ## upsamplefill (eye (2), [-1 -1 -1]) ## @result{} 1 0 ## -1 -1 ## -1 -1 ## -1 -1 ## 0 1 ## -1 -1 ## -1 -1 ## -1 -1 ## @end group ## @end example ## ## @seealso{upsample} ## @end deftypefn ## Author: Juan Pablo Carbajal <ajuanpi+dev@gmail.com> function y = upsamplefill (x, v, copy=false) if nargin<2 print_usage; end [nr,nc] = size (x); if copy if any ([nr,nc]==1) y = kron (x(:), ones(v+1,1)); if nr == 1 y = y.'; endif else y = kron (x, ones(v+1,1)); endif return else % Assumes 'v' row or column vector n = length(v) + 1; N = n*nr; if any ([nr,nc]==1) N = N*nc; idx = 1:n:N; idx_c = setdiff (1:N, 1:n:N); y = zeros (N,1); y(idx) = x; y(idx_c) = repmat (v(:), max(nr,nc), 1); if nr == 1 y = y.'; endif else idx = 1:n:N; idx_c = setdiff(1:N,1:n:N); y = zeros (N,nc); y(idx,:) = x; y(idx_c,:) = repmat (v(:), nr, nc); endif endif endfunction %!assert(upsamplefill([1,3,5],2),[1,2,3,2,5,2]); %!assert(upsamplefill([1;3;5],2),[1;2;3;2;5;2]); %!assert(upsamplefill([1,2,5],[2 -2]),[1,2,-2,2,2,-2,5,2,-2]); %!assert(upsamplefill(eye(2),2,true),[1,0;1,0;1,0;0,1;0,1;0,1]); %!assert(upsamplefill([1,3,5],2,true),[1,1,1,3,3,3,5,5,5]); %!assert(upsamplefill([1;3;5],2,true),[1;1;1;3;3;3;;5;5;5]); ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/vco.m�����������������������������������������������������������������������������0000644�0000000�0000000�00000005736�14673270174�011675� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2019-2023 The Octave Project Developers ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {} {y =} vco (@var{x}, @var{fc}, @var{fs}) ## @deftypefnx {} {y =} vco (@var{x}, [@var{fmin}, @var{fmax}], @var{fs}) ## Creates a signal that oscillates at a frequency determined by input @var{x} with a sampling frequency @var{fs}. ## ## Inputs: ## @itemize ## @item ## @var{x} - input data with a range of -1 to 1. A value of -1 means no output, 0 cuoreesponds to @var{fc}, ## and 1 corresponds to 2*@var{fc}. ## ## @item ## @var{fc} - Carrier frequency ## ## @item ## @var{fs} - Sampling rate ## ## @item ## @var{fmin}, @var{fmax} - Frequency modulation range limits. ## @end itemize ## ## Outputs: ## @itemize ## @item ## @var{y} - output signal ## @end itemize ## @end deftypefn function [y,yn] = vco (x, fc = [], fs = []) if (nargin < 1 || nargin > 3) print_usage (); endif ## We can't just set default values in parameter list because ## default FC depends on value of FS and empty arguments may be ## used to request default values. if (isvector (x) && rows (x) == 1) x = x(:); endif if (any (x(:) > 1 | x(:) < -1)) error ("vco: values in X must be in the range [-1, 1]"); endif if (isempty (fs)) fs = 1; endif if (isempty (fc)) fc = fs / 4; endif x_max = max (max (abs (x))); if (numel (fc) == 2) fmin = fc(1); fmax = fc(2); if (fmin > fs/2 || fmax > fs/2) error ("vco: FMIN and FMAX must be less than FS/2"); endif if (fmin >= fmax) error ("vco: FMAX must be greater than FMIN"); endif if (fmin < 0 || fmax < 0) error ("vco: FMIN and FMAX must be positive values"); endif ## I don't know whether this is the best way, but I think it gives ## the proper value for fc and the proper deviation (+/-) from ## that value. fc = (fmin + fmax) / 2; kf = (fmax - fmin) / 2 / fs * 2 * pi / x_max; elseif (isscalar (fc)) kf = (fc / fs) * 2 * pi / x_max; else error ("vco: FC must be a scalar"); endif if (! (isscalar (fs))) error ("vco: FS must be a scalar"); endif ## Note, no need to generate a matrix for T, we can rely on ## broadcasting instead. len = rows (x); t = (0 : (1/fs) : ((len-1)/fs))'; ## Use modulate instead? y = cos (2*pi*fc*t + kf*cumsum (x)); endfunction %!error vco %!error vco([1 2]) ����������������������������������signal-1.4.6/inst/wconv.m���������������������������������������������������������������������������0000644�0000000�0000000�00000003412�14673270174�012227� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2013 Lukas F. Reichlin ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} wconv (@var{type}, @var{x}, @var{f}) ## @deftypefnx {Function File} {@var{y} =} wconv (@var{type}, @var{x}, @var{f}, @var{shape}) ## 1-D or 2-D convolution. ## ## @strong{Inputs} ## @table @var ## @item type ## Type of convolution. ## @item x ## Signal vector or matrix. ## @item f ## Coefficients of @acronym{FIR} filter. ## @item shape ## Shape. ## @end table ## ## @strong{Outputs} ## @table @var ## @item y ## Convoluted signal. ## @end table ## @end deftypefn ## Author: Lukas Reichlin <lukas.reichlin@gmail.com> ## Created: April 2013 ## Version: 0.1 function y = wconv (type, x, f, shape = "full") if (nargin < 3 || nargin > 4) print_usage (); endif switch (type(1)) case {1, "1"} y = conv2 (x(:).', f(:).', shape); if (rows (x) > 1) y = y.'; endif case {2, "2"} y = conv2 (x, f, shape); case "r" y = conv2 (x, f(:).', shape); case "c" y = conv2 (x.', f(:).', shape); y = y.'; otherwise print_usage (); endswitch endfunction ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/welchwin.m������������������������������������������������������������������������0000644�0000000�0000000�00000007351�14673270174�012721� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2007 Muthiah Annamalai <muthiah.annamalai@uta.edu> ## Copyright (C) 2008-2009 Mike Gross <mike@appl-tech.com> ## Copyright (C) 2008-2009 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} welchwin (@var{m}) ## @deftypefnx {Function File} {} welchwin (@var{m}, "periodic") ## @deftypefnx {Function File} {} welchwin (@var{m}, "symmetric") ## Return the filter coefficients of a Welch window of length @var{m}. The ## Welch window is given by ## @var{w}(n)=1-(n/N-1)^2, n=[0,1, ... @var{m}-1]. ## The optional argument specifies a "symmetric" window (the default) or a ## "periodic" window. ## ## A symmetric window has zero at each end and maximum in the middle, and the ## length must be an integer greater than 2. The variable @var{N} in the ## formula above is @code{(@var{m}-1)/2}. ## ## A periodic window wraps around the cyclic interval [0,1, ... @var{m}-1], ## and is intended for use with the DFT. The length must be an integer ## greater than 1. The variable @var{N} in the formula above is ## @code{@var{m}/2}. ## ## @seealso{blackman, kaiser} ## @end deftypefn function w = welchwin (m, opt) if (nargin < 1 || nargin > 2) print_usage (); elseif (! (isscalar (m) && (m == fix (m)) && (m > 0))) error ("welchwin: M must be a positive integer"); endif N = (m - 1) / 2; mmin = 3; if (nargin == 2) switch (opt) case "periodic" N = m / 2; mmin = 2; case "symmetric" N = (m - 1) / 2; otherwise error ("welchwin: window type must be either \"periodic\" or \"symmetric\""); endswitch endif ## Periodic window is not properly defined for m < 2. ## Symmetric window is not properly defined for m < 3. if (m < mmin) error ("welchwin: M must be an integer greater than %d", mmin); endif n = [0:m-1]'; w = 1 - ((n-N)./N).^2; endfunction %!demo %! m = 32; %! t = [0:m-1]; %! printf ("Graph: single period of "); %! printf ("%d-point periodic (blue) and symmetric (red) windows\n", m); %! xp = welchwin (m, "periodic"); %! xs = welchwin (m, "symmetric"); %! plot (t, xp, "b", t, xs, "r") %!demo %! m = 32; %! t = [0:4*m-1]; %! printf ("Graph: 4 periods of "); %! printf ("%d-point periodic (blue) and symmetric (red) windows\n", m); %! xp = welchwin (m, "periodic"); %! xs = welchwin (m, "symmetric"); %! xp2 = repmat (xp, 4, 1); %! xs2 = repmat (xs, 4, 1); %! plot (t, xp2, "b", t, xs2, "r") %!demo %! m = 32; %! n = 512; %! xp = welchwin (m, "periodic"); %! s = fftshift (max (1e-2, abs (fft (postpad (xp, n))))); %! f = [-0.5:1/n:0.5-1/n]; %! printf ("%dx null-padded, power spectrum of %d-point window\n", n/m, m); %! semilogy (f, s) %!assert (welchwin (3), [0; 1; 0]); %!assert (welchwin (15), flipud (welchwin (15))); %!assert (welchwin (16), flipud (welchwin (16))); %!assert (welchwin (15), welchwin (15, "symmetric")); %!assert (welchwin (16)(1:15), welchwin (15, "periodic")); %% Test input validation %!error welchwin () %!error welchwin (0.5) %!error welchwin (-1) %!error welchwin (ones (1, 4)) %!error welchwin (1, 2, 3) %!error welchwin (1, "invalid") ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/window.m��������������������������������������������������������������������������0000644�0000000�0000000�00000003213�14673270174�012401� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2008 David Bateman ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{w} =} window (@var{f}, @var{m}) ## @deftypefnx {Function File} {@var{w} =} window (@var{f}, @var{m}, @var{opts}) ## Create an @var{m}-point window from the function @var{f}. The function ## @var{f} can be for example @code{@@blackman}. Any additional ## arguments @var{opt} are passed to the windowing function. ## @end deftypefn function wout = window (f, m, varargin) if (nargin == 0) error ("window: UI tool not supported"); elseif (nargin < 2) print_usage (); else w = feval (f, m, varargin{:}); if (nargout > 0) wout = w; endif endif endfunction %!assert (window (@bartlett, 16), window ("bartlett", 16)) %!assert (window (@hamming, 16), window ("hamming", 16)) %!assert (window (@hanning, 16), window ("hanning", 16)) %!assert (window (@triang, 16), window ("triang", 16)) %% Test input validation %!error window () %!error window (1) %!error window ("hanning") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/wkeep.m���������������������������������������������������������������������������0000644�0000000�0000000�00000003623�14673270174�012212� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2008 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} wkeep (@var{x}, @var{l}) ## @deftypefnx {Function File} {@var{y} =} wkeep (@var{x}, @var{l}, @var{opt}) ## Extract the elements of @var{x} of size @var{l} from the center, the right ## or the left. ## @end deftypefn function y = wkeep(x,l,opt = 'c') if (nargin < 2|| nargin > 3); print_usage; endif if(isvector(x)) if(l > length(x)) error('l must be or equal the size of x'); endif if(opt=='c') s = (length(x)-l)./2; y = x(1+floor(s):end-ceil(s)); elseif(opt=='l') y=x(1:l); elseif(opt=='r') y = x(end-l+1:end); else error('opt must be equal to c, l or r'); endif else if(length(l) == 2) s1 = (length(x)-l(1))./2; s2 = (length(x)-l(2))./2; else error('For a matrix l must be a 1x2 vector'); endif if(nargin==2) y = x(1+floor(s1):end-ceil(s1),1+floor(s2):end-ceil(s2)); else if(length(opt) == 2) firstr=opt(1); firstc=opt(2); else error('For a matrix l must be a 1x2 vector'); endif y=x(firstr:firstr+l(1)-1,firstc:firstc+l(2)-1); endif endif endfunction �������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/wrev.m����������������������������������������������������������������������������0000644�0000000�0000000�00000002134�14673270174�012056� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2008 Sylvain Pelissier <sylvain.pelissier@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} wrev (@var{x}) ## Reverse the order of the element of the vector @var{x}. ## @seealso{flipud, fliplr} ## @end deftypefn function y = wrev(x) if (nargin < 1|| nargin > 1); print_usage; endif if(~isvector(x)) error('x must be a vector'); endif l = length(x); k = 0:l-1; y = x(l-k); endfunction ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/xcorr.m���������������������������������������������������������������������������0000644�0000000�0000000�00000032237�14673270174�012237� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999-2001 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2004 <asbjorn.sabo@broadpark.no> ## Copyright (C) 2008, 2010 Peter Lanspeary <peter.lanspeary@.adelaide.edu.au> ## Copyright (C) 2022 Octave-Forge community <maintainers@octave.org> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{R}, @var{lag}] =} xcorr ( @var{X} ) ## @deftypefnx {Function File} {@dots{} =} xcorr ( @var{X}, @var{Y} ) ## @deftypefnx {Function File} {@dots{} =} xcorr ( @dots{}, @var{maxlag}) ## @deftypefnx {Function File} {@dots{} =} xcorr ( @dots{}, @var{scale}) ## Estimates the cross-correlation. ## ## Estimate the cross correlation R_xy(k) of vector arguments @var{X} and @var{Y} ## or, if @var{Y} is omitted, estimate autocorrelation R_xx(k) of vector @var{X}, ## for a range of lags k specified by argument "maxlag". If @var{X} is a ## matrix, each column of @var{X} is correlated with itself and every other ## column. ## ## The cross-correlation estimate between vectors "x" and "y" (of ## length N) for lag "k" is given by ## ## @tex ## $$ R_{xy}(k) = \sum_{i=1}^{N} x_{i+k} \overline{y_i}, $$ ## @end tex ## @ifnottex ## @example ## @group ## N ## R_xy(k) = sum x_@{i+k@} conj(y_i), ## i=1 ## @end group ## @end example ## @end ifnottex ## ## where data not provided (for example x(-1), y(N+1)) is zero. Note the ## definition of cross-correlation given above. To compute a ## cross-correlation consistent with the field of statistics, see @command{xcov}. ## ## @strong{ARGUMENTS} ## @table @var ## @item X ## [non-empty; real or complex; vector or matrix] data ## ## @item Y ## [real or complex vector] data ## ## If @var{X} is a matrix (not a vector), @var{Y} must be omitted. ## @var{Y} may be omitted if @var{X} is a vector; in this case xcorr ## estimates the autocorrelation of @var{X}. ## ## @item maxlag ## [integer scalar] maximum correlation lag ## If omitted, the default value is N-1, where N is the ## greater of the lengths of @var{X} and @var{Y} or, if @var{X} is a matrix, ## the number of rows in @var{X}. ## ## @item scale ## [character string] specifies the type of scaling applied ## to the correlation vector (or matrix). is one of: ## @table @samp ## @item none ## return the unscaled correlation, R, ## @item biased ## return the biased average, R/N, ## @item unbiased ## return the unbiased average, R(k)/(N-|k|), ## @item coeff or normalized ## return the correlation coefficient, R/(rms(x).rms(y)), ## where "k" is the lag, and "N" is the length of @var{X}. ## If omitted, the default value is "none". ## If @var{Y} is supplied but does not have the same length as @var{X}, ## scale must be "none". ## @end table ## @end table ## ## @strong{RETURNED VARIABLES} ## @table @var ## @item R ## array of correlation estimates ## @item lag ## row vector of correlation lags [-maxlag:maxlag] ## @end table ## ## The array of correlation estimates has one of the following forms: ## (1) Cross-correlation estimate if @var{X} and @var{Y} are vectors. ## ## (2) Autocorrelation estimate if is a vector and @var{Y} is omitted. ## ## (3) If @var{X} is a matrix, R is an matrix containing the cross-correlation ## estimate of each column with every other column. Lag varies with the first ## index so that R has 2*maxlag+1 rows and P^2 columns where P is the number of ## columns in @var{X}. ## ## If Rij(k) is the correlation between columns i and j of @var{X} ## ## @code{R(k+maxlag+1,P*(i-1)+j) == Rij(k)} ## ## for lag k in [-maxlag:maxlag], or ## ## @code{R(:,P*(i-1)+j) == xcorr(X(:,i),X(:,j))}. ## ## @code{reshape(R(k,:),P,P)} is the cross-correlation matrix for @code{X(k,:)}. ## ## @seealso{xcov} ## @end deftypefn ## The cross-correlation estimate is calculated by a "spectral" method ## in which the FFT of the first vector is multiplied element-by-element ## with the FFT of second vector. The computational effort depends on ## the length N of the vectors and is independent of the number of lags ## requested. If you only need a few lags, the "direct sum" method may ## be faster: ## ## Ref: Stearns, SD and David, RA (1988). Signal Processing Algorithms. ## New Jersey: Prentice-Hall. ## unbiased: ## ( hankel(x(1:k),[x(k:N); zeros(k-1,1)]) * y ) ./ [N:-1:N-k+1](:) ## biased: ## ( hankel(x(1:k),[x(k:N); zeros(k-1,1)]) * y ) ./ N ## ## If length(x) == length(y) + k, then you can use the simpler ## ( hankel(x(1:k),x(k:N-k)) * y ) ./ N function [R, lags] = xcorr (X, varargin) if (nargin < 1 || nargin > 4) print_usage; endif ## assign optional arguments according to data type maxlag=[]; scale=[]; Y=[]; for idx=1:length(varargin) arg = varargin{idx}; if ischar(arg) if isempty(scale) scale = arg; else error ("xcorr: unexpected char value '%s' when scale is already set to '%s'", arg, scale); endif elseif isscalar(arg) if isempty(maxlag) maxlag = arg; else error ("xcorr: unexpected scalar value '%f' when maxlag is already set to '%f'", arg, maxlag); endif elseif idx == 1 Y = arg; elseif (! isempty (arg)) error ("xcorr: unknown optional input variable at position %d", idx); endif endfor ## assign defaults to missing arguments if isvector(X) ## if isempty(Y), Y=X; endif ## this line disables code for autocorr'n N = max(length(X),length(Y)); else N = rows(X); endif if isempty(maxlag), maxlag=N-1; endif if isempty(scale), scale='none'; endif ## check argument values if isempty(X) || isscalar(X) || ! ismatrix(X) error("xcorr: X must be a vector or matrix"); endif if isscalar(Y) || ischar(Y) || (!isempty(Y) && !isvector(Y)) error("xcorr: Y must be a vector"); endif if !isempty(Y) && !isvector(X) error("xcorr: X must be a vector if Y is specified"); endif if !isscalar(maxlag) || !isreal(maxlag) || maxlag<0 || fix(maxlag)!=maxlag error("xcorr: maxlag must be a single non-negative integer"); endif ## ## sanity check on number of requested lags ## Correlations for lags in excess of +/-(N-1) ## (a) are not calculated by the FFT algorithm, ## (b) are all zero; so provide them by padding ## the results (with zeros) before returning. if (maxlag > N-1) pad_result = maxlag - (N - 1); maxlag = N - 1; %error("xcorr: maxlag must be less than length(X)"); else pad_result = 0; endif if isvector(X) && isvector(Y) && length(X) != length(Y) && ... !strcmp(scale,'none') error("xcorr: scale must be 'none' if length(X) != length(Y)") endif P = columns(X); M = 2^nextpow2(N + maxlag); if !isvector(X) ## For matrix X, correlate each column "i" with all other "j" columns R = zeros(2*maxlag+1,P^2); ## do FFTs of padded column vectors pre = fft (postpad (prepad (X, N+maxlag), M) ); post = conj (fft (postpad (X, M))); ## do autocorrelations (each column with itself) ## -- if result R is reshaped to 3D matrix (i.e. R=reshape(R,M,P,P)) ## the autocorrelations are on leading diagonal columns of R, ## where i==j in R(:,i,j) cor = ifft (post .* pre); R(:, 1:P+1:P^2) = cor (1:2*maxlag+1,:); ## do the cross correlations ## -- these are the off-diagonal column of the reshaped 3D result ## matrix -- i!=j in R(:,i,j) for i=1:P-1 j = i+1:P; cor = ifft( pre(:,i*ones(length(j),1)) .* post(:,j) ); R(:,(i-1)*P+j) = cor(1:2*maxlag+1,:); R(:,(j-1)*P+i) = conj( flipud( cor(1:2*maxlag+1,:) ) ); endfor elseif isempty(Y) ## compute autocorrelation of a single vector post = fft( postpad(X(:),M) ); cor = ifft( post .* conj(post) ); R = [ conj(cor(maxlag+1:-1:2)) ; cor(1:maxlag+1) ]; else ## compute cross-correlation of X and Y ## If one of X & Y is a row vector, the other can be a column vector. pre = fft( postpad( prepad( X(:), length(X)+maxlag ), M) ); post = fft( postpad( Y(:), M ) ); cor = ifft( pre .* conj(post) ); R = cor(1:2*maxlag+1); endif ## if inputs are real, outputs should be real, so ignore the ## insignificant complex portion left over from the FFT if isreal(X) && (isempty(Y) || isreal(Y)) R=real(R); endif ## correct for bias if strcmp(scale, 'biased') R = R ./ N; elseif strcmp(scale, 'unbiased') R = R ./ ( [ N-maxlag:N-1, N, N-1:-1:N-maxlag ]' * ones(1,columns(R)) ); elseif strcmp(scale, 'coeff') || strcmp(scale, 'normalized') ## R = R ./ R(maxlag+1) works only for autocorrelation ## For cross correlation coeff, divide by rms(X)*rms(Y). if !isvector(X) ## for matrix (more than 1 column) X rms = sqrt( sumsq(X) ); R = R ./ ( ones(rows(R),1) * reshape(rms.'*rms,1,[]) ); elseif isempty(Y) ## for autocorrelation, R(zero-lag) is the mean square. R = R / R(maxlag+1); else ## for vectors X and Y R = R / sqrt( sumsq(X)*sumsq(Y) ); endif elseif !strcmp(scale, 'none') error("xcorr: scale must be 'biased', 'unbiased', 'coeff' or 'none'"); endif ## Pad result if necessary ## (most likely is not required, use "if" to avoid unnecessary code) ## At this point, lag varies with the first index in R; ## so pad **before** the transpose. if pad_result R_pad = zeros(pad_result,columns(R)); R = [R_pad; R; R_pad]; endif ## Correct the shape (transpose) so it is the same as the first input vector if isvector(X) && P > 1 R = R.'; endif ## return the lag indices if desired if nargout == 2 maxlag += pad_result; lags = [-maxlag:maxlag]; endif endfunction ##------------ Use brute force to compute the correlation ------- ##if !isvector(X) ## ## For matrix X, compute cross-correlation of all columns ## R = zeros(2*maxlag+1,P^2); ## for i=1:P ## for j=i:P ## idx = (i-1)*P+j; ## R(maxlag+1,idx) = X(:,i)' * X(:,j); ## for k = 1:maxlag ## R(maxlag+1-k,idx) = X(k+1:N,i)' * X(1:N-k,j); ## R(maxlag+1+k,idx) = X(1:N-k,i)' * X(k+1:N,j); ## endfor ## if (i!=j), R(:,(j-1)*P+i) = conj(flipud(R(:,idx))); endif ## endfor ## endfor ##elseif isempty(Y) ## ## reshape X so that dot product comes out right ## X = reshape(X, 1, N); ## ## ## compute autocorrelation for 0:maxlag ## R = zeros (2*maxlag + 1, 1); ## for k=0:maxlag ## R(maxlag+1+k) = X(1:N-k) * X(k+1:N)'; ## endfor ## ## ## use symmetry for -maxlag:-1 ## R(1:maxlag) = conj(R(2*maxlag+1:-1:maxlag+2)); ##else ## ## reshape and pad so X and Y are the same length ## X = reshape(postpad(X,N), 1, N); ## Y = reshape(postpad(Y,N), 1, N)'; ## ## ## compute cross-correlation ## R = zeros (2*maxlag + 1, 1); ## R(maxlag+1) = X*Y; ## for k=1:maxlag ## R(maxlag+1-k) = X(k+1:N) * Y(1:N-k); ## R(maxlag+1+k) = X(1:N-k) * Y(k+1:N); ## endfor ##endif ##-------------------------------------------------------------- %!shared x, y %! x = 0.5.^(0:15); %! y = circshift(x,5); ## Test input validation %!error xcorr () %!error xcorr (1) %!error xcorr (x, 1, x) %!error xcorr (x, 'none', x) %!error xcorr (x, x, 'invalid') %!error xcorr (x, 'invalid') %!test %! [c,lags] = xcorr(x); %! # largest spike at 0 lag, where X matches itself - ie the center %! [m, im] = max(c); %! assert(m, 4/3, 1e-6) %! assert(im, (numel(lags)+1)/2); %! %! [c1,lags1] = xcorr(x, x); %! [m, im] = max(c1); %! assert(m, 4/3, 1e-6) %! assert(im, (numel(lags1)+1)/2); %! assert(c1, c, 2*eps); %! assert(lags1, lags); %!test %! [c,lags] = xcorr(x,y); %! # largest spike at 0 lag, where X matches Y %! [m, im] = max(c); %! assert(m, 4/3, 1e-6) %! assert(lags(im), -5); %!test %! [c0,lags0] = xcorr(x,y); %! [c1,lags1] = xcorr(x,y, 'none'); %! assert(c0, c1); %! assert(lags0, lags1); %!test %! [c0,lags0] = xcorr(x,y); %! [c1,lags1] = xcorr(x,y, 'normalized'); %! assert(lags0, lags1); %! [m, im] = max(c1); %! # at 0 lag, should be 1 %! assert(m, 1, 1e-6); %! [c2,lags2] = xcorr(x,y, 'coeff'); %! assert(c1, c2); %! assert(lags1, lags2); %!test %! [c0,lags0] = xcorr(x,y); %! [c1,lags1] = xcorr(x,y, 'biased'); %! assert(lags0, lags1); %! [m, im] = max(c1); %! assert(m, 1/12, 1e-6); %! %! [c1,lags1] = xcorr(x, 'biased'); %! assert(lags0, lags1); %! [m, im] = max(c1); %! assert(m, 1/12, 1e-6); %!test %! [c0,lags0] = xcorr(x,y); %! [c1,lags1] = xcorr(x,y, 'unbiased'); %! assert(lags0, lags1); %! [m, im] = max(c1); %! assert(m, 1/8.25, 1e-6); %!test %! [c,lags] = xcorr(x,y, 10); %! [m, im] = max(c); %! assert(lags(im), -5); %! assert(lags(1), -10); %! assert(lags(end), 10); %! %! [c,lags] = xcorr(x,10); %! [m, im] = max(c); %! assert(lags(1), -10); %! assert(lags(end), 10); %!test %! [c0,lags0] = xcorr(x,y, 'normalized', 10); %! [c1,lags1] = xcorr(x,y, 10, 'normalized'); %! assert(c0, c1); %! assert(lags0, lags1); �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/xcorr2.m��������������������������������������������������������������������������0000644�0000000�0000000�00000011323�14673270174�012312� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2000 Dave Cogdell <cogdelld@asme.org> ## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2012 CarnĂ« Draug <carandraug+dev@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} xcorr2 (@var{a}) ## @deftypefnx {Function File} {} xcorr2 (@var{a}, @var{b}) ## @deftypefnx {Function File} {} xcorr2 (@dots{}, @var{scale}) ## Compute the 2D cross-correlation of matrices @var{a} and @var{b}. ## ## If @var{b} is not specified, computes autocorrelation of @var{a}, i.e., ## same as @code{xcorr (@var{a}, @var{a})}. ## ## The optional argument @var{scale}, defines the type of scaling applied to the ## cross-correlation matrix. Possible values are: ## ## @table @asis ## @item "none" (default) ## No scaling. ## ## @item "biased" ## Scales the raw cross-correlation by the maximum number of elements of @var{a} ## and @var{b} involved in the generation of any element of @var{c}. ## ## @item "unbiased" ## Scales the raw correlation by dividing each element in the cross-correlation ## matrix by the number of products @var{a} and @var{b} used to generate that ## element. ## ## @item "coeff" ## Scales the normalized cross-correlation on the range of [0 1] so that a value ## of 1 corresponds to a correlation coefficient of 1. ## @end table ## ## @seealso{conv2, corr2, xcorr} ## @end deftypefn function c = xcorr2 (a, b, biasflag = "none") if (nargin < 1 || nargin > 3) print_usage; elseif (nargin == 2 && ischar (b)) biasflag = b; b = a; elseif (nargin == 1) ## we have to set this case here instead of the function line, because if ## someone calls the function with zero argument, since a is never set, we ## will fail with "`a' undefined" error rather that print_usage b = a; endif if (ndims (a) != 2 || ndims (b) != 2) error ("xcorr2: input matrices must must have only 2 dimensions"); endif ## compute correlation [ma,na] = size(a); [mb,nb] = size(b); c = conv2 (a, conj (b (mb:-1:1, nb:-1:1))); ## bias routines by Dave Cogdell (cogdelld@asme.org) ## optimized by Paul Kienzle (pkienzle@users.sf.net) ## coeff routine by CarnĂ« Draug (carandraug+dev@gmail.com) switch lower (biasflag) case {"none"} ## do nothing, it's all done case {"biased"} c = c / ( min ([ma, mb]) * min ([na, nb]) ); case {"unbiased"} lo = min ([na,nb]); hi = max ([na, nb]); row = [ 1:(lo-1), lo*ones(1,hi-lo+1), (lo-1):-1:1 ]; lo = min ([ma,mb]); hi = max ([ma, mb]); col = [ 1:(lo-1), lo*ones(1,hi-lo+1), (lo-1):-1:1 ]'; bias = col*row; c = c./bias; case {"coeff"} a = double (a); b = double (b); a = conv2 (a.^2, ones (size (b))); b = sumsq (b(:)); c(:,:) = c(:,:) ./ sqrt (a(:,:) * b); otherwise error ("xcorr2: invalid type of scale %s", biasflag); endswitch endfunction %!test # basic usage %! a = magic (5); %! b = [6 13 22; 10 18 23; 8 15 23]; %! c = [391 807 519 391 473 289 120 %! 920 1318 1045 909 1133 702 278 %! 995 1476 1338 1534 2040 1161 426 %! 828 1045 1501 2047 2108 1101 340 %! 571 1219 2074 2155 1896 821 234 %! 473 1006 1643 1457 946 347 108 %! 242 539 850 477 374 129 54]; %! assert (xcorr2 (a, b), c); %!shared a, b, c, row_shift, col_shift %! row_shift = 18; %! col_shift = 20; %! a = randi (255, 30, 30); %! b = a(row_shift-10:row_shift, col_shift-7:col_shift); %! c = xcorr2 (a, b, "coeff"); %!assert (nthargout ([1 2], @find, c == max (c(:))), {row_shift, col_shift}); # should return exact coordinates %! m = rand (size (b)) > 0.5; %! b(m) = b(m) * 0.95; %! b(!m) = b(!m) * 1.05; %! c = xcorr2 (a, b, "coeff"); %!assert (nthargout ([1 2], @find, c == max (c(:))), {row_shift, col_shift}); # even with some small noise, should return exact coordinates %!test # coeff of autocorrelation must be same as negative of correlation by additive inverse %! a = 10 * randn (100, 100); %! auto = xcorr2 (a, "coeff"); %! add_in = xcorr2 (a, -a, "coeff"); %! assert ([min(auto(:)), max(auto(:))], -[max(add_in(:)), min(add_in(:))]); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/xcov.m����������������������������������������������������������������������������0000644�0000000�0000000�00000006505�14673270174�012060� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999, 2001 Paul Kienzle <pkienzle@users.sf.net> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{R}, @var{lag}] =} xcov ( @var{X} ) ## @deftypefnx {Function File} {@dots{} =} xcov ( @var{X}, @var{Y} ) ## @deftypefnx {Function File} {@dots{} =} xcov ( @dots{}, @var{maxlag}) ## @deftypefnx {Function File} {@dots{} =} xcov ( @dots{}, @var{scale}) ## Compute covariance at various lags [=correlation(x-mean(x),y-mean(y))]. ## ## @table @var ## @item X ## input vector ## @item Y ## if specified, compute cross-covariance between X and Y, ## otherwise compute autocovariance of X. ## @item maxlag ## is specified, use lag range [-maxlag:maxlag], ## otherwise use range [-n+1:n-1]. ## @item scale: ## @table @samp ## @item biased ## for covariance=raw/N, ## @item unbiased ## for covariance=raw/(N-|lag|), ## @item coeff ## for covariance=raw/(covariance at lag 0), ## @item none ## for covariance=raw ## @item none ## is the default. ## @end table ## @end table ## ## Returns the covariance for each lag in the range, plus an ## optional vector of lags. ## ## @seealso{xcorr} ## @end deftypefn function [retval, lags] = xcov (X, Y, maxlag, scale) if (nargin < 1 || nargin > 4) print_usage; endif if nargin==1 Y=[]; maxlag=[]; scale=[]; elseif nargin==2 maxlag=[]; scale=[]; if ischar(Y), scale=Y; Y=[]; elseif isscalar(Y), maxlag=Y; Y=[]; endif elseif nargin==3 scale=[]; if ischar(maxlag), scale=maxlag; maxlag=[]; endif if isscalar(Y), maxlag=Y; Y=[]; endif endif ## FIXME: should let center(Y) deal with [] ## [retval, lags] = xcorr(center(X), center(Y), maxlag, scale); if (!isempty(Y)) [retval, lags] = xcorr(center(X), center(Y), maxlag, scale); else [retval, lags] = xcorr(center(X), maxlag, scale); endif endfunction ## Test input validation %!error xcov () %!test %! x = 1:5; %! [c, l] = xcov(x); %! assert(c, [-4.0 -4.0 -1.0 4.0 10.0 4.0 -1.0 -4.0 -4.0], 2*eps) %! assert(l, [-4 -3 -2 -1 0 1 2 3 4]) %!test %! x = 1:5; %! y = 1:5; %! [c, l] = xcov(x,y); %! assert(c, [-4.0 -4.0 -1.0 4.0 10.0 4.0 -1.0 -4.0 -4.0], 2*eps) %! assert(l, [-4 -3 -2 -1 0 1 2 3 4]) %! %! y = 1; %! [c, l] = xcov(x,y); %! assert(c, [4.0 10.0 4.0], 2*eps) %! assert(l, [-1 0 1]) %!test %! x = 1:5; %! y = 1:5; %! # maxlag %! [c, l] = xcov(x,y, 2); %! assert(c, [-1.0 4.0 10.0 4.0 -1.0], 2*eps) %! assert(l, [-2 -1 0 1 2]) %!test %! x = 1:5; %! y = 1:5; %! # scale %! [c, l] = xcov(x,y, 'none'); %! assert(c, [-4.0 -4.0 -1.0 4.0 10.0 4.0 -1.0 -4.0 -4.0], 2*eps) %! assert(l, [-4 -3 -2 -1 0 1 2 3 4]) %! %! [c, l] = xcov(x,y, 'biased'); %! assert(c, [-0.8 -0.8 -0.2 0.8 2.0 0.8 -0.2 -0.8 -0.8], 2*eps) %! assert(l, [-4 -3 -2 -1 0 1 2 3 4]) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/zerocrossing.m��������������������������������������������������������������������0000644�0000000�0000000�00000004334�14673270174�013626� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2008 Carlo de Falco <carlo.defalco@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{x0} =} zerocrossing (@var{x}, @var{y}) ## Estimates the points at which a given waveform y=y(x) crosses the ## x-axis using linear interpolation. ## @seealso{fzero, roots} ## @end deftypefn function retval = zerocrossing (x,y) x = x(:);y = y(:); crossing_intervals = (y(1:end-1).*y(2:end) <= 0); left_ends = (x(1:end-1))(crossing_intervals); right_ends = (x(2:end))(crossing_intervals); left_vals = (y(1:end-1))(crossing_intervals); right_vals = (y(2:end))(crossing_intervals); mid_points = (left_ends+right_ends)/2; zero_intervals = find(left_vals==right_vals); retval1 = mid_points(zero_intervals); left_ends(zero_intervals) = []; right_ends(zero_intervals) = []; left_vals(zero_intervals) = []; right_vals(zero_intervals) = []; retval2=left_ends-(right_ends-left_ends).*left_vals./(right_vals-left_vals); retval = union(retval1,retval2); endfunction %!test %! x = linspace(0,1,100); %! y = rand(1,100)-0.5; %! x0= zerocrossing(x,y); %! y0 = interp1(x,y,x0); %! assert(norm(y0,inf), 0, 100*eps) %!test %! x = linspace(0,1,100); %! y = rand(1,100)-0.5; %! y(10:20) = 0; %! x0= zerocrossing(x,y); %! y0 = interp1(x,y,x0); %! assert(norm(y0,inf), 0, 100*eps) %!demo %! x = linspace(0,1,100); %! y = rand(1,100)-0.5; %! x0= zerocrossing(x,y); %! y0 = interp1(x,y,x0); %! plot(x,y,x0,y0,'x') %!demo %! x = linspace(0,1,100); %! y = rand(1,100)-0.5; %! y(10:20) = 0; %! x0= zerocrossing(x,y); %! y0 = interp1(x,y,x0); %! plot(x,y,x0,y0,'x') ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/zp2sos.m��������������������������������������������������������������������������0000644�0000000�0000000�00000014757�14673270174�012351� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 2005 Julius O. Smith III <jos@ccrma.stanford.edu> ## Copyright (C) 2021-2022 Charles Praplan ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{sos}, @var{g}] =} zp2sos (@var{z}) ## @deftypefnx {Function File} {[@var{sos}, @var{g}] =} zp2sos (@var{z}, @var{p}) ## @deftypefnx {Function File} {[@var{sos}, @var{g}] =} zp2sos (@var{z}, @var{p}, @var{k}) ## @deftypefnx {Function File} {@var{sos} =} zp2sos (@dots{}) ## Convert filter poles and zeros to second-order sections. ## ## INPUTS: ## @itemize ## @item ## @var{z} = column-vector containing the filter zeros ## @item ## @var{p} = column-vector containing the filter poles ## @item ## @var{k} = overall filter gain factor. If not given the gain is assumed to be 1. ## @end itemize ## ## RETURNED: ## @itemize ## @item ## @var{sos} = matrix of series second-order sections, one per row: ## @example ## @var{sos} = [@var{B1}.' @var{A1}.'; ...; @var{BN}.' @var{AN}.'] ## @end example ## where ## @code{@var{B1}.' = [b0 b1 b2] and @var{A1}.' = [a0 a1 a2]} for ## section 1, etc. ## See @code{filter} for documentation of the second-order direct-form filter ## coefficients @var{B}i and %@var{A}i, i=1:N. ## ## @item ## @var{g} is the overall gain factor that effectively scales ## any one of the @var{B}i vectors. ## @end itemize ## ## If called with only one output argument, the overall filter gain is ## applied to the first second-order section in the matrix @var{sos}. ## ## EXAMPLE: ## @example ## [z, p, k] = tf2zp ([1 0 0 0 0 1], [1 0 0 0 0 .9]); ## [sos, g] = zp2sos (z, p, k) ## ## sos = ## 1.0000 0.6180 1.0000 1.0000 0.6051 0.9587 ## 1.0000 -1.6180 1.0000 1.0000 -1.5843 0.9587 ## 1.0000 1.0000 0 1.0000 0.9791 0 ## ## g = ## 1 ## @end example ## ## @seealso{sos2zp, sos2tf, tf2sos, zp2tf, tf2zp} ## @end deftypefn function [SOS,G] = zp2sos(z,p,k,DoNotCombineReal) if nargin<3, k=1; endif if nargin<2, p=[]; endif DoNotCombineReal = 0; [zc, zr] = cplxreal (z(:)); [pc, pr] = cplxreal (p(:)); nzc = length (zc); npc = length (pc); nzr = length (zr); npr = length (pr); if DoNotCombineReal # Handling complex conjugate poles for count = 1:npc SOS(count, 4:6) = [1, -2 * real(pc(count)), abs(pc(count))^2]; endfor # Handling real poles for count = 1:npr SOS(count + npc, 4:6) = [0, 1, -pr(count)]; endfor # Handling complex conjugate zeros for count = 1:nzc SOS(count, 1:3) = [1, -2 * real(zc(count)), abs(zc(count))^2]; endfor # Handling real zeros for count = 1:nzr SOS(count+nzc, 1:3) = [0, 1, -zr(count)]; endfor # Completing SOS if needed (sections without pole or zero) if npc + npr > nzc + nzr for count = nzc + nzr + 1 : npc + npr % sections without zero SOS(count, 1:3) = [0, 0, 1]; end else for count = npc + npr + 1 : nzc + nzr % sections without pole SOS(count, 4:6) = [0, 0, 1]; endfor endif else # Handling complex conjugate poles for count = 1:npc SOS(count, 4:6) = [1, -2 * real(pc(count)), abs(pc(count))^2]; endfor # Handling pair of real poles for count = 1:floor(npr/2) SOS(count+npc, 4:6) = [1, - pr(2 * count - 1) - pr(2 * count), pr(2 * count - 1) * pr(2 * count)]; endfor # Handling last real pole (if any) if mod (npr,2) == 1 SOS(npc + floor (npr / 2) + 1, 4:6)= [0, 1, -pr(end)]; endif # Handling complex conjugate zeros for count = 1:nzc SOS(count, 1:3)= [1, -2 * real(zc(count)), abs(zc(count))^2]; endfor # Handling pair of real zeros for count = 1:floor(nzr / 2) SOS(count+nzc, 1:3)= [1, - zr(2 * count - 1) - zr(2 * count), zr(2 * count - 1) * zr(2 * count)]; endfor # Handling last real zero (if any) if mod (nzr, 2) == 1 SOS(nzc + floor (nzr / 2) + 1, 1:3) = [0, 1, -zr(end)]; endif # Completing SOS if needed (sections without pole or zero) if npc + ceil(npr / 2) > nzc + ceil(nzr / 2) for count = nzc + ceil (nzr / 2) + 1 : npc + ceil (npr / 2) % sections without zero SOS(count, 1:3) = [0, 0, 1]; endfor else for count = npc + ceil(npr / 2) + 1:nzc + ceil (nzr / 2) % sections without pole SOS(count, 4:6) = [0, 0, 1]; endfor endif endif if ~exist ('SOS') SOS=[0, 0, 1, 0, 0, 1]; # leading zeros will be removed endif # Removing leading zeros if present in numerator and denominator for count = 1:size(SOS,1) B=SOS(count, 1:3); A=SOS(count, 4:6); while B(1)==0 && A(1)==0 A(1) = []; # faster than A = circshift(A,-1); A(3) = 0; # " B(1) = []; B(3) = 0; endwhile SOS(count,:) = [B,A]; endfor ## If no output argument for the overall gain, combine it into the ## first section. if (nargout < 2) SOS(1,1:3) = k * SOS(1,1:3); else G = k; endif %!test %! B=[1 0 0 0 0 1]; A=[1 0 0 0 0 .9]; %! [z,p,k] = tf2zp(B,A); %! [sos,g] = zp2sos(z,p,k); %! [Bh,Ah] = sos2tf(sos,g); %! assert({Bh,Ah},{B,A},100*eps); %!test %! sos = zp2sos ([]); %! assert (sos, [1, 0, 0, 1, 0, 0], 100*eps); %!test %! sos = zp2sos ([], []); %! assert (sos, [1, 0, 0, 1, 0, 0], 100*eps); %!test %! sos = zp2sos ([], [], 2); %! assert (sos, [2, 0, 0, 1, 0, 0], 100*eps); %!test %! [sos, g] = zp2sos ([], [], 2); %! assert (sos, [1, 0, 0, 1, 0, 0], 100*eps); %! assert (g, 2, 100*eps); %!test %! sos = zp2sos([], [0], 1); %! assert (sos, [0, 1, 0, 1, 0, 0], 100*eps); %!test %! sos = zp2sos([0], [], 1); %! assert (sos, [1, 0, 0, 0, 1, 0], 100*eps); %!test %! sos = zp2sos([-1-j -1+j], [-1-2j -1+2j], 10); %! assert (sos, [10, 20, 20, 1, 2, 5], 100*eps); �����������������signal-1.4.6/inst/zp2ss.m���������������������������������������������������������������������������0000644�0000000�0000000�00000003526�14673270174�012162� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1994, 1996, 2000, 2002, 2003, 2004, 2005, 2007 Auburn University ## Copyright (C) 2012 Lukas F. Reichlin <lukas.reichlin@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} zp2ss (@var{z}, @var{p}, @var{k}) ## Conversion from zero / pole to state space. ## ## @strong{Inputs} ## @table @var ## @item z ## @itemx p ## Vectors of (possibly) complex poles and zeros of a transfer ## function. Complex values must come in conjugate pairs ## (i.e., @math{x+jy} in @var{z} means that @math{x-jy} is also in @var{z}). ## @item k ## Real scalar (leading coefficient). ## @end table ## ## @strong{Outputs} ## @table @var ## @item @var{a} ## @itemx @var{b} ## @itemx @var{c} ## @itemx @var{d} ## The state space system, in the form: ## @tex ## $$ \dot x = Ax + Bu $$ ## $$ y = Cx + Du $$ ## @end tex ## @ifnottex ## @example ## @group ## . ## x = Ax + Bu ## y = Cx + Du ## @end group ## @end example ## @end ifnottex ## @end table ## @end deftypefn ## Author: David Clem function [a, b, c, d, e] = zp2ss (varargin) if (nargin == 0) print_usage (); endif [a, b, c, d, e] = dssdata (zpk (varargin{:}), []); endfunction ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/inst/zp2tf.m���������������������������������������������������������������������������0000644�0000000�0000000�00000002727�14673270174�012150� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1996, 1998, 2000, 2002, 2004, 2005, 2007 Auburn University ## Copyright (C) 2012 Lukas F. Reichlin <lukas.reichlin@gmail.com> ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{num}, @var{den}] =} zp2tf (@var{z}, @var{p}, @var{k}) ## Converts zeros / poles to a transfer function. ## ## @strong{Inputs} ## @table @var ## @item z ## @itemx p ## Vectors of (possibly complex) poles and zeros of a transfer ## function. Complex values must appear in conjugate pairs. ## @item k ## Real scalar (leading coefficient). ## @end table ## @end deftypefn ## Author: A. S. Hodel <a.s.hodel@eng.auburn.edu> ## (With help from students Ingram, McGowan.) function [num, den] = zp2tf (varargin) if (nargin == 0) print_usage (); endif [num, den] = tfdata (zpk (varargin{:}), "vector"); endfunction �����������������������������������������signal-1.4.6/inst/zplane.m��������������������������������������������������������������������������0000644�0000000�0000000�00000012543�14673270174�012371� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Copyright (C) 1999, 2001 Paul Kienzle <pkienzle@users.sf.net> ## Copyright (C) 2004 Stefan van der Walt <stefan@sun.ac.za> ## Copyright (C) 2019 Mike Miller ## ## 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; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {Function File} {} zplane (@var{z}, @var{p}) ## @deftypefnx {Function File} {} zplane (@var{b}, @var{a}) ## Plot the poles and zeros on a complex plane. If the arguments are column ## vectors @var{z} and @var{p}, the complex zeros @var{z} and poles @var{p} ## are displayed. If the arguments are row vectors @var{b} and @var{a}, the ## zeros and poles of the transfer function represented by these filter ## coefficients are displayed. ## ## If @var{z} and @var{p} are matrices, the columns are distinct sets of zeros ## and poles and are displayed together in distinct colors. ## ## Note that due to the nature of the @code{roots} function, poles and zeros ## may be displayed as occurring around a circle rather than at a single ## point. ## ## The transfer function is ## ## @example ## @group ## B(z) b0 + b1 z^(-1) + b2 z^(-2) + ... + bM z^(-M) ## H(z) = ---- = -------------------------------------------- ## A(z) a0 + a1 z^(-1) + a2 z^(-2) + ... + aN z^(-N) ## ## b0 (z - z1) (z - z2) ... (z - zM) ## = -- z^(-M+N) ------------------------------ ## a0 (z - p1) (z - p2) ... (z - pN) ## @end group ## @end example ## ## If called with only one argument, the poles @var{p} defaults to an empty ## vector, and the denominator coefficient vector @var{a} defaults to 1. ## @end deftypefn ## FIXME: Consider a plot-like interface: ## zplane(x1,y1,fmt1,x2,y2,fmt2,...) ## with y_i or fmt_i optional as usual. This would allow ## legends and control over point color and filters of ## different orders. function zplane(z, p = []) if (nargin < 1 || nargin > 2) print_usage; endif if columns(z)>1 || columns(p)>1 if rows(z)>1 || rows(p)>1 ## matrix form: columns are already zeros/poles else ## z -> b ## p -> a if isempty(z), z=1; endif if isempty(p), p=1; endif M = length(z) - 1; N = length(p) - 1; z = [ roots(z); zeros(N - M, 1) ]; p = [ roots(p); zeros(M - N, 1) ]; endif endif xmin = min([-1; real(z(:)); real(p(:))]); xmax = max([ 1; real(z(:)); real(p(:))]); ymin = min([-1; imag(z(:)); imag(p(:))]); ymax = max([ 1; imag(z(:)); imag(p(:))]); xfluff = max([0.05*(xmax-xmin), (1.05*(ymax-ymin)-(xmax-xmin))/10]); yfluff = max([0.05*(ymax-ymin), (1.05*(xmax-xmin)-(ymax-ymin))/10]); xmin = xmin - xfluff; xmax = xmax + xfluff; ymin = ymin - yfluff; ymax = ymax + yfluff; r = exp (2i * pi * [0:100] / 100); plot (real (r), imag (r), "k"); axis equal; grid on; axis (1.05 * [xmin, xmax, ymin, ymax]); hold on; plot_with_labels (z, "o"); plot_with_labels (p, "x"); hold off; endfunction function plot_with_labels (x, symbol) if (! isempty(x)) colors = get (gca (), "colororder"); for c = 1:columns (x) color = colors(mod (c, rows (colors)), :); plot (real (x(:,c)), imag (x(:,c)), "color", color, ... "linestyle", "none", "marker", symbol); x_u = unique (x(:,c)); for i = 1:length (x_u) n = sum (x_u(i) == x(:,c)); if (n > 1) label = sprintf (" ^%d", n); text (real (x_u(i)), imag (x_u(i)), label, "color", color); endif endfor endfor endif endfunction %!demo %! ## construct target system: %! ## symmetric zero-pole pairs at r*exp(iw),r*exp(-iw) %! ## zero-pole singletons at s %! pw = [0.2, 0.4, 0.45, 0.95]; # pw = [0.4]; %! pr = [0.98, 0.98, 0.98, 0.96]; # pr = [0.85]; %! ps = []; %! zw = [0.3]; # zw=[]; %! zr = [0.95]; # zr=[]; %! zs = []; %! %! ## system function for target system %! p = [[pr, pr] .* exp(1i * pi * [pw, -pw]), ps]'; %! z = [[zr, zr] .* exp(1i * pi * [zw, -zw]), zs]'; %! M = length(z); %! N = length(p); %! sys_a = [zeros(1, M-N), real(poly(p))]; %! sys_b = [zeros(1, N-M), real(poly(z))]; %! %! disp ("The first two graphs should be identical, with poles at (r,w) ="); %! disp (sprintf(" (%.2f,%.2f)", [pr; pw])); %! disp ("and zeros at (r,w) ="); %! disp (sprintf(" (%.2f,%.2f)", [zr; zw])); %! disp ("with reflection across the horizontal axis"); %! %! subplot (2, 3, 1); %! zplane (sys_b, sys_a); %! title ("Transfer function form"); %! %! subplot (2, 3, 2); %! zplane (z, p); %! title ("Zero pole form"); %! %! subplot (2, 3, 3); %! zplane (z); %! title ("Zeros only, p=[]"); %! %! subplot (2, 3, 4); %! zplane (sys_b); %! title ("Numerator only, a=1"); %! %! disp ("The matrix plot has 2 sets of points, one inside the other"); %! subplot (2, 3, 5); %! zplane ([z, 0.7*z], [p, 0.7*p]); %! title ("Matrix of zeros and poles"); �������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/io.sourceforge.octave.signal.metainfo.xml����������������������������������������������0000644�0000000�0000000�00000002402�14673270174�017746� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8"?> <!-- Copyright 2018-2019 Mike Miller Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty. --> <component type="addon"> <id>io.sourceforge.octave.signal</id> <extends>org.octave.Octave.desktop</extends> <name>Signal Processing</name> <summary>Signal processing, measurement, filtering, windowing, and spectral analysis</summary> <keywords> <keyword>FIR filter</keyword> <keyword>IIR filter</keyword> <keyword>convolution</keyword> <keyword>digital filter</keyword> <keyword>linear filter</keyword> <keyword>signal measurement</keyword> <keyword>signal processing</keyword> <keyword>spectral analysis</keyword> <keyword>window function</keyword> </keywords> <url type="homepage">https://octave.sourceforge.io/signal/</url> <url type="bugtracker">https://savannah.gnu.org/bugs/?group=octave</url> <metadata_license>FSFAP</metadata_license> <project_license>GPL-3.0+</project_license> <developer_name>Octave-Forge Community</developer_name> <update_contact>octave-maintainers@gnu.org</update_contact> </component> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/src/�����������������������������������������������������������������������������������0000755�0000000�0000000�00000000000�14673270174�010527� 5����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/src/Makefile���������������������������������������������������������������������������0000644�0000000�0000000�00000003075�14673270174�012174� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile for the signal package for GNU Octave # # Copyright (C) 2012-2019 Mike Miller # # 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; see the file COPYING. If not, see # <https://www.gnu.org/licenses/>. MKOCTFILE ?= mkoctfile SED ?= sed PKG_CXXFLAGS := -Wall $(PKG_CXXFLAGS_APPEND) OCT_FILES = \ __fwht__.oct \ __ultrwin__.oct \ cl2bp.oct \ firpm.oct \ medfilt1.oct \ remez.oct \ sosfilt.oct \ upfirdn.oct CL2BP_OBJECTS = cl2bp.o cl2bp_lib.o FIRPM_OBJECTS = firpm.o mmfir.o OCT_SOURCES = $(patsubst %.oct,%.cc,$(OCT_FILES)) all: $(OCT_FILES) %.o: %.cc $(MKOCTFILE) $(PKG_CXXFLAGS) -c $< -o $@ %.o: %.c $(MKOCTFILE) -c $< -o $@ %.oct: %.cc octave-compat.h $(MKOCTFILE) $(PKG_CXXFLAGS) $< -o $@ cl2bp.oct: $(CL2BP_OBJECTS) $(MKOCTFILE) $(PKG_CXXFLAGS) $^ -o $@ firpm.oct: $(FIRPM_OBJECTS) $(MKOCTFILE) $(PKG_CXXFLAGS) $^ -o $@ $(CL2BP_OBJECTS): cl2bp_lib.h octave-compat.h PKG_ADD PKG_DEL: $(OCT_SOURCES) $(SED) -n -e 's/.*$@: \(.*\)/\1/p' $^ > $@-t mv $@-t $@ clean: -rm -f *.o *.oct PKG_* .PHONY: all clean �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/src/__fwht__.cc������������������������������������������������������������������������0000644�0000000�0000000�00000003310�14673270174�012577� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright (C) 2013-2019 Mike Miller 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; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ #include <octave/oct.h> template <typename T> static void do_fwht (T *x, octave_idx_type n) { double *xa = &x[0]; double *xb = &x[n/2]; // Perform the FWHT butterfly on the input for (octave_idx_type i = 0; i < n/2; i++) { double ya = xa[i] + xb[i]; double yb = xa[i] - xb[i]; xa[i] = ya; xb[i] = yb; } // Divide and conquer if (n > 2) { do_fwht (xa, n/2); do_fwht (xb, n/2); } } DEFUN_DLD (__fwht__, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {} __fwht__ (@var{x})\n\ Undocumented internal function.\n\ @end deftypefn") { int nargin = args.length (); if (nargin != 1) print_usage (); else { NDArray x = args(0).array_value (); octave_idx_type n = x.rows (); double *data = x.fortran_vec (); for (octave_idx_type i = 0; i < x.columns (); i++) { do_fwht (&data[i*n], n); } return octave_value (x); } return octave_value (); } /* ## No test needed for internal helper function. %!assert (1) */ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/src/__ultrwin__.cc���������������������������������������������������������������������0000644�0000000�0000000�00000022224�14673270174�013340� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright (C) 2013 Rob Sykes <robs@users.sourceforge.net> 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; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ #include <cmath> #include <cstdlib> #include <cstdio> #include <octave/oct.h> #include <octave/lo-specfun.h> #if !defined M_PI #define M_PI 3.14159265358979323846 #endif #if defined (__cplusplus) && __cplusplus > 201402L # define ATTR_FALLTHROUGH [[fallthrough]] #elif defined (__GNUC__) && __GNUC__ >= 7 # define ATTR_FALLTHROUGH __attribute__ ((__fallthrough__)) #else # define ATTR_FALLTHROUGH ((void) 0) #endif #if DEBUG_ULTRWIN #define SHOW1(x) fprintf(stderr, "%c%+.3e", " 1"[(x) > .5], (x) - ((x) > .5)) #endif #define EPSILON (1./0x100000) /* For caller rounding error. */ #define BETA_MAX (12*(1+EPSILON)) #define XMU_MIN (.99*(1-EPSILON)) static double * ultraspherical_win(int n, double mu, double xmu) { double * w = NULL; int bad = n < 1 || xmu < XMU_MIN || (!mu && xmu == 1) || (n > BETA_MAX * 2 && xmu * cos(M_PI * BETA_MAX / n) > 1); if (!bad && (w = (double *)malloc(sizeof(*w)* n))) { int i, j, k, l = 0, m = (n + 1) / 2, met; double * divs = w + m - 1, c = 1 - 1 / (xmu * xmu), t, u, v[64], vp, s; for (i = 0; i < (int)(sizeof(v) / sizeof(v[0])); v[i++] = 0); if (n > 1) for (i = 0; i < m; l = j - (j <= i++)) { vp = *v, s = *v = i? (*v + v[1]) * mu * (divs[i] = 1./i) : 1; for (met = 0, j = 1, u = 1; ; ++l, v[l] = vp * (i - l) / (mu + l - 1)) { #define _ t = v[j], v[j] += vp, vp = t, t = s, s += \ v[j] * (u *= c * (n - i - j) * divs[j]), met = s && s == t, ++j, for (k = ((l-j+1) & ~7) + j; j < k && !met; _ _ _ _ _ _ _ _ (void)0); for (; j <= l && !met; _ (void)0); #undef _ if (met || !(j <= i)) break; } w[i] = s / (n - i - 1); } else w[0] = 1; u = 1 / w[i = m - 1], w[i] = 1; for (--i ; i >= 0; u *= (n - 2 - i + mu) / (n - 2 - i), w[i] *= u, --i); for (i = 0; i < m; w[n - 1 - i] = w[i], ++i); } return w; } typedef struct {double f, fp;} uspv_t; static uspv_t ultraspherical_polyval(int n, double mu, double x, double const *divs) { double fp = n > 0? 2 * x * mu : 1, fpp = 1, f; uspv_t result; int i, k; #define _ f = (2*x*(i+mu)*fp - (i+2*mu-1)*fpp) * divs[i+1], fpp=fp, fp=f, ++i, for (i = 1, k = i + ((n - i) & ~7); i < k; _ _ _ _ _ _ _ _ (void)0); for (; i < n; _ (void)0); #undef _ result.f = fp, result.fp = fpp; return result; } #define MU_EPSILON (1./0x4000) #define EQ(mu,x) (fabs((mu)-(x)) < MU_EPSILON) static uspv_t ultraspherical_polyval2( /* With non-+ve integer protection */ int n, double mu, double x, double const * divs) { int sign = (~(int)floor(mu) & ~(~2u/2))? 1:-1; /* -ve if floor(mu) <0 & odd */ uspv_t r; if (mu < MU_EPSILON && EQ(mu,(int)mu)) mu = floor(mu + .5) + MU_EPSILON * ((int)mu > mu? -1:1); r = ultraspherical_polyval(n, mu, x, divs); r.f *= sign, r.fp *= sign; return r; } static double find_zero(int n, double mu, int l, double extremum_mag, double ripple_ratio, double lower_bound, double const *divs) { double dx, x0, t, x, epsilon = 1e-10, one_over_deriv, target = 0; int i, met = 0; if (!divs) return 0; if (!l) { double r = ripple_ratio; /* FIXME: factor in weighted extremum_mag here */ x = r > 1 ? cosh(acosh(r) / n) : cos(acos(r) / n); /* invert chebpoly-1st */ x0 = x *= lower_bound / cos(M_PI * .5 / n) + epsilon; target = log(extremum_mag * ripple_ratio); } else { double cheb1 = cos(M_PI * (l - .5) / n), cheb2 = cos(M_PI * l / (n + 1)); if (mu < 1 - l && EQ((int)(mu+.5),mu+.5)) x = met = 1; else if (EQ(mu,0)) x = cheb1, met = 1; /* chebpoly-1st-kind */ else if (EQ(mu,1)) x = cheb2, met = 1; /* chebpoly-2nd-kind */ else x = (cheb1 * cheb2) / (mu * cheb1 + (1 - mu) * cheb2); x0 = x; } for (i = 0; i < 24 && !met; ++i, met = fabs(dx) < epsilon) {/*Newton-Raphson*/ uspv_t r = ultraspherical_polyval2(n, mu, x, divs); if (!(t = ((2*mu + n-1) * r.fp - n*x * r.f))) /* Fail if div by 0 */ break; one_over_deriv = (1 - x*x) / t; /* N-R slow for deriv~=1, so take log: */ if (!l) { /* d/dx(f(g(x))) = f'(g(x)).g'(x) */ one_over_deriv *= r.f; /* d/dx(log x) = 1/x */ if (r.f <= 0) /* Fail if log of non-+ve */ break; if (x + (dx = (target - log(r.f)) * one_over_deriv) <= lower_bound) dx = (lower_bound - x) * .875; x += dx; } else x += dx = -r.f * one_over_deriv; #if DEBUG_ULTRWIN fprintf(stderr, "1/deriv=%9.2e dx=%9.2e x=", one_over_deriv, dx); SHOW1(x); fprintf(stderr, "\n"); #endif } #if DEBUG_ULTRWIN fprintf(stderr, "find_zero(n=%i mu=%g l=%i target=%g r=%g x0=", n, mu, l, target, ripple_ratio); SHOW1(x0); fprintf(stderr, ") %s ", met? "converged to" : "FAILED at"); SHOW1(x); fprintf(stderr, " in %i iterations\n", i); #else static_cast<void>(x0); #endif return met? x : 0; } static double * make_divs(int n, double **divs) { int i; if (!*divs) { *divs = (double *)malloc(n * sizeof(**divs)); if (*divs) for (i = 0; i < n; (*divs)[i] = 1./(i+1), ++i); } return *divs? *divs - 1 : 0; } #define DIVS make_divs(n, &divs) typedef enum {uswpt_Xmu, uswpt_Beta, uswpt_AttFirst, uswpt_AttLast} uswpt_t; double * ultraspherical_window(int n, double mu, double par, uswpt_t type, int even_norm, double *xmu_) { double * w = 0, xmu = 0, * divs = 0, last_extremum_pos = 0; if (n > 0 && fabs(mu) <= (8*(1+EPSILON))) switch (type) { case uswpt_Beta: xmu = mu == 1 && par == 1? 1 : par < .5 || par > BETA_MAX? 0 : find_zero(n-1, mu, 1, 0, 0, 0, DIVS) / cos(M_PI * par / n); break; case uswpt_AttFirst: if (par < 0) break; ATTR_FALLTHROUGH; case uswpt_AttLast: if (type == uswpt_AttLast && mu >= 0 && par < 0); else if (!EQ(mu,0)) { int extremum_num = type == uswpt_AttLast? (int)((n-2)/2 +.5) : 1 + EQ(mu,-1.5); double extremum_pos = find_zero(n-2, mu+1, extremum_num, 0, 0, 0, DIVS); double extremum_mag = !extremum_pos? 0 : fabs(ultraspherical_polyval2(n-1, mu, extremum_pos, DIVS).f); double xmu_lower_bound = !extremum_mag? 0 : find_zero(n-1, mu, 1, 0, 0, 0, DIVS); /* 1st null */ xmu = !xmu_lower_bound? 0 : find_zero( n-1, mu, 0, extremum_mag, pow(10, par/20), xmu_lower_bound, DIVS); last_extremum_pos = type == uswpt_AttLast? extremum_pos : last_extremum_pos; } else xmu = cosh(acosh(pow(10, par/20))/(n-1)); /* Cheby 1st kind */ break; default: case uswpt_Xmu: xmu = par; break; } #if DEBUG_ULTRWIN fprintf(stderr, "n=%i mu=%.3f xmu=%.16g\n", n, mu, xmu); #endif if (xmu > 0) w = ultraspherical_win(n, mu, xmu); if (w && (~n & !!even_norm) && n > 2 && !(mu == 1 && xmu == 1)) { int i = n / 2 - 1, j = 1; double * d = DIVS, t = 0, s = -1, x = even_norm == 1? 0 : last_extremum_pos? last_extremum_pos : find_zero(n-2, mu+1, i, 0, 0, 0, d); x = x? M_PI/2 - acos(x/xmu) : 0; for (; i >= 0; t += w[i] * d[j] * (s=-s) * (x?cos(j*x):1), --i, j += 2); for (t = M_PI/4 / t, i = 0; t < 1 && i < n; w[i] *= t, ++i); #if DEBUG_ULTRWIN fprintf(stderr, "%snorm DFT(w.sinc Ï€x) @ %g %.16g\n", t<1? "":"NO ", 2*x,t); #endif } free(divs); if (xmu_) *xmu_ = xmu; return w; } //---------------------------------------------------------------------------- DEFUN_DLD (__ultrwin__, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {} __ultrwin__ (@var{m}, @var{mu}, @var{par}, @var{par_type}, @var{norm})\n\ Undocumented internal function.\n\ @end deftypefn") { octave_value_list retval; int nargin = args.length (); if (nargin != 5) { print_usage (); return retval; } for (octave_idx_type i = 0; i < nargin; i++) if (! args(i).is_real_scalar ()) { print_usage (); return retval; } int m = args(0).scalar_value (); double mu = args(1).scalar_value (); double par = args(2).scalar_value (); uswpt_t par_type = static_cast<uswpt_t> (args(3).scalar_value ()); int even_norm = args(4).scalar_value (); double xmu; double *w = ultraspherical_window (m, mu, par, par_type, even_norm, &xmu); if (!w) { error ("ultrwin: parameter(s) out of range"); return retval; } ColumnVector ww (m); for (octave_idx_type i = 0; i < m; i++) ww(i) = w[i]; free (w); retval(0) = ww; retval(1) = xmu; return retval; } /* ## No test needed for internal helper function. %!assert (1) */ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/src/cl2bp.cc���������������������������������������������������������������������������0000644�0000000�0000000�00000010651�14673270174�012043� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright (C) 2008-2009 Evgeni A. Nurminski <nurmi@dvo.ru> Copyright (C) 2008-2009 Pete Gonzalez <pgonzalez@bluel.com> 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; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ #include <octave/oct.h> #include "cl2bp_lib.h" #include "octave-compat.h" static void cancel_handler(void *) { OCTAVE_QUIT; } // When CL2BP_LOGGING is defined, this will direct messages to the Octave pager void cl2bp_log(const char *message) { octave_stdout << message; } DEFUN_DLD (cl2bp, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {@var{h} =} cl2bp (@var{m}, @var{w1}, @var{w2}, @var{up}, @var{lo})\n\ @deftypefnx {Loadable Function} {@var{h} =} cl2bp (@var{m}, @var{w1}, @var{w2}, @var{up}, @var{lo}, @var{gridsize})\n\ \n\ Constrained L2 bandpass FIR filter design. This is a fast implementation of\n\ the algorithm cited below. Compared to @dfn{remez}, it offers implicit\n\ specification of transition bands, a higher likelihood of convergence, and an\n\ error criterion combining features of both L2 and Chebyshev approaches.\n\ \n\ Inputs:\n\ \n\ @table @var\n\ @item m\n\ degree of cosine polynomial, i.e. the number of output coefficients will be\n\ @var{m}*2+1\n\ @item w1\n\ @itemx w2\n\ bandpass filter cutoffs in the range 0 <= @var{w1} < @var{w2} <= pi,\n\ where pi is the Nyquist frequency\n\ @item up\n\ vector of 3 upper bounds for [stopband1, passband, stopband2]\n\ @item lo\n\ vector of 3 lower bounds for [stopband1, passband, stopband2]\n\ @item gridsize\n\ search grid size; larger values may improve accuracy,\n\ but greatly increase calculation time. Default value is 2048, max value is 1e6.\n\ @end table\n\ \n\ Output:\n\ \n\ A vector of @var{m}*2+1 FIR coefficients, or an empty value if the solver\n\ failed to converge.\n\ \n\ Example:\n\ @example\n\ @code{h = cl2bp(30, 0.3*pi, 0.6*pi, [0.02, 1.02, 0.02], [-0.02, 0.98, -0.02], 2^11);}\n\ @end example\n\ \n\ Original Paper: I. W. Selesnick, M. Lang, and C. S. Burrus. A modified\n\ algorithm for constrained least square design of multiband FIR filters without\n\ specified transition bands.\n\ IEEE Trans. on Signal Processing, 46(2):497-501, February 1998.\n\ @end deftypefn\n\ @seealso{remez}\n") { octave_value_list retval; const int nargin = args.length(); if (nargin < 5 || nargin > 6) { print_usage (); return retval; } const int m = args(0).int_value(true); const double w1 = args(1).double_value(); const double w2 = args(2).double_value(); const ColumnVector up_vector(args(3).vector_value()); const ColumnVector lo_vector(args(4).vector_value()); if (up_vector.numel() != 3 || lo_vector.numel() != 3) { error("cl2bp: The up and lo vectors must contain 3 values"); return retval; } double up[3]; double lo[3]; for (int i=0; i<3; ++i) { up[i] = up_vector(i); lo[i] = lo_vector(i); } const int L = (nargin == 5) ? 2048 : args(5).int_value(true); if (L > 1000000) { error("cl2bp: The \"gridsize\" parameter cannot exceed 1000000"); return retval; } MallocArray<double> h; try { cl2bp(h, m, w1, w2, up, lo, L, 1.e-5, 20, cancel_handler); } catch (std::exception &ex) { error("%s", ex.what()); return retval; } ColumnVector h_vector(h.get_length()); for (int i=0; i<h.get_length(); ++i) h_vector(i) = h[i]; return octave_value(h_vector); } /* %!test %! b = [ %! 0.0000000000000000 %! 0.0563980420304213 %! -0.0000000000000000 %! -0.0119990278695041 %! -0.0000000000000001 %! -0.3016146759510104 %! 0.0000000000000001 %! 0.5244313235801866 %! 0.0000000000000001 %! -0.3016146759510104 %! -0.0000000000000001 %! -0.0119990278695041 %! -0.0000000000000000 %! 0.0563980420304213 %! 0.0000000000000000]; %! assert(cl2bp(7, 0.25*pi, 0.75*pi, [0.01, 1.04, 0.01], [-0.01, 0.96, -0.01], 2^11), b, 1e-14); %! assert(cl2bp(7, 0.25*pi, 0.75*pi, [0.01, 1.04, 0.01], [-0.01, 0.96, -0.01]), b, 1e-14); */ ���������������������������������������������������������������������������������������signal-1.4.6/src/cl2bp_lib.cc�����������������������������������������������������������������������0000644�0000000�0000000�00000041766�14673270174�012704� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright (C) 2008-2009 Evgeni A. Nurminski <nurmi@dvo.ru> Copyright (C) 2008-2009 Pete Gonzalez <pgonzalez@bluel.com> 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; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS // disable spurious warnings #define _USE_MATH_DEFINES // for math.h #endif #include "cl2bp_lib.h" #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <math.h> #include <string.h> #include <stdexcept> #define BIG_NUMBER 100000 //----------------------------------------------------------------------------------------------------------- #ifdef CL2BP_LOGGING static void log_printf(const char *format, ...) { va_list argptr; va_start(argptr, format); char buf[20*1024]; if (vsnprintf(buf,20*1024-1,format,argptr) == -1) { strcpy(buf, "#ERROR#"); } va_end(argptr); cl2bp_log(buf); } #else #define log_printf(...) ((void)0) // don't log anything (for a big speed improvement) #endif //----------------------------------------------------------------------------------------------------------- static int local_max(const MallocArray<double>& x, int n, MallocArray<int>& ix) { int i, mx; mx = 0; MallocArray<double> xx(n+2); xx[0] = xx[n + 1] = -BIG_NUMBER; for ( i = 1; i <= n; i++) xx[i] = x[i - 1]; for ( i = 0; i < n; i++ ) { (((xx[i] < xx[i + 1]) && (xx[i + 1] > xx[i + 2])) || ((xx[i] < xx[i + 1]) && (xx[i + 1] >= xx[i + 2])) || ((xx[i] <= xx[i + 1]) && (xx[i + 1] > xx[i + 2])) ) && ( ix[mx++] = i ); } return mx; } //----------------------------------------------------------------------------------------------------------- static int solvps(MallocArray<double>& a, MallocArray<double>& b, int n, void (*cancel_handler)(void *), void *cancel_state) { double t; int j, k; int a_p; int a_q; int a_r; int a_s; // In empirical tests, 2% to 6% of the execution time was spent in solvps() if (cancel_handler) cancel_handler(cancel_state); for (j = 0, a_p = 0; j < n; ++j, a_p += n+1) { for (a_q = j*n; a_q < a_p; ++a_q) a[a_p] -= a[a_q] * a[a_q]; if (a[a_p] <= 0.) return -1; a[a_p] = sqrt(a[a_p]); for (k = j + 1, a_q = a_p + n; k < n; ++k, a_q += n) { for (a_r = j*n, a_s = k*n, t = 0.; a_r < a_p;) t += a[a_r++] * a[a_s++]; a[a_q] -= t; a[a_q] /= a[a_p]; } } for (j = 0, a_p = 0; j < n; ++j, a_p += n+1) { for (k = 0, a_q = j*n; k < j;) b[j] -=b [k++] * a[a_q++]; b[j] /= a[a_p]; } for (j = n - 1, a_p = n*n - 1; j >= 0; --j, a_p -= n + 1) { for (k = j + 1, a_q = a_p + n; k < n; a_q += n) b[j] -= b[k++]* a[a_q]; b[j] /= a[a_p]; } return 0; } //----------------------------------------------------------------------------------------------------------- static void rmmult(MallocArray<double>& rm, const MallocArray<double>& a, const MallocArray<double>& b, int n, int m, int l, void (*cancel_handler)(void *), void *cancel_state) { double z; int i,j,k; int b_p; // index into b int a_p; // index into a int rm_start = 0; // index into rm int rm_q; // index into rm MallocArray<double> q0(m); for (i = 0; i < l ; ++i, ++rm_start) { // In empirical tests, 87% to 95% of the execution time was spent in rmmult() if (cancel_handler) cancel_handler(cancel_state); for (k = 0, b_p = i; k < m; b_p += l) q0[k++] = b[b_p]; for (j = 0, a_p = 0, rm_q = rm_start; j < n; ++j, rm_q += l) { for (k = 0, z = 0.; k < m;) z += a[a_p++] * q0[k++]; rm[rm_q]=z; } } } //----------------------------------------------------------------------------------------------------------- static void mattr(MallocArray<double>& a, const MallocArray<double>& b, int m, int n) { int i, j; int b_p; int a_p = 0; int b_start = 0; for (i = 0; i < n; ++i, ++b_start) for ( j = 0, b_p = b_start; j < m; ++j, b_p += n ) a[a_p++] = b[b_p]; } //----------------------------------------------------------------------------------------------------------- static void calcAx(MallocArray<double>& Ax, int m, int L) { double r = M_SQRT2, pi = M_PI; int i, j; Ax.resize((L+1)*(m + 1)); for ( i = 0; i <= L; i++) for ( j = 0; j <= m; j++) Ax[i*(m+1) + j] = cos(i*j*pi/L); for ( i = 0; i < (L+1)*(m+1); i += m + 1 ) Ax[i] /= r; } //----------------------------------------------------------------------------------------------------------- #ifdef CL2BP_LOGGING static double L2error(const MallocArray<double>& x, const MallocArray<double>& w, int L, double w1, double w2) { double xx, ww, sumerr, pi = M_PI; int i; for ( i = 0, sumerr = 0; i < L + 1; i++ ) { ww = w[i]; xx = x[i]; sumerr += ( ww < w1*pi || ww > w2*pi ) ? xx*xx : (1 - xx)*(1 - xx); } return sumerr; } #endif // CL2BP_LOGGING //----------------------------------------------------------------------------------------------------------- static double CHerror(double *wmin, const MallocArray<double>& x, const MallocArray<double>& w, int L, double w1, double w2) { double xx, ww, err, errmax; int i; errmax = -1; *wmin = 0; for ( i = 0; i < L + 1; i++ ) { ww = w[i]; xx = x[i]; err = (( ww < w1 ) || (ww > w2 )) ? fabs(xx) : fabs(1 - xx); if ( err > errmax ) { errmax = err; *wmin = ww; } } return errmax; } //----------------------------------------------------------------------------------------------------------- static void Ggen(MallocArray<double>& G, int m, const MallocArray<double>& w, const MallocArray<int>& kmax, int l_kmax, const MallocArray<int>& kmin, int l_kmin) { G.resize((l_kmax + l_kmin)*(m + 1)); int nsys, i, j; double r = M_SQRT2; nsys = l_kmax + l_kmin; for ( i = 0; i < l_kmax; i++) for ( j = 0; j <= m; j++) G[i*(m+1) + j] = cos(w[kmax[i]]*j); for ( i = l_kmax; i < nsys; i++) for ( j = 0; j <= m; j++) G[i*(m+1) + j] = -cos(w[kmin[i - l_kmax]]*j); for ( i = 0; i < nsys*(m+1); i += m+1 ) G[i] /= r; } //----------------------------------------------------------------------------------------------------------- bool cl2bp(MallocArray<double>& h, int m, double w1, double w2, double up[3], double lo[3], int L, double eps, int mit, void (*cancel_handler)(void *), void *cancel_state) { // Ensure sane values for input parameters if (m < 2 || m > 5000) throw std::invalid_argument("cl2bp: The m count must be between 2 and 5000"); if (w1 < 0 || w1 > w2 || w2 > 2*M_PI) throw std::invalid_argument("cl2bp: The cutoffs must be in the range 0 < w1 < w2 < 2*pi"); // Z is allocated as Z(2*L-1-2*m) if (L <= m) throw std::invalid_argument("cl2bp: The \"gridsize\" parameter must be larger than \"m\""); double r = M_SQRT2; double pi = M_PI; double wmin, ww, xw; int q1, q2, q3, i, iter = 0; int off, neg; int ik; int l_kmax; int l_kmin; int l_okmax; int l_okmin; double uvo = 0, lvo = 0; double err, diff_up, diff_lo; double erru, erro; int iup, ilo; int nsys, j; int imin = BIG_NUMBER; double umin; int k1 = -1, k2 = -1, ak1, ak2; double cerr; h.resize(2*m+1); bool converged = true; MallocArray<double> x0(L+1); MallocArray<double> x1(L+1); MallocArray<double> xx(L+1); MallocArray<double> xm1(L+1); MallocArray<double> w(L+1); MallocArray<double> u(L+1); MallocArray<double> l(L+1); MallocArray<double> a(L+1); MallocArray<double> c(L+1); MallocArray<int> kmax(L+1); MallocArray<int> kmin(L+1); l_kmax = l_kmin = 0; MallocArray<int> okmin(L+1); MallocArray<int> okmax(L+1); l_okmax = l_okmin = 0; MallocArray<double> rhs(m+2); MallocArray<double> mu(2*(L+1)); for ( i = 0; i <= L; i++ ) w[i] = i*pi/L; MallocArray<double> Z(2*L-1-2*m); q1 = (int)floor(L*w1/pi); q2 = (int)floor(L*(w2-w1)/pi); q3 = L + 1 - q1 - q2; off = 0; for ( i = 0; i < q1; i++) { u[i] = up[0]; l[i] = lo[0]; } off += i; for ( i = 0; i < q2; i++) { u[off + i] = up[1]; l[off + i] = lo[1]; } off += i; for ( i = 0; i < q3; i++) { u[off + i] = up[2]; l[off + i] = lo[2]; } c[0] = (w2-w1)*r; for ( i = 1; i <= m; i++) c[i] = 2*(sin(w2*i)-sin(w1*i))/i; for ( i = 0; i <= m; i++) { c[i] /= pi; a[i] = c[i]; } log_printf("\nInitial approximation. Unconstrained L2 filter coefficients.\n"); log_printf("=============================================================\n"); log_printf("\nZero order term %8.3lf\n", a[0]); for ( i = 1; i <= m; i++) { log_printf("%4d %8.3lf", i, a[i]); if (i - 8*(i/8) == 0) log_printf("\n"); } log_printf("\n"); // Precalculate Ax MallocArray<double> Ax; calcAx(Ax, m, L); //calcA(x0, a, m, L); rmmult(x0, Ax, a, L + 1, m + 1, 1, cancel_handler, cancel_state); err = CHerror(&wmin, x0, w, L, w1, w2); log_printf("\nChebyshev err %12.4e (%11.5e) <> L2 err %12.4e\n", err, wmin/pi, L2error(x0, w, L, w1, w2)/(L+1)); for (iter = 1; ; iter++) { log_printf("\n:::::: Iteration %3d :::::::::::\n", iter); if ( (uvo > eps*2) || (lvo > eps*2) ) { log_printf("\nXXX Take care of old errors: uvo lvo %12.3e %12.3e", uvo, lvo); if( k1 >= 0 ) log_printf(" k1 %3d(%d)", k1, okmax[k1]); if( k2 >= 0 ) log_printf(" k2 %3d(%d)", k2, okmin[k2]); log_printf("\n"); if ( uvo > lvo ) { kmax[l_kmax] = okmax[k1]; l_kmax++; l_okmax--; for (i = k1; i < l_okmax; i++) okmax[i] = okmax[i + 1]; } else { kmin[l_kmin] = okmin[k2]; l_kmin++; l_okmin--; for (i = k2; i < l_okmin; i++) okmin[i] = okmin[i + 1]; } nsys = l_kmax + l_kmin; /* for (i = 0; i < l_kmax; i++) log_printf("i %3d kmax %3d mu %12.4e\n", i, kmax[i], mu[i]); log_printf("\n"); for (i = 0; i < l_kmin; i++) log_printf("i %3d kmin %3d mu %12.4e\n", i, kmin[i], mu[i + l_kmax]); log_printf("\n\n"); */ } else { //calcA(x1, a, m, L); rmmult(x1, Ax, a, L + 1, m + 1, 1, cancel_handler, cancel_state); for ( i = 0; i < l_kmax; i++) okmax[i] = kmax[i]; for ( i = 0; i < l_kmin; i++) okmin[i] = kmin[i]; l_okmax = l_kmax; l_okmin = l_kmin; l_kmax = local_max(x1, L + 1, kmax); for ( i = 0; i < L + 1; i++) xm1[i] = -x1[i]; l_kmin = local_max(xm1, L + 1, kmin); log_printf("\nSignificant deviations from the ideal filter. Levels:"); log_printf(" %8.2e %8.2e %8.2e (lo)", lo[0], lo[1], lo[2]); log_printf(" %8.2e %8.2e %8.2e (up)", up[0], up[1], up[2]); log_printf("\n"); for ( i = 0, ik = 0; i < l_kmax; i++) { j = kmax[i]; if ( x1[j] > u[j] - 10*eps ) { kmax[ik] = j; ik++; } } l_kmax = ik; log_printf("overshoots = %d\n", l_kmax); for ( i = 0; i < l_kmax; i++) { j = kmax[i]; ww = w[j]; xw = x1[j]; err = (w1 < ww && ww < w2) ? xw - 1 : xw; log_printf(" i = %3d kmax = %3d xw = %12.5e err = %10.3e u = %12.4e max = %9.2e\n", i, j, xw, err, u[j], xw - u[j]); } for ( i = 0, ik = 0; i < l_kmin; i++) { j = kmin[i]; if ( x1[j] < l[j] + 10*eps ) { kmin[ik] = j; ik++; } } l_kmin = ik; log_printf("undershoots = %d\n", l_kmin); for ( i = 0; i < l_kmin; i++) { j = kmin[i]; ww = w[j]; xw = -xm1[j]; err =(w1 < ww && ww < w2) ? xw - 1 : xw; log_printf(" i = %3d kmin = %3d xw = %12.5e err = %10.3e l = %12.4e min = %9.2e\n", i, j, xw, err, l[j], xw - l[j]); } err = erru = erro = diff_up = diff_lo = 0; iup = ilo = 0; for ( i = 0; i < l_kmax; i++) { ik = kmax[i]; diff_up = x1[ik] - u[ik]; if ( diff_up > erru ) { erru = diff_up; iup = i; } } for ( i = 0; i < l_kmin; i++) { ik = kmin[i]; diff_lo = l[ik] - x1[ik]; if ( diff_lo > erro ) { erro = diff_lo; ilo = i; } } err = erro > erru ? erro : erru; log_printf("erru = %14.6e iup = %4d kmax = %4d ", erru, iup, kmax[iup]); log_printf("erro = %14.6e ilo = %4d kmin = %4d\n", erro, ilo, kmin[ilo]); #ifndef CL2BP_LOGGING static_cast<void>(iup); #endif if ( err < eps ) break; } nsys = l_kmax + l_kmin; MallocArray<double> G(nsys*(m + 1)); MallocArray<double> GT(nsys*(m + 1)); MallocArray<double> GG(nsys*nsys); for ( i = 0; i < l_kmax; i++) for ( j = 0; j <= m; j++) G[i*(m+1) + j] = cos(w[kmax[i]]*j); for ( i = l_kmax; i < nsys; i++) for ( j = 0; j <= m; j++) G[i*(m+1) + j] = -cos(w[kmin[i - l_kmax]]*j); for ( i = 0; i < nsys*(m+1); i += m+1 ) G[i] /= r; mattr(GT, G, nsys, m + 1); rmmult(GG, G, GT, nsys, m + 1, nsys, cancel_handler, cancel_state); rmmult(rhs, G, c, nsys, m + 1, 1, cancel_handler, cancel_state); for ( i = 0; i < nsys; i++) if ( i < l_kmax ) rhs[i] -= u[kmax[i]]; else rhs[i] += l[kmin[i - l_kmax]]; for ( i = 0; i < nsys; ++i) mu[i] = rhs[i]; solvps(GG, mu, nsys, cancel_handler, cancel_state); log_printf("\nXXX KT-system with %d equations resolved.\n", nsys); for ( i = 0, neg = 0; i < nsys; i++) if ( mu[i] < 0 ) neg++; log_printf("\nTotal number of negative multipliers = %3d\n\n", neg); while (neg) { umin = BIG_NUMBER; for ( i = 0, j = 0; i < nsys; i++) { if ( mu[i] >= 0 ) continue; j++; if ( mu[i] < umin ) { imin = i; umin = mu[i]; } } if ( umin > 0 ) break; log_printf(" neg = %3d of %3d imin = %3d mu-min = %12.4e\n", j, nsys, imin, umin); for ( i = imin; i < nsys - 1; i++) { rhs[i] = rhs[i + 1]; for ( j = 0; j <= m; j++) G[i*(m + 1) + j] = G[(i + 1)*(m + 1) + j]; } if ( imin < l_kmax ) { for ( i = imin; i < l_kmax - 1; i++) kmax[i] = kmax[i + 1]; l_kmax--; } else { for ( i = imin; i < nsys - 1; i++) kmin[i - l_kmax] = kmin[i - l_kmax + 1]; l_kmin--; } --nsys; mattr(GT, G, nsys, m + 1); rmmult(GG, G, GT, nsys, m + 1, nsys, cancel_handler, cancel_state); for ( i = 0; i < nsys; ++i) mu[i] = rhs[i]; solvps(GG, mu, nsys, cancel_handler, cancel_state); } MallocArray<double> da(m + 1); MallocArray<double> zd(nsys); rmmult(da, GT, mu, m + 1, nsys, 1, cancel_handler, cancel_state); for ( i = 0; i <= m; i++) a[i] = c[i] - da[i]; rmmult(zd, G, a, nsys, m + 1, 1, cancel_handler, cancel_state); MallocArray<double> zz(l_okmax + l_okmin); Ggen(G, m, w, okmax, l_okmax, okmin, l_okmin); rmmult(zz, G, a, l_okmax + l_okmin, m + 1, 1, cancel_handler, cancel_state); uvo = lvo = eps; k1 = k2 = -1; ak1 = ak2 = -1; if (l_okmax + l_okmin > 0) log_printf("\nErrors on the previous set of freqs\n\n"); for (i = 0; i < l_okmax; i++) { j = okmax[i]; cerr = zz[i] - u[j]; log_printf(" i %2d j %3d u %12.4e Ga %12.4e cerr %12.4e\n", i, j, u[j], zz[i], cerr); if ( cerr > uvo ) { uvo = cerr; k1 = i; ak1 = j; } } cerr = 0; for (i = 0; i < l_okmin; i++) { j = okmin[i]; cerr = l[j] + zz[i + l_okmax]; log_printf(" i %2d j %3d l %12.4e Ga %12.4e cerr %12.4e\n", i, j, l[j], zz[i + l_okmax], cerr); if ( cerr > lvo ) { lvo = cerr; k2 = i, ak2 = j; } } if ( l_okmax + l_okmin > 0 ) { log_printf("\n uvo = %12.4e k1 = %4d (%3d) ", uvo, k1, ak1); log_printf(" lvo = %12.4e k2 = %4d (%3d) ", lvo, k2, ak2); log_printf(" maxerr = %12.4e\n", uvo > lvo ? uvo : lvo); #ifndef CL2BP_LOGGING static_cast<void>(ak1); #endif } log_printf("\nConstrained L2 band filter coefficients.\n"); log_printf("=====================================\n"); #ifdef CL2BP_LOGGING log_printf("\nZero order term %8.3lf\n", a[0]); for ( i = 1; i <= m; i++) { log_printf("%4d %8.3lf", i, a[i]); if (i - 8*(i/8) == 0) log_printf("\n"); } log_printf("\n"); #endif //calcA(xx, a, m, L); rmmult(xx, Ax, a, L + 1, m + 1, 1, cancel_handler, cancel_state); if ( iter >= mit ) { log_printf("Maximum iterations reached\n"); converged = false; } } for (i = 0; i < m; i++) { h[i] = a[m - i]/2; h[m + i + 1] = a[i + 1]/2; } h[m] = a[0]*r/2; return converged; } ����������signal-1.4.6/src/cl2bp_lib.h������������������������������������������������������������������������0000644�0000000�0000000�00000007315�14673270174�012536� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright (C) 2008-2009 Evgeni A. Nurminski <nurmi@dvo.ru> Copyright (C) 2008-2009 Pete Gonzalez <pgonzalez@bluel.com> 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; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ #ifndef CL2BP_H #define CL2BP_H #include <cstdlib> #include <cassert> #include <cstring> //for memset //----------------------------------------------------------------------------------------------------------- // If you want to debug the cl2bp algorithm, define the CL2BP_LOGGING symbol and provide an // implementation of cl2bp_log(). #ifdef CL2BP_LOGGING extern void cl2bp_log(const char *message); #endif //----------------------------------------------------------------------------------------------------------- // This is a simple helper class that performs bounds-checking for debug builds, but reduces to an unchecked // malloc() array for release builds. template <class T> class MallocArray { int length; T *ptr; public: T& operator[](int index) { assert(index >= 0 && index < length); return ptr[index]; } T operator[](int index) const { assert(index >= 0 && index < length); return ptr[index]; } int get_length() const { return length; } void resize(int length_) { assert(length_ >= 0 && length_ <= 512*1024*1024); // verify that the array size is reasonable length = length_; ptr = (T *)realloc(ptr, length * sizeof(T)); std::memset(ptr, 0, length * sizeof(T)); } MallocArray(int length_=0) { ptr = 0; length = 0; if (length_) resize(length_); } ~MallocArray() { free(ptr); } private: MallocArray(const MallocArray&) { } // copy constructor is unimplemented and disallowed }; //----------------------------------------------------------------------------------------------------------- // Constrained L2 BandPass FIR filter design // h 2*m+1 filter coefficients (output) // m degree of cosine polynomial // w1,w2 fist and second band edges // up upper bounds // lo lower bounds // L grid size // eps stopping condition ("SN") // mit maximum number of iterations // // cl2bp() returns true if the solver converged, or false if the maximum number of iterations was reached. // If provided, the cancel_handler function pointer will be called periodically inside long-running loops, // giving an opportunity to abort (by throwing a C++ exception). The cancel_state parameter is a // user-defined pointer, e.g. a button object, boolean flag, or other means of detecting a cancel request. // // Example usage: // MallocArray<double> coefficients; // double up[3] = { 0.02, 1.02, 0.02 }; // double lo[3] = { -0.02, 0.98, -0.02 }; // cl2bp(coefficients, 30, 0.3*M_PI, 0.6*M_PI, up, lo, 1<<11, 1.e-5, 20); // // The algorithm is described in this paper: // I. W. Selesnick, M. Lang, and C. S. Burrus. A modified algorithm for constrained least square // design of multiband FIR filters without specified transition bands. IEEE Trans. on Signal // Processing, 46(2):497-501, February 1998. bool cl2bp(MallocArray<double>& h, int m, double w1, double w2, double up[3], double lo[3], int L, double eps, int mit, void (*cancel_handler)(void *)=0, void *cancel_state=0); #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/src/firpm.cc���������������������������������������������������������������������������0000644�0000000�0000000�00000111361�14673270174�012156� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������//////////////////////////////////////////////////////////////////////// // // Copyright (C) 2014/15/21 Rob Sykes <robs@users.sourceforge.net> // // See the file COPYRIGHT.md in the top-level directory of this // distribution or <https://octave.org/copyright/>. // // This file is part of Octave. // // Octave 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. // // Octave 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 Octave; see the file COPYING. If not, see // <https://www.gnu.org/licenses/>. // //////////////////////////////////////////////////////////////////////// #include "mmfir.h" #include <octave/oct.h> #include <octave/Cell.h> #include <ov-fcn-handle.h> #include <ov-scalar.h> #include <octave/parse.h> #include "octave-compat.h" #define AL(x) (int)(sizeof (x)/sizeof (x[0])) // Array-Length #define returnError(...) do { error (__VA_ARGS__);\ return octave_value_list (); } while (0) enum { RESP_FN_ARG_N, RESP_FN_ARG_F, RESP_FN_ARG_G, RESP_FN_ARG_W, RESP_FN_ARG_VAR }; static MmfirResult mmfirRespFn (MmfirBandSpec const * bandSpecs, int len, MmfirPoint points[], va_list args) { (void)bandSpecs; octave_fcn_handle * const respFnHandle(va_arg (args, octave_fcn_handle *)); octave_value_list * const respFnArgs (va_arg (args, octave_value_list *)); ColumnVector G (len); for (int i=0; i<len; ++i) G (i) = points[i].f; (*respFnArgs) (RESP_FN_ARG_G) = G; octave_value_list const result( octave::feval (respFnHandle->function_value (), *respFnArgs, 2)); auto const nargout (result.length ()); ColumnVector A; if (nargout>0) A=result (0).vector_value (); ColumnVector W; if (nargout>1) W=result (1).vector_value (); if (A.numel ()!=len) { error ("firpm respFn amplitude length %i should be %i", (int)A.numel (), len); return MmfirInvalidAmplitude; } if (W.numel ()!=len && nargout>1) { error ("firpm respFn weight length %i should be %i", (int)W.numel (), len); return MmfirInvalidWeight; } if (nargout>1) for (int i=0; i<len; ++i) points[i].a=A (i), points[i].w=W (i); else for (int i=0; i<len; ++i) points[i].a=A (i), points[i].w=1; return MmfirSuccess; } static double lgrid (octave_value const & v) { double const density(v.double_value ()); return log ( std::max (density, 16.)) / log (4) - 2; } DEFUN_DLD (firpm, args, nargout, "\ -*- texinfo -*-\n\ @deftypefn {Loadable Function} {@var{b} =} firpm (@var{n}, @var{f}, @var{a})\n\ @deftypefnx {Loadable Function} {@var{b} =} firpm (@var{n}, @var{f}, @@@var{respFn})\n\ @deftypefnx {Loadable Function} {@var{b} =} firpm (@var{n}, @var{f}, @{@@@var{respFn}, @dots{}@})\n\ @deftypefnx {Loadable Function} {@var{b} =} firpm (@dots{}, @var{w})\n\ @deftypefnx {Loadable Function} {@var{b} =} firpm (@dots{}, @var{class})\n\ @deftypefnx {Loadable Function} {@var{b} =} firpm (@dots{}, @{@var{accuracy, @dots{}@}})\n\ @deftypefnx {Loadable Function} {[@var{b}, @var{minimax}] =} firpm (@dots{})\n\ @deftypefnx {Loadable Function} {[@var{b}, @var{minimax}, @var{res}] =} firpm (@dots{})\n\ @cindex signal processing\n\ \n\ Designs a linear-phase FIR filter according to given specifications and the\n\ `minimax' criterion. The method (per McClellan et al.@footnote{ J. H.\n\ McClellan, T. W. Parks and L. R. Rabiner, `A Computer Program for Designing\n\ Optimum FIR Linear Phase Digital Filters', IEEE Trans.@: Audio Electroacoust.,\n\ vol.@: AU-21, 1973, pp.@: 506--525.}) uses successive approximation to minimize\n\ the maximum weighted error between the desired and actual frequency response of\n\ the filter. Such filters are variably described as being `minimax',\n\ `equiripple', or `optimal (in the Chebyshev sense)'.\n\ \n\ @heading Arguments\n\ \n\ @table @var\n\ \n\ @item @dots{}\n\ Where shown as the first argument to @code{firpm}, indicates that any\n\ previously-indicated list of arguments may substitute for the ellipsis.\n\ \n\ @item n\n\ A positive integer giving the filter order.\n\ \n\ @item f\n\ A vector of real-numbers, increasing in the range [0,1], giving the frequencies\n\ of the left and right edges of each band for which a specific amplitude\n\ response is desired: [l1 r1 l2 r2 @dots{}]. 1 represents the\n\ Nyquist-frequency. Transition-bands are defined implicitly as the regions\n\ between or outside the given bands.\n\ \n\ @item a\n\ A vector of real-numbers giving the desired amplitude response. An amplitude\n\ value is given either for each band edge: [a(l1) a(r1) a(l2) a(r2) @dots{}], or\n\ for each band: [a1 a2 @dots{}]. In the former case, in-band amplitude is\n\ determined by linear interpolation between the given band-edge values. 1\n\ represents unity-gain, 0 represents infinite attenuation, and @minus{}1\n\ represents a phase change of pi radians.\n\ \n\ Note that amplitude response is necessarily zero at @var{f}=0 for type III and\n\ IV filters, and at @var{f}=1 for type II and III filters.\n\ \n\ @item @@respFn\n\ A handle to a `response function' that supplies the desired amplitude response\n\ and error-weighting. This, unlike @var{a} above, allows the response to be\n\ arbitrary (subject to the note above). @qcode{firpm} invokes the response\n\ function according to the following syntax:\n\ \n\ @example\n\ @var{ag} = @qcode{respFn} (@var{n},@var{f},@var{g},@var{w}, @dots{})\n\ [@var{ag} @var{wg}] = @qcode{respFn} (@var{n},@var{f},@var{g},@var{w}, @dots{})\n\ @var{symmetry} = @qcode{respFn} (\"defaults\", @{@var{n},@var{f},@var{g},@var{w}, @dots{}@})\n\ @end example\n\ \n\ where:\n\ @itemize\n\ @item\n\ @var{n} and @var{f} are as given to @qcode{firpm}.\n\ \n\ @item\n\ @var{w} is as given to @qcode{firpm}, or ones if not given.\n\ \n\ @item\n\ @var{ag} and @var{wg} are the desired amplitude and weighting functions\n\ evaluated at each frequency in vector @var{g} (which are frequencies within the\n\ non-transition bands of @var{f}). Returning @var{ag} alone gives uniform\n\ weighting.\n\ \n\ @item\n\ @var{symmetry} is either @qcode{\"even\"} or @qcode{\"odd\"}; this provides an\n\ alternative to using the @var{class} values @qcode{\"symmetric\"}\n\ and @qcode{\"antisymmetric\"}.\n\ \n\ @item\n\ Per the ellipses shown here and above, when @@@var{respFn} is given contained\n\ in a cell-array, any additionally contained values are appended to the\n\ @var{respFn} invocation argument-list.\n\ \n\ @end itemize\n\ \n\ @item w\n\ When used in conjunction with @var{a}, @var{w} is a vector of positive\n\ real-numbers giving error-weightings to be applied at each given band-edge\n\ [w(l1) w(r1) w(l2) w(r2) @dots{}], or for each band [w1 w2 @dots{}]. In the\n\ former case, in-band weighting is determined by linear interpolation between\n\ the given band-edge values. A higher relative error weighting yields a lower\n\ relative error.\n\ \n\ When used in conjunction with @@@var{respFn}, @var{w} is a vector (constrained\n\ as above) that is passed through to @var{respFn}.\n\ \n\ @item class\n\ A string, which may be abbreviated, giving the filter-class:\n\ @itemize\n\ \n\ @item\n\ @qcode{\"symmetric\"} (the default) for type I or II filters,\n\ \n\ @item\n\ @qcode{\"antisymmetric\"} (or @qcode{\"hilbert\"}) for standard type III or IV\n\ filters,\n\ \n\ @item\n\ @qcode{\"differentiator\"} for type III or IV filters with inverted phase and\n\ with error-weighting (further to @var{w}) of 2/f applied in the pass-band(s).\n\ @end itemize\n\ \n\ @item accuracy, @dots{}\n\ Up to three properties contained within a cell-array: @var{accuracy},\n\ @var{persistence}, @var{robustness}, that respectively control how close the\n\ computed filter will be to the ideal minimax solution, the number of\n\ computation iterations over which the required accuracy will be sought, and the\n\ precision of certain internal processing. Each can each be set to a small\n\ positive number (typically @leq{}3), to increase the relevant item; this may\n\ increase computation time, but the need to do so should be rare. A value of 0\n\ can be used to leave an item unchanged.\n\ \n\ Alternatively, setting @var{accuracy} @geq{}16 emulates @sc{matlab}'s\n\ @var{lgrid} argument.\n\ \n\ @end table\n\ \n\ @heading Results\n\ \n\ If a problem occurs during the computation, a diagnostic message will normally\n\ be displayed. If this happens, adjusting @var{accuracy}, @var{persistence}, or\n\ @var{robustness} may provide the solution. Some filters however, may not be\n\ realizable due to machine-precision limitations. If a filter can be computed,\n\ returned values are as follows:\n\ \n\ @table @var\n\ \n\ @item b\n\ A length @var{N}+1 row-vector containing the computed filter coefficients.\n\ \n\ @item minimax\n\ The absolute value of the minimized, maximum weighted error, or this number\n\ negated if the required accuracy could not be achieved.\n\ \n\ @item res\n\ A structure of data relating to the filter computation and a partial\n\ response-analysis of the resultant filter; fields are vectors:\n\ @quotation\n\ @multitable @columnfractions .125 .6\n\ @item @code{fgrid}\n\ @tab Analysis frequencies per @var{f}.\n\ @item @code{des}\n\ @tab Desired amplitude response.\n\ @item @code{wt}\n\ @tab Error weighting.\n\ @item @code{H}\n\ @tab Complex frequency response.\n\ @item @code{error}\n\ @tab Desired minus actual amplitude response.\n\ @item @code{iextr}\n\ @tab Indices of local peaks in @code{error}.\n\ @item @code{fextr}\n\ @tab Frequencies of local peaks in @code{error}.\n\ @end multitable\n\ @end quotation\n\ \n\ @end table\n\ \n\ Using @var{res} is not recommended because it can be slow to compute and, since\n\ the analysis excludes transition-bands, any `anomalies'@footnote{ Tapio\n\ Saram@\"aki, `Finite impulse response filter design', Chapter 4 in `Handbook for\n\ Digital Signal Processing', edited by S. K. Mitra and J. F. Kaiser, John Wiley\n\ and Sons, New York, 1993, pp.@: 155--277.\n\ (@url{https://homepages.tuni.fi/tapio.saramaki/Mitra_Kaiser.pdf})} therein are not easy to\n\ discern. In general, @code{freqz} suffices to check that the response of the\n\ computed filter is satisfactory.\n\ \n\ @heading Examples\n\ @example\n\ @group\n\ # Low-pass with frequencies in Hz:\n\ Fs = 96000; Fn = Fs/2; # Sampling & Nyquist frequencies.\n\ b = firpm (50, [0 20000 28000 48000] / Fn, [1 0]);\n\ @end group\n\ @end example\n\ \n\ @example\n\ @group\n\ # Type IV high-pass:\n\ b = firpm (31, [0 0.5 0.7 1], [0 1], \"antisym\");\n\ @end group\n\ @end example\n\ \n\ @example\n\ @group\n\ # Inverse-sinc (arbitrary response):\n\ b = firpm (20, [0 0.5 0.9 1], @@(n,f,g) ...\n\ deal ((g<=f(2))./sinc (g), (g>=f(3))*9+1));\n\ @end group\n\ @end example\n\ \n\ @example\n\ @group\n\ # Band-pass with filter-response check:\n\ freqz (firpm (40, [0 3 4 6 8 10]/10, [0 1 0]))\n\ @end group\n\ @end example\n\ \n\ Further examples can be found in the @code{firpm} and @code{firpmord}\n\ demonstration scripts.\n\ \n\ @heading Compatibility\n\ Given invalid filter specifications, Octave emits an error and does not produce\n\ a filter; @sc{matlab} in such circumstances may still produce filter\n\ coefficients.\n\ \n\ Unlike with @sc{matlab}, with Octave @var{minimax} can be negative; for\n\ compatibility, take the absolute value.\n\ \n\ @xseealso{firpmord}\n\ \n\ @end deftypefn\n\ ") { int i, arg (0), nargin((int)args.length ()), N; octave_value_list respFnArgs; // The first 3 parameters are mandatory: if (nargin < 3) { print_usage (); return octave_value_list (); } // N: octave_value const & v = args(arg++); if (!v.is_real_scalar () || (N = (int)v.scalar_value ()) != v.scalar_value ()) returnError ("firpm parameter N (filter order) must be an integer"); respFnArgs (RESP_FN_ARG_N) = v; // F[]: ColumnVector freqs; if (!args(arg).is_string () && args(arg).is_real_matrix ()) freqs = args(arg++).vector_value (); if (freqs.numel () < 2 || (freqs.numel () & 1)) returnError ("firpm parameter F (band-edge frequencies) " "must be a real, even-lengthed vector"); int numBands((int)freqs.numel () >> 1); OCTAVE_LOCAL_BUFFER (MmfirBandSpec, bands, numBands); for (i = 0; i < numBands; ++i) bands[i].freqL = freqs(2*i), bands[i].freqR = freqs(2*i+1); respFnArgs (RESP_FN_ARG_F) = freqs; respFnArgs (RESP_FN_ARG_G) = ColumnVector(); // Overwritten later. respFnArgs (RESP_FN_ARG_W) = ColumnVector(numBands, 1); // ditto // @RESP_FN or A[]: octave_fcn_handle * respFnHandle(0); if (args(arg).is_function_handle()) respFnHandle = args(arg++).fcn_handle_value (); else if (octave::signal::iscell(args(arg))) { Cell c(args(arg).cell_value ()); int k(0); if (c.numel () >= 1 && c(k).is_function_handle ()) { respFnHandle = c(k++).fcn_handle_value (); for (; k<c.numel (); ++k) respFnArgs(RESP_FN_ARG_VAR+k-1)=c(k); ++arg; } else returnError ("firpm response function handle is missing"); } else // A[] { ColumnVector amps; if (!args(arg).is_string () && (args(arg).is_real_matrix () || (args(arg).is_real_scalar () && numBands == 1))) amps = args(arg++).vector_value (); bool have2(amps.numel () == numBands * 2); if (amps.numel () != numBands && !have2) returnError ("firpm parameter A must be a real vector of " "response amplitudes: one per band, or per band-edge"); for (i = 0; i < numBands; ++i) if (have2) bands[i].ampL = amps(2*i), bands[i].ampR = amps(2*i+1); else bands[i].ampL = bands[i].ampR = amps(i); } // W[]: if (arg < nargin && !args(arg).is_string () && ( args(arg).is_real_matrix () || (args(arg).is_real_scalar () && numBands == 1))) { ColumnVector weights(args(arg++).vector_value ()); bool have2(weights.numel () == numBands * 2); if (weights.numel () != numBands && !have2) returnError ("firpm parameter W must be a real vector of " "error weights: one per band, or per band-edge"); for (i = 0; i < numBands; ++i) if (have2) bands[i].weightL = weights(2*i), bands[i].weightR = weights(2*i+1); else bands[i].weightL = bands[i].weightR = weights(i); respFnArgs (RESP_FN_ARG_W) = weights; } else for (i = 0; i < numBands; ++i) bands[i].weightL = bands[i].weightR = 1; // CLASS[]: int Class(-1); if (arg < nargin && args(arg).is_string ()) { char const * names[] = { "SYMMETRIC", "BANDPASS", // bandpass is historical "ANTISYMMETRIC", "HILBERT", "DIFFERENTIATOR" }; std::string s(args(arg++).string_value ()); std::transform(s.begin(), s.end(),s.begin(), ::toupper); for (++Class; Class < AL(names) && std::string(names[Class]).substr (0, s.size ()) != s; ++Class); if (!(Class < AL(names))) returnError ("firpm filter-class must be in " "{'%s', '%s' (or '%s'), '%s'}", names[0], names[2], names[3], names[4]); Class >>= 1; // Shift away alternative names. } if (Class<0 && respFnHandle && !respFnHandle->function_value ()->is_anonymous_function ()) { octave_value_list args; args(0) = respFnHandle->fcn_name (); args(1) = Cell(respFnArgs); octave_value_list result(octave::feval ("__firpm_probe__", args, 1)); Class = std::min ((int)result(0).scalar_value (), 2); // For safety. } Class=std::max (Class, 0); // Default is 'symmetric'. // PROPERTIES: static char const * const propertyNames[] = { "ACCURACY", "PERSISTENCE", "ROBUSTNESS", "TARGET", "FLAGS" }; double realProperties[] = { 0, 0, 0, 0, 0 }; if (arg < nargin && octave::signal::iscell(args(arg)) ) { Cell c(args(arg).cell_value ()); if (c.numel ()) { for (i=0; i<AL(realProperties) && i<c.numel (); ++i) { if (!c(i).is_real_scalar ()) returnError ("firpm property %s must be a real scalar", propertyNames[i]); double const d(c(i).double_value ()); realProperties[i] = i || d<16? d : lgrid (d); } ++arg; } } // If any args remain at this point, then something has gone awry: if (arg < nargin) { std::ostringstream os; octave_value tmp(args(arg)); // Need tmp since print is no longer const. tmp.print (os, true); std::string s(os.str ()); size_t p = s.find_last_not_of (" \t\r\n"); if (p != std::string::npos) s.erase (p+1); returnError ("firpm argument # %i is invalid: %s", arg+1, s.c_str ()); } // Attempt to generate the filter: OCTAVE_LOCAL_BUFFER (double, h, N+1); MmfirState state; MmfirReport report(mmfir (h, (MmfirFilterClass)Class, N+1, numBands, bands, realProperties[0], realProperties[1], realProperties[2], realProperties[3], octave::math::nint (realProperties[4]), nargout>2? &state : 0, respFnHandle? mmfirRespFn:0, respFnHandle, &respFnArgs)); // Warn if any controls were clamped: for (i = 0; i < AL(report.controls); ++i) if (report.controls[i] != realProperties[i]) warning ("firpm property %s was clamped to %g", propertyNames[i], report.controls[i]); // Check if a filter was generated: if (report.result >= MmfirInvocationError) returnError ("firpm invocation error: %s", report.text); else if (report.result >= MmfirError) returnError ("firpm failed to make a filter (result=%i)", report.result); // Missed-target is handled silently: if (report.result == MmfirMissedTarget) N = -1; // Return empty B. else // Check if a warning should be issued: if (report.result >= MmfirWarning) warning ("firpm %s (result=%i)", report.text, report.result); // Copy filter coefficients to an Octave row-vector: RowVector b(N+1); for (int i=N+1; i--;) b(i) = h[i]; // Return [B, MINIMAX, RES]: octave_value_list ret; ret(0) = octave_value(b); if (nargout>1) // MINIMAX: ret(1) = octave_value(report.minimax * (report.result? -1 : +1)); if (nargout>2) // RES: { int const S(state.spaceLength); int const P(state.peaksLength); ColumnVector fgrid(S), FP(S), des(S), wt(S), err(S); ColumnVector iextr(P), fextr(P); ComplexColumnVector H(S); double const mulA(Class==2? -1:1); double const mulW(Class==2? .5:1); for (int i=0; i<S; ++i) { fgrid(i)=(state.space)[i].f; FP (i)=(state.space)[i].f*M_PI; des (i)=(state.space)[i].a*mulA; wt (i)=(state.space)[i].w*mulW; } octave_value_list args; octave_scalar one(1); args(0) = ret(0); args(1) = one.as_double (); args(2) = FP; octave_value_list result(octave::feval ("freqz", args, 1)); H=result(0).complex_vector_value (); double const offset(Class? +M_PI/2 : 0); for (int i=0; i<S; ++i) { double const a(offset+N/2.*FP(i)); double const ampResp(H(i).real ()*cos (a) - H(i).imag ()*sin (a)); err(i) = (state.space)[i].a-ampResp; // Negated error. } for (int i=0, j=0; i<P; ++i) { double const f=(state.peaks)[i].f; while (fgrid(j)<f) ++j; int idx=j-(fgrid(j)!=f && fabs (err(j)) < fabs (err(j-1))); iextr(i)=idx+1; fextr(i)=fgrid(idx); } free(state.space); free(state.peaks); octave_map m; m.assign ("fgrid", Cell(1,1,fgrid)); m.assign ("des" , Cell(1,1,des )); m.assign ("wt" , Cell(1,1,wt )); m.assign ("H" , Cell(1,1,H )); m.assign ("error", Cell(1,1,err )); m.assign ("iextr", Cell(1,1,iextr)); m.assign ("fextr", Cell(1,1,fextr)); ret(2) = m; } return ret; } /* Invocation tests %!error <firpm parameter N \(filter order\) must be an integer> firpm (1.1, 2, 3); %!error <firpm parameter N \(filter order\) must be an integer> firpm (i, 2, 3); %!error <firpm parameter N \(filter order\) must be an integer> firpm ([1 2], 2, 3); %!error <firpm parameter F \(band-edge frequencies\) must be a real, even-lengthed vector> firpm (1, 2, 3); %!error <firpm parameter F \(band-edge frequencies\) must be a real, even-lengthed vector> firpm (2, [1 2 3], 3); %!error <firpm parameter F \(band-edge frequencies\) must be a real, even-lengthed vector> firpm (2, [1 i], 3); %!error <firpm parameter A must be a real vector of response amplitudes: one per band, or per band-edge> firpm (1, [1 2], i); %!error <firpm parameter A must be a real vector of response amplitudes: one per band, or per band-edge> firpm (1, [1 2], []); %!error <firpm parameter A must be a real vector of response amplitudes: one per band, or per band-edge> firpm (1, [1 2], [1 2 3]); %!error <firpm parameter A must be a real vector of response amplitudes: one per band, or per band-edge> firpm (1, [1 2], [1 i]); %!error <firpm parameter W must be a real vector of error weights: one per band, or per band-edge> firpm (1, [1 2], 1, []); %!error <firpm parameter W must be a real vector of error weights: one per band, or per band-edge> firpm (1, [1 2], 1, [1 2 3]); %!error <firpm filter-class must be in {'SYMMETRIC', 'ANTISYMMETRIC' \(or 'HILBERT'\), 'DIFFERENTIATOR'}> firpm (1, [1 2], 1, [1 2], 'diffi'); %!error <firpm filter-class must be in {'SYMMETRIC', 'ANTISYMMETRIC' \(or 'HILBERT'\), 'DIFFERENTIATOR'}> firpm (1, [1 2], 1, [1 2], 'hilberts'); %!error <firpm property ACCURACY must be a real scalar> firpm (1, [1 2], 1, [1 2], {'antisymmetric'}); %!error <firpm property PERSISTENCE must be a real scalar> firpm (1, [1 2], 1, [1 2], {0, [1 1]}); %!error <firpm argument # 4 is invalid: \(0,1\)> firpm (1, [1 2], 1, i); %!error <firpm argument # 4 is invalid: {}\(0x0\)> firpm (2, [0 1], [1 0], {}, 1); %!warning <firpm property ROBUSTNESS was clamped to 0> firpm (1, [.1 .9], 1, [1 2], {0,0,-1}); %!error <firpm failed to make a filter \(result=[456]\)> firpm (2, [.1 .9], 1); %!error <band-edge frequencies must increase in \[0,1\]> firpm (1, [1 2], 1, [1 2], 'diff'); %!error <type II/III Nyquist amplitude response must be 0> firpm (81, [0 .2 .3 1], [1 -1]); %!error <type III/IV DC amplitude response must be 0> firpm (81, [0 .2 .3 1], [-1 0], 'a'); Functional tests The first 6 tests exercise all 6 filter type (3 classes, odd/even-order). The b0 values come from a reference implementation. %!test b0 = [ %! -0.01306844322361 %! -0.00576879446491 %! 0.00838126690529 %! -0.04580777271297 %! -0.03857170268345 %! -0.06564404551953 %! -0.03895798206108 %! 0.10957536253443 %! -0.09596565600341 %! -0.04596208116089 %! 0.25250866248593 %! -0.04596208116089 %! -0.09596565600341 %! 0.10957536253443 %! -0.03895798206108 %! -0.06564404551953 %! -0.03857170268345 %! -0.04580777271297 %! 0.00838126690529 %! -0.00576879446491 %! -0.01306844322361 %! ]'; %! [b m] = firpm (20, [0 .2 .3 .4 .5 .7 .9 1], [0 .2 0 0 .5 .7 0 0], [1 4 16 64], 'b', {256}); %! assert (b0, b, 1e-5); assert (m, 0.21493, -5e-5); %!test b0 = [ %! -0.00025230206347 %! -0.01634334994986 %! 0.02291167335102 %! 0.04226921430992 %! 0.01542390317553 %! 0.03368560169380 %! -0.07263229297607 %! 0.02402776579442 %! 0.10971999889298 %! -0.19495185723437 %! 0 %! 0.19495185723437 %! -0.10971999889298 %! -0.02402776579442 %! 0.07263229297607 %! -0.03368560169380 %! -0.01542390317553 %! -0.04226921430992 %! -0.02291167335102 %! 0.01634334994986 %! 0.00025230206347 %! ]'; %! [b m] = firpm (20, [0 .2 .3 .4 .5 .7 .9 1], [0 .2 0 0 .5 .7 0 0], [1 4 16 64], 'h', {256}); %! assert (b0, b, 1e-5); assert (m, 0.19499, -5e-5); %!test b0 = [ %! -0.00377491711564 %! 0.00749876297245 %! -0.01857378491500 %! -0.02436623414958 %! 0.02123220611895 %! -0.00133887288041 %! 0.08769905297256 %! -0.01438000909341 %! -0.11006930405280 %! 0.20125570410204 %! 0 %! -0.20125570410204 %! 0.11006930405280 %! 0.01438000909341 %! -0.08769905297256 %! 0.00133887288041 %! -0.02123220611895 %! 0.02436623414958 %! 0.01857378491500 %! -0.00749876297245 %! 0.00377491711564 %! ]'; %! [b m] = firpm (20, [0 .2 .3 .4 .5 .7 .9 1], [0 .2 0 0 .5 .7 0 0], [1 4 16 64], 'd', {256}); %! assert (b0, b, 1e-5); assert (m, 0.49129, -5e-5); %!test b0 = [ %! 0.00110112420442 %! 0.00032786748236 %! 0.03890416611405 %! 0.02776952210339 %! -0.00513106293312 %! 0.00821219616448 %! -0.05050622257469 %! 0.07143158068636 %! 0.04353182141693 %! -0.17253512167493 %! 0.13296924791431 %! 0.13296924791431 %! -0.17253512167493 %! 0.04353182141693 %! 0.07143158068636 %! -0.05050622257469 %! 0.00821219616448 %! -0.00513106293312 %! 0.02776952210339 %! 0.03890416611405 %! 0.00032786748236 %! 0.00110112420442 %! ]'; %! [b m] = firpm (21, [0 .2 .3 .4 .5 .7 .9 1], [0 .2 0 0 .5 .7 0 0], [1 4 16 64], 'b', {256}); %! assert (b0, b, 1e-5); assert (m, 0.19215, -5e-5); %!test b0 = [ %! 0.00688473243750 %! -0.00142370547227 %! 0.00792901881787 %! 0.05914568352388 %! 0.03038499582274 %! 0.03374098557746 %! -0.02191978751853 %! -0.08702247834731 %! 0.10568616843372 %! -0.06074859970379 %! -0.18689246939614 %! 0.18689246939614 %! 0.06074859970379 %! -0.10568616843372 %! 0.08702247834731 %! 0.02191978751853 %! -0.03374098557746 %! -0.03038499582274 %! -0.05914568352388 %! -0.00792901881787 %! 0.00142370547227 %! -0.00688473243750 %! ]'; %! [b m] = firpm (21, [0 .2 .3 .4 .5 .7 .9 1], [0 .2 0 0 .5 .7 0 0], [1 4 16 64], 'h', {256}); %! assert (b0, b, 1e-5); assert (m, 0.20726, -5e-5); %!test b0 = [ %! -0.00164508269033 %! 0.00067200008069 %! 0.00268424782721 %! -0.03510524314006 %! 0.00455581822868 %! 0.00862256307919 %! 0.03221163698642 %! 0.08429446688809 %! -0.12214036419364 %! 0.04373834279952 %! 0.19029552670347 %! -0.19029552670347 %! -0.04373834279952 %! 0.12214036419364 %! -0.08429446688809 %! -0.03221163698642 %! -0.00862256307919 %! -0.00455581822868 %! 0.03510524314006 %! -0.00268424782721 %! -0.00067200008069 %! 0.00164508269033 %! ]'; %! [b m] = firpm (21, [0 .2 .3 .4 .5 .7 .9 1], [0 .2 0 0 .5 .7 0 0], [1 4 16 64], 'd', {256}); %! assert (b0, b, 1e-5); assert (m, 0.47868, -5e-5); %!test b0=[ %! -0.01402452049012097 %! 0.001876620211412957 %! 0.03037229727821556 %! -0.01238680025691372 %! -0.0170173995332925 %! -0.001299983105532321 %! -0.01887047540094186 %! 0.0478657090945251 %! 0.02646457824791903 %! -0.05579347345500663 %! -0.001118815789852797 %! -0.05887946612620026 %! 0.03589780658038378 %! 0.229839817358415 %! -0.1717538614573135 %! -0.2842595261696291 ]'; %! [b m] = firpm (31 , [0 .3 .4 .7 .8 1], [0 1 0], [10 1 10], 'a', {1}); %! assert (b, [b0 fliplr(-b0)], 5e-9); %! assert (m, 0.059734, -5e-5); %!test b0 = [ %! -8.876086291046802e-04 %! 2.355569104748801e-02 %! -8.241671888096303e-04 %! -4.470074798008300e-02 %! -2.808154545387648e-03 %! 8.170132813894931e-02 %! -1.058582827015804e-03 %! -1.777420298924492e-01 %! -2.265334116571183e-02 %! 5.239577857603830e-01 %! 8.489449590726375e-01 %! 5.239577857603830e-01 %! -2.265334116571183e-02 %! -1.777420298924492e-01 %! -1.058582827015804e-03 %! 8.170132813894931e-02 %! -2.808154545387648e-03 %! -4.470074798008300e-02 %! -8.241671888096303e-04 %! 2.355569104748801e-02 %! -8.876086291046802e-04 %! ]'; %! [b m] = firpm (N=20, [0 .4 .6 1], {@(n,f,g,w,v1) deal ((log2 (v1/n+w(2)+g)).*(g<=f(2)), ones (size(g))),2*N}); %! assert (b0, b, 1e-5); assert (m, .0210628, -5e-5); %!test [b m] = firpm (40, [0 .5 .6 1], [1 0]); %! assert (m, 0.010304, -5e-5); %!test [b m] = firpm (40, [0 .25 .3 .6 .65 1], [0 1 0]); %! assert (m, 0.055834, -5e-5); %!test [b m] = firpm (30, [0 .2 .4 .6 .8 1], [1 .5 0]); %! assert (m, 5.6277e-04, -5e-5); %!test %! [b m] = firpm (40, [0 .2 .3 .4 .5 .6 .7 .8 .9 1], [1 0 1 0 1], [11 100 7 10 5]); %! assert (m, 0.25723, -5e-5); %!test [b m] = firpm (80, [0 .2 .3 1], [1 -1]); %! assert (m, 6.6123e-04, -5e-5); %!test [b m] = firpm (40, [0 2.5/pi], [0 2.5], [.5], 'differentiator'); %! assert (m, 2.5226e-06, -5e-5); %!test [b m] = firpm (59, [0 .2 .3 1], [0 1 0 0], 'd'); %! assert (m, 0.0073785, -5e-5); %!test [b m] = firpm (31, [0 .5 .7 1], [0 1], 'antisymmetric'); %! assert (m, 0.0015660, -5e-5); %!test assert (firpm (31, [0 .5 .7 1], [0 1], 'antisymmetric'), firpm (31, [0 .5 .7 1], [0 1], 'hilbert')) %!test [b m] = firpm (30, [.1 .9], 1, 'antisymmetric'); %! assert (m, 0.0027064, -5e-5); %!test [b m] = firpm (1000, [0 .4 .41 1], [1 0]); %! assert (m, 5.2892e-05, -5e-5); %!test [b m] = firpm (120, [0 .5 .55 .75 .75 1], [1 0 0], [1 1 4 64 64 64]); %! assert (m, 0.0048543, -5e-5); %!test [b m] = firpm (11, [0 2*.45], .5, 'symmetric'); %! assert (m, 0.045066, -5e-5); %!warning <firpm not-converged \(result=1\)> firpm (298, [0 .28 .33 .48 .53 1], [0 1 0], [93 68 89], {50,-1}); %!test [b m] = firpm (298, [0 .28 .33 .48 .53 1], [0 1 0], [93 68 89], {50}); %! assert (m, 6.86583e-05, -5e-5); %!test assert (firpm (11, [0 2*.45], .5, 'symmetric'), firpm (11, [0 2*.45], .5, 'bandpass')) %!test assert (firpm (11, [0 2*.45], .5, 'symmetric'), firpm (11, [0 2*.45], .5)) %!assert (firpm (20, [0 .3 .5 1], [1 1 0 0]), firpm (20, [0 .3 .5 1], [1 0])) %!test assert ( %! firpm (30, [0.1 0.9], 1, "antisymmetric"), %! firpm (30, [0.1 0.9], 1, "hilbert")) %!test assert ( %! firpm (11, [0 0.9], 1, {1}), %! firpm (11, [0 0.9], 1, {64})) %!test %! [b1 m1] = firpm (20, [0 0.4 0.5 1], [1 0], [1 1/8]); %! [b2 m2] = firpm (20, [0 0.4 0.5 1], [1 0], [8 1]); %! assert (b1, b2) %! assert (m1 * 8, m2) %! %!demo %! %! N=38; F=[0 .47 .53 1]; A=[1 1 0 0]; W=[1 1]; ant=0; %! [b m r] = firpm (N, F, A, W, 'sa'(1+ant)); %! %! mul=[1 i](1+ant); %! clf; [h f] = freqz (b); plot (f/pi, real (mul*h.*exp (i*f*N/2)), %! f=F(1:2),(a=A(1:2))-(M=m/W(1)),'r', f, a+M,'r', %! f=F(3:4),(a=A(3:4))-(M=m/W(2)),'r', f, a+M,'r', %! r.fextr, real ((mul*r.H.*exp (i*r.fgrid*pi*N/2))(r.iextr)),'ko') %! grid on; axis ([0 1 -.1 1.1]); set (gca, 'xtick', [0:.1:1], 'ytick', [0:.1:1]) %! title (sprintf ('firpm type-I low-pass filter (order=%i)', length (b) - 1)); %! ylabel ('Amplitude response'); xlabel ('Frequency (normalized)') %! axes ('position', [.58 .35 .3 .5]) %! stem (b); grid off %! title ('Impulse response') %! axis ([1 length(b) -.15 .55]) %! %-------------------------------------------------- %! % Figure shows transfer and impulse-response of %! % half-band filter design. %! %!demo %! %! N=41; F=[0 .1 .16 .34 .4 1]; A=[0 0 1 1 0 0]; W=[1 3 2]; ant=1; %! [b m r] = firpm (N, F, A, W, 'sa'(1+ant)); %! %! mul=[1 i](1+ant); %! clf; [h f] = freqz (b); plot (f/pi, real (mul*h.*exp (i*f*N/2)), %! f=F(1:2),(a=A(1:2))-(M=m/W(1)),'r', f, a+M,'r', %! f=F(3:4),(a=A(3:4))-(M=m/W(2)),'r', f, a+M,'r', %! f=F(5:6),(a=A(5:6))-(M=m/W(3)),'r', f, a+M,'r', %! r.fextr, real ((mul*r.H.*exp (i*r.fgrid*pi*N/2))(r.iextr)),'ko') %! grid on; axis ([0 1 -.1 1.1]); set (gca, 'xtick', [0:.1:1], 'ytick', [0:.1:1]) %! title (sprintf ('firpm type-IV weighted band-pass filter (order=%i)', length (b) - 1)); %! ylabel ('Amplitude response'); xlabel ('Frequency (normalized)') %! axes ('position', [.55 .4 .3 .4]) %! stem (b); grid off %! title ('Impulse response') %! axis ([1 length(b) -.3 .3]) %! %-------------------------------------------------- %! % Figure shows transfer and impulse-response of %! % band-pass filter design. %! %!demo %! %! curve = @(a,b,y,z,x) z*(b-a)./((x-a)*z/y+b-x); %! respFn = @(n,f,g,w,curve) deal (g>=f(3) & g<=f(4), ... %! (g<=f(2)).*curve (f(2),f(1),w(1),w(3),g) + ... %! (g>=f(3) & g<=f(4))*w(2) + ... %! (g>=f(5) & g<=f(6)).*curve (f(5),f(6),w(1),w(3),g) + ... %! (g>f(7))*w(4)); % NB contiguous bands so > not >=. %! b=firpm (127, [0 .2 .24 .26 .3 .5 .5 1], {respFn, curve}, [10 1 100 10]); %! %! clf; [h f]=freqz (b); plot (f/pi, 20*log10 (abs (h))) %! grid on; axis ([0 1 -90 5]); set (gca, 'xtick', [0:.1:1], 'ytick', [-80:10:0]) %! title (sprintf ('firpm type-II band-pass filter with shaped stop-bands (order=%i)', length (b) - 1)); %! ylabel ('Magnitude response (dB)'); xlabel ('Frequency (normalized)') %! %-------------------------------------------------- %! % Figure shows transfer of band-pass filter design %! % with shaped error-weight in the stop-bands. %! %!demo %! %! b = firpm (40, [0 .1 .3 1], [-1 1]); %! %! clf; [h f] = freqz (b,1,2^14); plot (f/pi, 20*log10 (abs (h))) %! grid on; axis ([0 1 -60 5]); set (gca, 'xtick', [0:.1:1]) %! title (sprintf ('firpm type-I notch filter (order=%i)', length (b) - 1)); %! ylabel ('Magnitude response (dB)'); xlabel ('Frequency (normalized)') %! axes ('position', [.42 .55 .45 .2]) %! plot (f/pi, 20*log10 (abs (h))); grid on %! axis ([0 1 -(e=1e-2) e]) %! title ('Pass-bands detail') %! axes ('position', [.42 .2 .45 .2]) %! stem (b); grid off %! title ('Impulse response') %! axis ([1 length(b) -.45 .65]) %! %-------------------------------------------------- %! % Figure shows transfer and impulse-response of %! % notch filter design. %! %!demo %! %! b = firpm (1000, [0 .4 .41 1], [1 0], {1}); %! %! clf; [h f] = freqz (b, 1, 2^17); plot (f/pi, 20*log10 (abs (h))) %! title (sprintf ('firpm type-I brick-wall low-pass filter (order=%i)', length (b) - 1)); %! ylabel ('Magnitude response (dB)'); xlabel ('Frequency (normalized)') %! grid on; axis ([0 1 -100 5]); set (gca, 'xtick', [0:.1:1]) %! axes ('position', [.55 .6 .3 .2]) %! plot (f/pi, 20*log10 (abs (h))); grid on %! title ('Details') %! axis ([.38 .401 -(e=1e-3) e]) %! axes ('position', [.55 .3 .3 .2]) %! plot (f/pi, 20*log10 (abs (h))); grid on %! axis ([.409 .43 -86 -85]) %! axes ('position', [.2 .35 .2 .3]) %! semilogy (abs (b)); grid off %! title ('Impulse response magnitude') %! axis ([0 length(b)+1 1e-6 1]) %! %-------------------------------------------------- %! % Figure shows transfer and impulse-response of %! % brick-wall low-pass filter design. %! %!demo %! %! b = firpm (20, [0 2.5]/pi, [0 2.5], 'differentiator'); %! %! clf %! [h f] = freqz (b,1,2^12); %! subplot (2, 1, 1) %! plot (f, abs (h)); grid on %! title (sprintf ('firpm type-III differentiator filter (order=%i)', length (b) - 1)); %! ylabel ('Magnitude response'); xlabel ('Frequency (radians/sample)') %! axis ([0 pi 0 pi]) %! subplot (2, 1, 2) %! plot (f, abs (abs (h)./f-1)); grid on %! axis ([0 2.5 0 1e-3]) %! title ('Pass-band error (inverse-f weighted)') %! %-------------------------------------------------- %! % Figure shows transfer of differentiator filter design. %! % above: full-band %! % below: detail of pass-band error (inverse-f weighted) %! %!demo %! %! b = firpm (30, [.05 .95], 1, 'antisymmetric'); %! %! clf; [h f] = freqz (b); plot (f/pi, abs (h)) %! grid on; axis ([0 1 0 1.1]); set (gca, 'xtick', [0:.1:1], 'ytick', [0:.1:1]) %! title (sprintf ('firpm type-III hilbert transformer filter (order=%i)', length (b) - 1)); %! ylabel ('Magnitude response'); xlabel ('Frequency (normalized)') %! axes ('position', [.3 .25 .45 .4]) %! stem (b); grid off %! title ('Impulse response') %! axis ([1 length(b) -.7 .7]) %! %-------------------------------------------------- %! % Figure shows transfer and impulse-response of %! % hilbert filter design. %! %!demo %! cic = @(f) (sin (pi*(f+eps*!f)/2)./sin (pi*(f+eps*!f)/2/10)/10).^4; %! %! if compare_versions(OCTAVE_VERSION, '6', '<') %! eval('b = firpm (30, [0 .5 .7 1], @(n,f,g, w) deal (a=(g<=f(2))./cic (g), 1./(a+!a)));') %! else %! function [ag wg] = resp (n,f,g,w) ag = (g<=f(2))./cic (g); wg = 1./(ag+!ag); endfunction %! b = firpm (30, [0 .5 .7 1], @resp); %! endif %! %! clf; [h f]=freqz (b); plot (f/=pi, 20*log10 (abs (h))) %! grid on; axis ([0 1 -60 6]); set (gca, 'xtick', [0:.1:1]) %! title (sprintf ('firpm type-I CIC-compensation filter (order=%i)', length (b) - 1)); %! ylabel ('Magnitude response (dB)'); xlabel ('Frequency (normalized)') %! axes ('position', [2 3 4 3]/10) %! plot (f, 20*log10 (abs (h).*cic (f))); axis ([0 .55 -.04 .04]); grid on %! title ('Compensated filter response') %! %-------------------------------------------------- %! % Figure shows transfer details of CIC-compensation %! % filter design. %! %!demo %! clf; n=30; Fp=.8; for d=linspace (-.5, .5, 10) %! %! b = firpm (n, [0 Fp], {@(n,f,g,w,d,Fp) (g<=Fp).*cos (g*pi*d),d,Fp})... %! + firpm (n, [0 Fp], {@(n,f,g,w,d,Fp) (g<=Fp).*sin (g*pi*d),d,Fp}, 'a'); %! %! [g f]=grpdelay (b); %! set (gca,'ColorOrderIndex',1); plot (f/pi, g-n/2); hold ('on'); end; %! hold ('off'); grid on; axis ([0 1 -.6 .6]); set (gca, 'xtick', [0 Fp 1], 'ytick', [-.5:.5:.5]) %! title (sprintf ('firpm type-I fractional-delay filters (order=%i)', length (b) - 1)); %! ylabel ('Fractional-delay (samples)'); xlabel ('Frequency (normalized)') %! %-------------------------------------------------- %! % Figure shows delay response of (non-linear-phase) %! % filter designs with progressive fractional-delay. */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/src/medfilt1.cc������������������������������������������������������������������������0000644�0000000�0000000�00000040612�14673270174�012546� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright (C) 2015-2016 Lachlan Andrew, Monash University 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; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ /* Author: Lachlan Andrew <lachlanbis@gmail.com> Created: 2015-12-13 */ /** @file libinterp/corefcn/medfilt1.cc One dimensional median filter, for real double variables. */ #include <algorithm> #include <memory> #include "oct.h" #include "defun-dld.h" #include "error.h" #include "ov.h" #include "octave-compat.h" enum nan_opt_type { NAN_OPT_INCLUDE, NAN_OPT_OMIT }; enum pad_opt_type { PAD_OPT_ZERO, PAD_OPT_TRUNCATE }; // Keep a sorted sliding window of values. // There is no error checking, to keep things fast. // Keeps NaNs at the "top" (after Inf) class sorted_window { std::unique_ptr<double[]> buf; octave_idx_type numel; octave_idx_type numNaN; bool nan_if_any_is; // Return the index of target in the window, from element start to the end // FIXME: for large n, use binary search, but be careful to keep NaN at end octave_idx_type find (double target, octave_idx_type start = 0) { octave_idx_type i; for (i = start; i < numel; i++) if (!(buf[i] < target)) { if (target == target) // We've found the target. return i; else return numel; // target is NaN; add it to the end. } return numel; } public: // Create sorted window with maximum size width. // If skip_nan then the median will consider only valid numbers within // the window. sorted_window (octave_idx_type width, bool skip_nan = true) : buf (new double [width]), numel (0), numNaN (0), nan_if_any_is (! skip_nan) { } // Initialize to contain seed, and zeros additional zeros. void init (const double *seed, octave_idx_type num, octave_idx_type stride, octave_idx_type zeros = 0) { numel = zeros; numNaN = 0; std::fill_n (&buf[0], zeros, 0.0); // Insert from seed. Could sort if it is large num *= stride; for (octave_idx_type i = 0; i < num; i += stride) add (seed[i]); } // Take item prev from the window and replace it by next. // Assumes prev is in the window. void replace (double next, double prev) { octave_idx_type n_pos, p_pos; if (next < prev) { n_pos = find (next); p_pos = find (prev, n_pos); if (n_pos != p_pos) std::copy_backward (&buf[n_pos], &buf[p_pos], &buf[p_pos + 1]); } else if (next > prev) { p_pos = find (prev); n_pos = find (next, p_pos); if (n_pos != p_pos) { std::copy (&buf[p_pos + 1], &buf[n_pos], &buf[p_pos]); n_pos--; // position shifts due to deletion of p_pos } } else if (next != prev) // one is NaN. { if (next == next) { n_pos = find (next); std::copy_backward (&buf[n_pos], &buf[numel - 1], &buf[numel]); numNaN--; } else if (prev == prev) { p_pos = find (prev); std::copy (&buf[p_pos + 1], &buf[numel], &buf[p_pos]); n_pos = numel - 1; numNaN++; } else return; // fallthrough case (next, prev both NaN) } else // fallthrough case (next == prev) requires no action. return; buf [n_pos] = next; } // Expand the window by one element, inserting next. // This will crash if this exceeds the allocation of buf. void add (double next) { octave_idx_type n_pos; if (next == next) // not NaN { n_pos = find (next); if (n_pos < numel) std::copy_backward (&buf[n_pos], &buf[numel], &buf[numel + 1]); } else // NaN stored at end, so nothing to move. { n_pos = numel; numNaN++; } buf[n_pos] = next; numel++; } // Reduce the window by one element, deleting prev. // This will crash if the window is already empty void remove (double prev) { octave_idx_type p_pos; if (prev == prev) { p_pos = find (prev); std::copy (&buf[p_pos + 1], &buf[numel], &buf[p_pos]); } else // NaN stored at end, so nothing to move. numNaN--; numel--; } // The middle value if numel-numNaN is odd, // or the mean of the two middle values if numel-numNaN is even. // This will crash if the window is empty. double median (void) { double retval = 0; octave_idx_type non_nan_window = numel; double last = buf [numel-1]; if (last != last) // if NaN { if (nan_if_any_is) retval = last; else { non_nan_window = numel - numNaN; if (non_nan_window == 0) retval = last; } } if (retval == 0) // if result is not NaN { if (non_nan_window & 1) retval = buf[non_nan_window >> 1]; else { octave_idx_type mid = non_nan_window >> 1; retval = (buf[mid - 1] + buf[mid]) / 2; } } return retval; } }; // Median filter on a single vector, // starting at x with values spaced by stride. // The output is placed into y, with the same stride. static inline void medfilt1_vector (double *x, double *y, octave_idx_type n, octave_idx_type len, octave_idx_type stride, octave_idx_type leading, octave_idx_type trailing, octave_idx_type start_middle, octave_idx_type end_middle, octave_idx_type last, octave_idx_type initial_fill, pad_opt_type pad_opt, sorted_window& sw) { sw.init (x, initial_fill, stride, (pad_opt == PAD_OPT_ZERO) ? (n - initial_fill) : 0); // Partial window at the start if (pad_opt == PAD_OPT_ZERO) for (octave_idx_type i = 0; i < start_middle; i += stride) { sw.replace (x[i + leading], 0); y[i] = sw.median (); } else for (octave_idx_type i = 0; i < start_middle; i += stride) { sw.add (x[i + leading]); y[i] = sw.median (); } if (n < len) // Full sized window for (octave_idx_type i = start_middle; i < end_middle; i += stride) { sw.replace (x[i + leading], x[i - trailing]); y[i] = sw.median (); } else { // All of x is in the window double m = sw.median (); for (octave_idx_type i = start_middle; i < end_middle; i += stride) y[i] = m; } // Partial window at the end if (pad_opt == PAD_OPT_ZERO) for (octave_idx_type i = end_middle; i < last; i += stride) { sw.replace (0, x[i - trailing]); y[i] = sw.median (); } else for (octave_idx_type i = end_middle; i < last; i += stride) { sw.remove (x[i - trailing]); y[i] = sw.median (); } } DEFUN_DLD(medfilt1, args, , " -*- texinfo -*- \n\ @deftypefn {} {@var{y} =} medfilt1 (@var{x}, @var{n})\n\ @deftypefnx {} {@var{y} =} medfilt1 (@var{x}, @var{n}, [], @var{dim})\n\ @deftypefnx {} {@var{y} =} medfilt1 (..., @var{NaN_flag}, @var{padding})\n\ \n\ Apply a one dimensional median filter with a window size of @var{n} to\n\ the data @var{x}, which must be real, double and full.\n\ For @var{n} = 2m+1, @var{y}(i) is the median of @var{x}(i-m:i+m).\n\ For @var{n} = 2m, @var{y}(i) is the median of @var{x}(i-m:i+m-1).\n\ \n\ The calculation is performed over the first non-singleton dimension, or over\n\ dimension @var{dim} if that is specified as the fourth argument. (The third\n\ argument is ignored; Matlab used to use it to tune its algorithm.)\n\ \n\ @var{NaN_flag} may be @qcode{omitnan} or @qcode{includenan} (the default).\n\ If it is @qcode{omitnan} then any NaN values are removed from the window\n\ before the median is taken.\n\ Otherwise, any window containing an NaN returns a median of NaN.\n\ \n\ @var{padding} determines how the partial windows at the start and end of\n\ @var{x} are treated.\n\ It may be @qcode{truncate} or @qcode{zeropad} (the default).\n\ If it is @qcode{truncate} then the window for @var{y}(i) is\n\ the intersection of the window stated above with 1:length(@var{x}).\n\ If it is @qcode{zeropad}, then partial windows have additional zeros\n\ to bring them up to size @var{n}.\n\ \n\ @seealso{filter, medfilt2}\n\ @end deftypefn") { if (args.length () < 1) print_usage (); octave_idx_type n = 3, dim = 0; nan_opt_type nan_opt = NAN_OPT_INCLUDE; pad_opt_type pad_opt = PAD_OPT_ZERO; int nargin = args.length (); Array<double> signal = args(0).array_value (); // parse arguments. // FIXME: This allows repeated arguments like // medfilt1(..., "truncate", "zeropad") while (args(nargin - 1).is_string ()) { if (nargin < 2) print_usage (); std::string s = args(nargin - 1).string_value (); if (! strcasecmp (s.c_str (), "omitnan")) nan_opt = NAN_OPT_OMIT; else if (! strcasecmp (s.c_str (), "truncate")) pad_opt = PAD_OPT_TRUNCATE; else if (strcasecmp (s.c_str (), "includenan") && strcasecmp (s.c_str (), "zeropad")) // the defaults error ("medfilt1: Invalid NAN_FLAG or PADDING value '%s'", s.c_str ()); nargin--; // skip this for parsing the numeric args } if (nargin >= 2) { if (octave::signal::isnumeric (args(1))) { if (args(1).numel () != 1 || octave::signal::iscomplex (args(1))) error ("medfilt1: N must be a real scalar"); else n = args(1).idx_type_value (); } else error ("medfilt1: Invalid type for N: %s", args(1).type_name ().c_str ()); if (nargin >= 4) { if (octave::signal::isnumeric (args(3))) { if (args(3).numel () != 1) error ("medfilt1: DIM must be a scalar"); else if (octave::signal::iscomplex (args(3))) error ("medfilt1: DIM must be real"); dim = round (args(3).double_value ()); if (dim != args(3).double_value ()) error ("medfilt1: DIM must be an integer, not %g", args(3).double_value ()); //if (dim < 1 || dim > signal.dims ().length ()) if (dim < 1) error ("medfilt1: DIM must be positive, not %ld", static_cast<long> (dim)); } else error ("medfilt1: Invalid type for DIM: %s", args(1).type_name ().c_str ()); if (nargin > 4) error ("medfilt1: Too many input arguments"); } } // Guard again divide-by-zero later. // This is the last "early return". if (args(0).numel () == 0) return ovl (args(0)); // The following code is based on filter.cc dim_vector x_dims = args(0).dims (); if (dim < 1) dim = x_dims.first_non_singleton (); else dim--; // make 0-based, not 1-based octave_idx_type x_len = x_dims (dim); octave_idx_type x_stride = 1; for (octave_idx_type i = 0; i < dim; i++) x_stride *= x_dims(i); MArray<double> x = args(0).array_value (); MArray<double> retval; retval.resize (x_dims, 0.0); double *p_in = x.fortran_vec (); double *p_out = retval.fortran_vec (); sorted_window sw (n, nan_opt == NAN_OPT_OMIT); // how far ahead should data be put in window octave_idx_type leading = ((n - 1) / 2) * x_stride; // how far back should data be removed from wdw octave_idx_type trailing = n * x_stride - leading; // last position in this slice octave_idx_type last = x_len * x_stride; // start of the "middle" phase with fixed window size octave_idx_type start_middle; // end of the "middle" phase with fixed window size octave_idx_type end_middle; // start window with x(1:initial_fill) octave_idx_type initial_fill = (n - 1) / 2; if (n < x_len) // small window: { // The middle phase is when replacing window elements. start_middle = trailing; end_middle = last - leading; } else // big window: { // The middle phase has whole input in the window. if (n < 2 * x_len) { start_middle = last - leading; end_middle = trailing; } else // huge window: all answers are just the median of x. { start_middle = 0; end_middle = last; initial_fill = x_len; } } octave_idx_type x_num = x_dims.numel () / x_len; octave_idx_type x_offset = 0, inner_offset = 0; for (octave_idx_type num = 0; num < x_num; num++) { medfilt1_vector (p_in + x_offset, p_out + x_offset, n, x_len, x_stride, leading, trailing, start_middle, end_middle, last, initial_fill, pad_opt, sw); if (x_stride == 1) x_offset += x_len; else { x_offset++; if (++inner_offset == x_stride) { inner_offset = 0; x_offset += x_stride * (x_len - 1); } } } return ovl (retval); } /* %!assert (medfilt1 ([1 2 3 4 3 2 1]), [1 2 3 3 3 2 1]); %!assert (medfilt1 ([1 2 3 4 3 2 1]'), [1 2 3 3 3 2 1]'); %!assert (medfilt1 ([1 2 3 4 3 2 1], "truncate"), [1.5 2 3 3 3 2 1.5]); %!assert (medfilt1 ([-1 2 3 4 3 -2 1], "truncate"), [0.5 2 3 3 3 1 -0.5]); %!assert (medfilt1 ([-1 2 3 4 3 -2 1], "zeropad"), [0 2 3 3 3 1 0]); %!assert (medfilt1 ([]), []); %!test %! A = [1 2 3 ; 6 5 4 ; 6 5 2 ]; %! assert (medfilt1 (A,4,[],2), [0.5 1.5 1.5; 2.5 4.5 4.5; 2.5 3.5 3.5]); %! assert (medfilt1 (A,4,[],1), [0.5 3.5 3.5; 1 3.5 3.5; 1.5 2.5 2.5]'); %! assert (medfilt1 (A,3,[],1), [1 2 3; 6 5 3; 6 5 2]); %!test %! A = [ Inf 4 -4 NaN -1 -1 -3 -2 1 -Inf]; %! B = medfilt1 (A, 7, [], 1, 'includenan', 'zeropad'); %! assert (B, [0, 0, 0, NaN, 0, 0, 0, 0, 0, 0]); %! B = medfilt1 (A, 7, [], 2, 'includenan', 'zeropad'); %! assert (B, [NaN, NaN, NaN, NaN, NaN, NaN, NaN, -1, -1, 0]); %! B = medfilt1 (A, 7, [], 2, 'includenan', 'truncate'); %! assert (B, [NaN, NaN, NaN, NaN, NaN, NaN, NaN, -1.5, -2, -2.5]); %! B = medfilt1 (A, 7, [], 2, 'omitnan', 'zeropad'); %! assert (B, [0, 0, -0.5, -1, -1.5, -1.5, -1.5, -1, -1, 0]); %! B = medfilt1 (A, 7, [], 2, 'omitnan', 'truncate'); %! assert (B, [4, 1.5, -1, -1, -1.5, -1.5, -1.5, -1.5, -2, -2.5]); %!test %! A = medfilt1 ([ NaN NaN -Inf], 4, [], 2, 'omitnan', 'truncate'); %! assert (A, [NaN, -Inf, -Inf]); %!test %! A = medfilt1 ([-2 Inf -2; 1 3 -Inf; 1 0 -Inf], 1, [], 2); %! assert (A, [-2 Inf -2; 1 3 -Inf; 1 0 -Inf]); %!test %! A = medfilt1 ([-Inf 0 -3; Inf 1 NaN], 9, [], 1); %! assert (A, [0, 0, NaN; 0, 0, NaN]); %! A = medfilt1 ([-Inf 0 -3; Inf 1 NaN], 9, [], 1, 'omitnan', 'truncate'); %! assert (A, [NaN, 0.5, -3; NaN, 0.5, -3]); %!test %! A = medfilt1 ([Inf -3 Inf Inf 0 -2; Inf 1 NaN 5 5 -3], 3, [], 1); %! assert (A, [Inf, 0, NaN, 5, 0, -2; Inf, 0, NaN, 5, 0, -2]); %!test %! A = medfilt1 ([3 3 7 5 6]', 5, [], 1, 'omitnan', 'truncate'); %! assert (A, [3, 4, 5, 5.5, 6]'); %! A = medfilt1 ([3 3 7 5 6]', 5, [], 2, 'omitnan', 'truncate'); %! assert (A, [3, 3, 7, 5, 6]'); %!test %! A = medfilt1 ([3 1 4 1 3], 3, 'omitnan', 'truncate'); %! assert (A, [2, 3, 1, 3, 2]); %!test %! A = medfilt1 ([3 1 4 1 3], 6, 'omitnan', 'truncate'); %! assert (A, [3, 2, 3, 3, 2]); %!test %! A = medfilt1 ([1 2 3 4 4 3 2 1; 6 5 4 3 3 4 5 6; 6 5 4 3 2 1 0 -1; 6 5 4 3 2 1 0 -1]); %! assert (A, [1 2 3 3 3 3 2 1; 6 5 4 3 3 3 2 1; 6 5 4 3 2 1 0 -1; 6 5 4 3 2 1 0 -1]); # Input checking %!error (medfilt1 ([1 2 3], -1)); %!error (medfilt1 ([1 2 3], 1, [], "hello")); %!error (medfilt1 ([1 2 3], 1, [], "omitnan", false)); %!error (medfilt1 ({1 2 3})); */ ����������������������������������������������������������������������������������������������������������������������signal-1.4.6/src/mmfir.c����������������������������������������������������������������������������0000644�0000000�0000000�00000055647�14673270174�012026� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// mmfir.c: MiniMax FIR filter design per McClellan, Parks & Rabiner // Copyright (c) 2014/15/21 Rob Sykes <robs@users.sourceforge.net> // // mmfir 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. // // mmfir 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 <http://www.gnu.org/licenses/>. #include "mmfir.h" #if defined QUAD_PREC #include <quadmath.h> #endif #include <limits.h> #include <math.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #if INT_MAX == 2147483647 typedef int rand_t; #elif LONG_MAX == 2147483647L typedef long rand_t; #else #error no suitable int32 type #endif #if defined _MSC_VER #define inline __inline #endif // Real-number precision, quad, double or long double (the default). #if defined QUAD_PREC // Very slow without native support. typedef __float128 real; #define cosr cosq #define sinr sinq #define PIr M_PIq #elif defined DOUBLE_PREC typedef double real; #define cosr cos #define sinr sin #define PIr PI #else typedef long double real; #define cosr cosl #define sinr sinl #define PIr 3.1415926535897932384626433832795029L #endif #define bandL (&bandSpecs[0]) #define bandR (&bandSpecs[numBands-1]) #define clamp(x,lo,hi) (((x)>(hi))?(hi):(((x)<(lo))?(lo):(x))) #define debugLevel (flags & 3) #define dir(x) ((x)<0? -1: (x)>0? 1 : 0) #define epsilon 1e-11 // In some circumstances, treat < epsilon as 0 #define E(x) peaks[x].e #define e(x) space[x].e #define F(x) peaks[x].f #define f(x) space[x].f #define maxExtras (numBands+2) #define maxPeaks (R+1+maxExtras) #define PI 3.1415926535897932384626433832795029 #define rand(r,x) (ranqd1(r) * ((x) / (65536. * 32768.))) // in [-x,x) #define ranqd1(r) ((r) = 1664525 * (r) + 1013904223) // int32_t r #define returnError(x) do {report.result=x; goto END;} while(0) #define iround(x) (int)floor((x)+.5) #define setF(F) for (f=(F); f>b->freqR; ++b) #define userEpsilon 1e-6 #define hasConverged(len) (((minimality = minimality_(peaks, len, \ minimalityThreshold))>0 && (density<density2 || stability>2)) || stability>2.7) static inline double maxD(double a, double b) {return a>=b? a:b;} static inline int maxI(int a, int b) {return a>=b? a:b;} static char const * const errorText[]={ "out-of-memory", "number of bands must be at least 1", "filter-order must be at least 1", "band-edge frequencies must increase in [0,1]", "weighting function out-of-range", "amplitude function out-of-range", "type III/IV DC amplitude response must be 0", "type II/III Nyquist amplitude response must be 0", }; // Type definitions: typedef enum {TypeI, TypeII, TypeIII, TypeIV} FirType; typedef struct {real x, beta, gamma;} LagrangeCoef; typedef MmfirPoint Point; // Determine coefs of a 2nd-order polynomial from 3 of its points: static void poly2( double x0, double x1, double x2, double y0, double y1, double y2, double * a, double * b, double * c) { double a0 = y0/((x0-x1)*(x0-x2)); double a1 = y1/((x1-x2)*(x1-x0)); double a2 = y2/((x2-x0)*(x2-x1)); *a = a0+a1+a2; *b = -(a0*(x1+x2) + a1*(x0+x2) + a2*(x0+x1)); *c = a0*x1*x2 + x0*a1*x2 + x0*x1*a2; } // Evaluate a 2nd-order polynomial at given point: static double poly2Val(double a, double b, double c, double x) { return (a*x + b)*x + c; } /* For filter-response analysis, use a discrete frequency space that is * 'warped' around transition-bands. The warping function is derived from the * observation by Shpak/Antoniou (1990) that an 'initial guess' for the peak * frequencies based on adjacent-peak spacing proportional to s(n) = * exp(c1+c2*n), improves upon one where the adjacent-peak spacing is constant. * * E.g., for a band-pass filter with band-edges 0, s1, p1, p2, s2, 1, the * analysis points within warped space compared to those in a linear space * might look like the following (second stop-band not shown): * 0 s1 p1 p2 * Warped: o o o o o oo oo o o o o o o o oo * Linear: o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o * * Warp function derivation is as follows: approx. peak position continuous * function, warp(x) = * x>=1: f(x)-f(0) * x<1: 2nd-order approximation (since exp. approx. breaks down here) * where f(x) = Indef. integral of s(x) = exp(c1+c2*x)/c2 * * Constants c1, c2 are determined empirically. Dependent constants c3=-f(0), * ca,cb,cc are calculated as follows: c3 = -exp(c1)/c2; * poly2(0,1,2, 0,warp(1),warp(2), &ca,&cb,&cc); */ static double const c1 = +.1235; static double const c2 = -.8; static double const c3 = 1.41431; static double const ca = .214437; static double const cb = .006742; static double const cc = 0; static double warp(double x) // Calculate warp in arbitrary units: { double t = c1 + c2*x; return x<0? 0 : x<1? poly2Val(ca,cb,cc,x) : x-(t>-38? exp(t)/c2 : 0)-c3; } static double iwarp(double y) // Inverse of warp(). { double t, x1=y+c3, x; if (y<0) return 0; if (y<warp(1)) return (-cb + sqrt(cb*cb-4*ca*(cc-y)))/(2*ca); // Newton iteration: do x=x1, t=c1+c2*x, x1=x-(warp(x)-y)/(1-(t>-38? exp(t) : 0)); while (fabs(x1-x)>1e-5); return x1; } // Generate a set of warped frequency-space points. // N.B. rand helps to avoid Lagrange interpolation instability: static int warpSpace(Point * p, double m, double f1, double f2, int density, int step, rand_t * random) { int i, n = (int)ceil(m*density); double scale, df = f2 - f1; p->f = f1, p+=step; // End points must be exact (not calculated). if (n > 0) { scale = df/warp(1.*n/density); for (i = 1; i < n; ++i) p->f = f1+scale*warp((i+rand(*random, .001))/density), p+=step; p->f = f2; // End points must be exact (not calculated). } return 1+n; } static int warpSpaceR( // Right of transition-band. Point * p, double m, double f1, double f2, int density, rand_t * random) { return warpSpace(p, m, f1, f2, density, +1, random); } static int warpSpaceL ( // Left of transition-band. Point * p, double m, double f1, double f2, int density, rand_t * random) { return warpSpace(p+(int)ceil(m*density), m, f2, f1, density, -1, random); } static int warpSpaceRL( // Between transition-bands. Point * p, double m, double f1, double f2, int density, rand_t * random) { double df1 = (f2 - f1) * .5, m1 = m * .5; int n = warpSpaceR(p, m1, f1, f1+df1, density, random); warpSpaceL(p + n-1, m1, f1+df1, f2, density, random); return n*2-1; } // Apportion space to each band, taking account of warping: static void apportionSpace(MmfirBandSpec * b, int numBands, int n) { int i, changed; double sum, t, av; do { // Use an iterative method. for (av=changed=0, i=0; i<numBands; ++i) av += warp(b[i].portion*n/b[i].ends)/(b[i].portion0/b[i].ends); av/=numBands; for (sum=i=0; i<numBands; ++i) { t=iwarp(av*b[i].portion0/b[i].ends)/n*b[i].ends; changed += fabs(t-b[i].portion) > 1e-6; sum+= b[i].portion=t; } for (i=0; i<numBands; b[i++].portion/=sum); // Normalise. } while (changed); } static inline real // Modifier at given f in [0,1], for filter-type T typeMod(real f, FirType T) { switch (T) { case TypeI : default: return 1; case TypeII : return cosr(f *(PIr*.5)); // Has zero at f=1. case TypeIII: return sinr(f * PIr); // Has zero at f=0, f=1. case TypeIV : return sinr(f *(PIr*.5)); // Has zero at f=0. } } // Call the response fn.; optionally check its output for validity; // apply typeMod if applicable: static MmfirResult respFnMod(MmfirRespFn respFn, FirType T, MmfirBandSpec const * b, int len, Point * p, int check, va_list args) { va_list tmpArgs; MmfirResult err; va_copy(tmpArgs, args), err=respFn(b, len, p, tmpArgs), va_end(tmpArgs); if (err) return err; int i; if (check) { double maxA=0; for (i=0; i<len; ++i) { double const d=fabs(p[i].a), w=p[i].w; maxA=maxD(maxA, d); if (d > 1e+10) return MmfirInvalidAmplitude; if (w < 1e-10 || w > 1e+10) return MmfirInvalidWeight; } if (maxA<1e-20) return MmfirInvalidAmplitude; } if (T) for (i=0; i<len; ++i) { double f; setF(p[i].f); real const t = typeMod(f,T); p[i].a=(double)(p[i].a/t); p[i].w=(double)(p[i].w*t/(b->weightF?f:1)); } return MmfirSuccess; } // Calculate the estimated amplitude response at a single, given // frequency using precalculated Lagrange interpolation coefficients. static real A(LagrangeCoef const * coefs, int R, double f) { int i = 0; real n = 0, d = 0, x = cosr(PIr*f), t; for (; i < R; d += t = coefs[i].beta / t, n += coefs[i].gamma * t, ++i) if (fabs((double)(t = x - coefs[i].x)) < epsilon) return coefs[i].gamma; return n/d; } static MmfirResult builtInRespFn( // For simple response, given in bandSpecs: MmfirBandSpec const * b, int len, Point * p, va_list args) { (void)args; int i; double f; for (i=0; i<len; ++i) { setF(p[i].f); // '...R' values here contain pre-calculated gradient: p[i].w= (b->weightL + b->weightR*(f-b->freqL)); p[i].a= (b->ampL + b->ampR *(f-b->freqL)); } return MmfirSuccess; } static double minimality_(Point const * p, int len, double threshold) { // Determine the minimality of the maximum error: double max=1+1e-9; while (len--) max=maxD(max, fabs(p[len].w)); return -log10(max-1)-threshold; } MmfirReport mmfir( double h[], MmfirFilterClass filterClass, int N0, // = filter order + 1 int numBands, MmfirBandSpec bandSpecs[/* numBands */], // N.B. destroyed. double accuracy, double persistence, double robustness, double target, int flags, MmfirState * state, MmfirRespFn respFn, ...) { int N = maxI(N0,2); FirType T = (FirType)((filterClass!=MmfirSymmetric)*2 + !(N&1)); int R = N/2 + !T; // R = # of cosine functions; num peaks = R+1 MmfirReport report = {MmfirSuccess, 0, 0, 0, 0, {0,0,0}}; // For forward-compatibility of the use of the control // variables, (almost) silently ignore out-of-range values: int density2 = iround((5+(numBands>2))*(1+( report.controls[0]=clamp(accuracy,0,7) ))); int maxIterations = iround(128*pow(1.587, report.controls[1]=clamp(persistence,-3,3) )); int density = 3+(numBands>2)+iround( report.controls[2]=clamp(robustness,0,3) ); int doneInit=0, doLG=1; // For the lower/higher density passes. int spaceLength=0, i, j, _1; // _1 holds +/- 1 int prevNumPeaks=0; double f; double delta_1 = 1e-30; // 1/delta double totalWidth=0; // Of given bands; in which peaks will be distributed. MmfirBandSpec * b; // Allocate the working arrays: LagrangeCoef * coefs = calloc((size_t)(R+1), sizeof(*coefs)); Point * peaks = calloc((size_t)(maxPeaks), sizeof(*peaks)); Point * prevPeaks = calloc((size_t)(maxPeaks), sizeof(*prevPeaks)); Point * space0 = 0, * space = 0; // Need to determine its size first. MmfirResult err; va_list respFnArgs, tmpArgs; va_start(respFnArgs, respFn); if (!respFn) respFn = builtInRespFn; // Initial checks: if (numBands<=0) returnError(MmfirInvalidNumBands); if (N!=N0) returnError(MmfirInvalidOrder); if (bandL->freqL<0 || bandR->freqR>1) returnError(MmfirInvalidFrequency); // Further checks, and pre-calc. linear interp. gradients, etc.: for (b=bandL; b<=bandR; ++b) { double df = b->freqR - b->freqL; if ((df <= userEpsilon) || (b<bandR && b->freqR>(b+1)->freqL)) returnError(MmfirInvalidFrequency); if (respFn==builtInRespFn) { if (filterClass==MmfirDifferentiator) b->ampL *= -1, b->ampR *= -1; b->weightF = filterClass==MmfirDifferentiator && (fabs(b->ampL) > userEpsilon || fabs(b->ampR) > userEpsilon); if (b->weightF) b->weightL *= 2, b->weightR *= 2; // For 2/f weighting. b->ampR = (b->ampR - b->ampL ) / df; b->weightR = (b->weightR - b->weightL) / df; } else b->weightF=0; totalWidth += df; } // Avoid dividing by typeMod(0,T)=0: if ((T == TypeIII || T == TypeIV) && (b=bandL)->freqL < (f=epsilon)) { Point p = {b->freqL,0,0,0}; va_copy(tmpArgs, respFnArgs), err=respFn(b,1,&p,tmpArgs), va_end(tmpArgs); if (err) returnError(err); if (fabs(p.a) > userEpsilon) returnError(MmfirInvalidDcAmplitude); if (respFn==builtInRespFn) { b->ampL += b->ampR*(f-b->freqL); b->weightL += b->weightR*(f-b->freqL); } totalWidth -= f-b->freqL, b->freqL = f; } // Avoid dividing by typeMod(1,T)=0: if ((T==TypeII || T==TypeIII) && (b=bandR)->freqR > (f=1-epsilon)) { Point p = {b->freqR,0,0,0}; va_copy(tmpArgs, respFnArgs), err=respFn(b,1,&p,tmpArgs), va_end(tmpArgs); if (err) returnError(err); if (fabs(p.a) > userEpsilon) returnError(MmfirInvalidNyquistAmplitude); totalWidth -= b->freqR-f, b->freqR = f; } // Separate any contiguous bands: for (b=bandL; b<bandR; ++b) if (b->freqR > (f = b[1].freqL-epsilon)) totalWidth -= b->freqR-f, b->freqR = f; // Usually, start with a lower density, then switch to the final value: for (density2=maxI(density,density2); report.result==MmfirSuccess && density<=density2; doLG=0, density+=maxI(density2-density,1)) { // Map current density to a convergence minimality threshold: double minimalityThreshold = density<density2? density*.35-.45 : (density+35)*.05; // Though in this case, stability usually prevails. if (debugLevel>1) fprintf(stderr, "minimalityThreshold: %g\n", minimalityThreshold); { // Allocate & populate the analysis frequency space: rand_t random = 0; for (b=bandL; b<=bandR; ++b) { double df = b->freqR - b->freqL; b->portion = b->portion0 = df/totalWidth; b->ends=2-(b->freqL <= epsilon || b->freqR >= 1-epsilon); } apportionSpace(bandL, numBands, R+1); // Determine # of points in analysis space: for (spaceLength=0, b=bandL; b<=bandR; b->endP=spaceLength, ++b) { double m = (R+1)*b->portion; if (b->freqL <= epsilon || b->freqR >= 1-epsilon) spaceLength += 1 + (int)ceil(m*density); else spaceLength += 2 * (1 + (int)ceil(m*.5*density)) - 1; } // Allocate space and calculate frequencies: free(space0); if ((space0 = (Point *)calloc((size_t)(spaceLength+2), sizeof(*space)))) { space = space0+1; // Simplifies peak detection at edges of space. for (j=0, b = bandL; b<=bandR; ++b) { double m = (R+1)*b->portion; if (b->freqL <= epsilon) j+= warpSpaceL(space+j, m, b->freqL, b->freqR, density, &random); else if (b->freqR >= 1-epsilon) j+= warpSpaceR(space+j, m, b->freqL, b->freqR, density, &random); else j+= warpSpaceRL(space+j, m, b->freqL, b->freqR, density, &random); } err = respFnMod( respFn, T, bandL, spaceLength, space, !doneInit, respFnArgs); if (err) returnError(err); } } if (!space0 || !coefs || !peaks || !prevPeaks) returnError(MmfirOutOfMemory); // Initial 'guess' distributes peaks evenly through warped space. The // offset of half a step at each end facilitates longer filters: if (!doneInit++) for (i=0; i<=R; ++i) peaks[i].f=space[iround((i+.5)/(R+1)*(spaceLength-1))].f; report.result=MmfirOngoing; while (1) { // Perform the Remez exchange (until break, below): double max, minimality, stability=0; int numPeaks, ok, extras=0; if (doLG++) { // Calculate Lagrange coefficients for response estimate: real denom = 0, numer = 0, t1, t, delta; err=respFnMod(respFn, T, bandL, R+1, peaks, 0, respFnArgs); if (err) returnError(err); for (i=0; i<=R; ++i) coefs[i].x = cosr(PIr * peaks[i].f); for (_1 = -1, b=bandL, i=0; i <= R; ++i) { for (t=1, j=0; j<=R; t1=t, t*=2*(coefs[i].x-coefs[j].x) +(i==j), ++j); if (!t1 || !t) returnError(MmfirNumericalError); coefs[i].beta = 1/t1; // Value at i==R will not be used. numer += peaks[i].a/t, denom += (_1 = -_1)/(t*peaks[i].w); } if (!numer || !denom) returnError(MmfirNumericalError); delta_1 = 1/(double)(delta = numer/denom); for (_1 = -1, b=bandL, i=0; i < R; ++i) coefs[i].gamma = peaks[i].a-(_1 = -_1)*delta/peaks[i].w; } // Stop Remez here if converged or no iterations remain: if (report.result == MmfirSuccess) break; else if (report.iterations == maxIterations) { report.result = density<density2? MmfirGaveUp1 : MmfirGaveUp; break; } else ++report.iterations; // Evaluate the normalised (i.e. converges to [-1,1]) error function: for (i=0, b=bandL; b<=bandR; i=b->endP, ++b) #ifdef _OPENMP #pragma omp parallel for #endif for (j=i; j<b->endP; ++j) { // omp needs separate counter j here. Point * const p = space+j; p->e = delta_1 * (double)(p->w * (p->a - A(coefs, R, p->f))); } report.FEs += spaceLength; // Find and store all local peaks in error magnitude: b=bandL, numPeaks=0; for (i=0; i<spaceLength; ++i) if (dir(e(i+1)-e(i))!=dir(e(i)-e(i-1))) { double e, A, B, C, fp; // Approx. continuous-space peak (by interpolation in discrete-space): setF(f(i)); j = i - (f(i) == b->freqR) + (f(i) == b->freqL); // Band-edge back-off poly2(f(j-1), f(j), f(j+1), e(j-1), e(j), e(j+1), &A, &B, &C); fp = B/A*-.5; // Freq. at which 1st derivative of poly is 0. ok = j==i || (dir(e(j+1)-e(j))*dir(e(j)-e(j-1)) > 0 && fp >= f(i-(j<=i)) && fp <= f(i+(j>=i))); // Band-edge needs care. f = ok? fp : f, e = ok? poly2Val(A,B,C,f) : e(i); // Store the peak: But avoid twin- \_ if (!numPeaks || f>peaks[numPeaks-1].f) { /* peaks in this case: \ */ if (numPeaks == maxPeaks) // Likely due to numerical error. returnError(MmfirTooManyPeaks); peaks[numPeaks].w=peaks[numPeaks].e=e, peaks[numPeaks++].f=f; // (1) } } if (debugLevel>2) { // Dump arrays to files for debugging: char name[9]; FILE * f = fopen(name,"w"); for (i=0; i<spaceLength;++i) fprintf(f, "%.16f %.9g\n", f(i), e(i)); fclose(f); name[0]='p'; f = fopen(name,"w"); for (i=0; i<numPeaks;++i) fprintf(f, "%.16f % .9g\n", F(i), E(i)); fclose(f); } // Check that there are at least R+1 peaks: if ((extras = numPeaks - (R+1)) < 0) returnError(MmfirTooFewPeaks); // Perhaps due to numerical error. // Before discarding any peaks, check freq. stability of the entire set: if (numPeaks == prevNumPeaks) { for (max=1e-9, i=0; i<numPeaks-1; ++i) max=maxD(max,fabs(1-(prevPeaks[i+1].f-prevPeaks[i].f)/(F(i+1)-F(i)))); stability = -log10(max); } else stability = -9.99; // If converged, don't change peak-set: if (extras && density==density2 && hasConverged(numPeaks)) for (i=0; i<numPeaks; peaks[i].e=prevPeaks[i].w, ++i); // Per (1) above memcpy(prevPeaks, peaks, (unsigned)numPeaks*sizeof(*peaks)); prevNumPeaks = numPeaks; // If >R+1 peaks, reduce to R+1 by discarding lesser peaks/pairs: while (numPeaks>R+1) { int n=1, try2, d_na, d; // d = index of peak to discard. // Find a lesser peak, either overall or at one end: try2=numPeaks-(R+1)>1, i=try2? 1 : numPeaks-1; for (d_na=d=0; !d_na && i<numPeaks; ++i) { d_na = E(i)*E(i-1)>0? i : d_na; // Check alternating. d = fabs(E(i)) < fabs(E(d))? i : d; // Check magnitude. } d=d_na? d_na: d; // Prefer to discard non-alternating. if (try2 && d && d != numPeaks-1) // Discard pair only if not at end. n=2, d-=fabs(E(d-1))<fabs(E(d+1)); // Choose lesser adjacent. memmove(peaks+d, peaks+d+n, (size_t)((numPeaks-=n)-d)*sizeof(*peaks)); if (debugLevel>1) fprintf(stderr, "x%i %i:%i\n", d_na, d, n); } if (hasConverged(R+1)) report.result = MmfirSuccess; if (debugLevel) fprintf(stderr, "%2i %2i %2i % .2f % .2f\n", report.iterations, density, extras, maxD(minimality,-9.99), stability); } } if (target && 1/fabs(delta_1) > target) returnError(MmfirMissedTarget); { // Generate filter coefficients: double * a = (double *)prevPeaks; // Reuse, as it's no longer in use. double _1 = T>TypeII? -1:1, phi = (T<TypeIII)*.5, s; // Sample the final estimated response; modify for filter type: #ifdef _OPENMP #pragma omp parallel for #endif for (i=0; i<=N/2; ++i) { double f=2.*i/N; a[i] = (double)(A(coefs, R, f) * typeMod(f, T)); } report.FEs += N/2+1; // --> time-domain using symmetry-aware IDFT (could also use IFFT): a[N/2] /= 1+T/3; #ifdef _OPENMP #pragma omp parallel for #endif for (i=0; i <(N+1)/2; ++i) { for (s=*a*.5, j=1; j <= N/2; s += sin(PI*((N-1-2.*i)/N*j+phi))*a[j], ++j); h[i] = _1*(h[N-1-i] = 2*s/N); } } END: if (state) { // Needed only for Octave/Matlab: free(space0), space0=0; int s0=iround(totalWidth*R*pow(4,2+accuracy)), s=0; for (j=0, b = bandL; b<=bandR; ++b) s += maxI(2, iround(b->portion*s0)); int S=s+numBands; if ((space = (Point *)calloc((size_t)S, sizeof(*space)))) { for (j=0, b = bandL; b<=bandR; ++b) { int m = maxI(2, iround(b->portion*s0)); for (i=0; i<m; ++i) space[j++].f=b->freqL+(b->freqR-b->freqL)/m*i; space[j++].f=b->freqR; } va_copy(tmpArgs,respFnArgs),respFn(bandL,S,space,tmpArgs),va_end(tmpArgs); } state->space = space, space=0; state->peaks = peaks, peaks=0; state->spaceLength=S; state->peaksLength=R+1; } va_end(respFnArgs); free(space0); free(prevPeaks); free(peaks); free(coefs); // Complete and return the report: report.text = report.result >= MmfirInvocationError? errorText[report.result-MmfirInvocationError] : report.result >= MmfirError? "numerical-error" : report.result >= MmfirWarning? "not-converged" : "success"; report.minimax = 1/fabs(delta_1); return report; } �����������������������������������������������������������������������������������������signal-1.4.6/src/mmfir.h����������������������������������������������������������������������������0000644�0000000�0000000�00000007544�14673270174�012024� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// mmfir.h: MiniMax FIR filter design per McClellan, Parks & Rabiner // Copyright (c) 2014/15/21 Rob Sykes <robs@users.sourceforge.net> // // mmfir 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. // // mmfir 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 <http://www.gnu.org/licenses/>. #if !defined mmfir_included #define mmfir_included #include <stdarg.h> #if defined __cplusplus extern "C" { #endif typedef enum { MmfirSymmetric, // Type I/II (symmetric impulse-response). MmfirAntiSymmetric, // Type III/IV (anti-symmetric impulse-response). MmfirDifferentiator // Ditto, but with passband error-weighting *= 2/f } MmfirFilterClass; typedef struct { double freqL, freqR; // Frequency at left & right band-edges. In [0,1] double ampL, ampR; // Desired amplitude of response at given edges. double weightL, weightR; // Error weighting (multiplier) at given edges. // Internal use only: int ends, weightF, endP, hadRemoval; double eAv, ePk; double portion0, portion; } MmfirBandSpec; typedef enum { MmfirSuccess, MmfirWarning, // Section marker MmfirGaveUp = MmfirWarning, MmfirGaveUp1, // During first pass. // No filter will be returned: MmfirMissedTarget, MmfirError, // Section marker MmfirTooFewPeaks = MmfirError, MmfirTooManyPeaks, MmfirNumericalError, MmfirInvocationError, // Section marker MmfirOutOfMemory = MmfirInvocationError, MmfirInvalidNumBands, MmfirInvalidOrder, MmfirInvalidFrequency, MmfirInvalidWeight, MmfirInvalidAmplitude, MmfirInvalidDcAmplitude, MmfirInvalidNyquistAmplitude, // Internal use only: MmfirRuntimeError, MmfirOngoing } MmfirResult; typedef struct { // Useful stuff: MmfirResult result; // As defined above. char const * text; // Textual version of result. double minimax; // Final approximated minimax weighted error. // Academic interest: int FEs; // # of Lagrange interp. fn. evaluations made. int iterations; // # of Remez iterations made. double controls[3]; // Allows client to know if these were clamped. } MmfirReport; typedef struct { double f; // Frequency in [0,1] of this point double a; // Desired amplitude response @ this point. double w; // Error weight @ this point. double e; // Internal use only. } MmfirPoint; typedef struct { MmfirPoint * space; MmfirPoint * peaks; int spaceLength; int peaksLength; } MmfirState; typedef MmfirResult (* MmfirRespFn)( MmfirBandSpec const * bandSpecs, // As bandSpecs below. int numPoints, MmfirPoint points[/* numPoints */], // Provide .a & .w for each .f va_list additionalArgs); MmfirReport mmfir( double h[], // In which to store the N filter coeffiecients. MmfirFilterClass filterClass, int N, // = filter order + 1 int numBands, MmfirBandSpec bandSpecs[/* numBands */], // N.B. destroyed. double accuracy, double persistence, double robustness, double target, int flags, MmfirState * reserved, // Set to 0. MmfirRespFn respFn, // Set to 0 if resp. is given in bandSpecs. ...); // Additional args for (non-zero) respFn. #if defined __cplusplus } #endif #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/src/octave-compat.h��������������������������������������������������������������������0000644�0000000�0000000�00000004727�14673270174�013454� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright (C) 2018-2019 Mike Miller 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; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ #if ! defined (octave_signal_octave_compat_h) #define octave_signal_octave_compat_h #include <octave/lo-mappers.h> #include <octave/version.h> #if (! defined (OCTAVE_MAJOR_VERSION) || ! defined (OCTAVE_MINOR_VERSION) \ || (OCTAVE_MAJOR_VERSION < 4) \ || ((OCTAVE_MAJOR_VERSION == 4) && (OCTAVE_MINOR_VERSION < 2))) # include <octave/gripes.h> #else # include <octave/errwarn.h> #endif #if (! defined (OCTAVE_MAJOR_VERSION) || ! defined (OCTAVE_MINOR_VERSION) \ || (OCTAVE_MAJOR_VERSION < 4) \ || ((OCTAVE_MAJOR_VERSION == 4) && (OCTAVE_MINOR_VERSION < 2))) inline void err_wrong_type_arg (const char *name, const octave_value& tc) { gripe_wrong_type_arg (name, tc); } namespace octave { namespace math { inline int nint (double x) { return NINT (x); } } } #endif namespace octave { namespace signal { #if (! defined (OCTAVE_MAJOR_VERSION) || ! defined (OCTAVE_MINOR_VERSION) \ || (OCTAVE_MAJOR_VERSION < 4) \ || ((OCTAVE_MAJOR_VERSION == 4) && (OCTAVE_MINOR_VERSION < 4))) inline bool iscomplex (const octave_value& v) { return v.is_complex_type (); } inline bool isnumeric (const octave_value& v) { return v.is_numeric_type (); } inline bool isreal (const octave_value& v) { return v.is_real_type (); } inline bool iscell (const octave_value& v) { return v.is_cell (); } #else inline bool iscomplex (const octave_value& v) { return v.iscomplex (); } inline bool isnumeric (const octave_value& v) { return v.isnumeric (); } inline bool isreal (const octave_value& v) { return v.isreal (); } inline bool iscell (const octave_value& v) { return v.iscell (); } #endif } } #endif �����������������������������������������signal-1.4.6/src/remez.cc���������������������������������������������������������������������������0000644�0000000�0000000�00000060036�14673270174�012165� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright (C) 1995, 1998 Jake Janovetz <janovetz@uiuc.edu> Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net> Copyright (C) 2000 Kai Habel <kahacjde@linux.zrz.tu-berlin.de> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 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; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ /************************************************************************** * There appear to be some problems with the routine Search. See comments * therein [search for PAK:]. I haven't looked closely at the rest * of the code---it may also have some problems. *************************************************************************/ #include <octave/oct.h> #include <cassert> #include <cmath> #ifndef OCTAVE_LOCAL_BUFFER #include <vector> #define OCTAVE_LOCAL_BUFFER(T, buf, size) \ std::vector<T> buf ## _vector (size); \ T *buf = &(buf ## _vector[0]) #endif #include "octave-compat.h" #define CONST const #define BANDPASS 1 #define DIFFERENTIATOR 2 #define HILBERT 3 #define NEGATIVE 0 #define POSITIVE 1 #define Pi 3.1415926535897932 #define Pi2 6.2831853071795865 #define GRIDDENSITY 16 #define MAXITERATIONS 40 /******************* * CreateDenseGrid *================= * Creates the dense grid of frequencies from the specified bands. * Also creates the Desired Frequency Response function (D[]) and * the Weight function (W[]) on that dense grid * * * INPUT: * ------ * int r - 1/2 the number of filter coefficients * int numtaps - Number of taps in the resulting filter * int numband - Number of bands in user specification * double bands[] - User-specified band edges [2*numband] * double des[] - Desired response per band [2*numband] * double weight[] - Weight per band [numband] * int symmetry - Symmetry of filter - used for grid check * int griddensity * * OUTPUT: * ------- * int gridsize - Number of elements in the dense frequency grid * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize] * double D[] - Desired response on the dense grid [gridsize] * double W[] - Weight function on the dense grid [gridsize] *******************/ void CreateDenseGrid(int r, int numtaps, int numband, const double bands[], const double des[], const double weight[], int gridsize, double Grid[], double D[], double W[], int symmetry, int griddensity) { int i, j, k, band; double delf, lowf, highf, grid0; delf = 0.5/(griddensity*r); /* * For differentiator, hilbert, * symmetry is odd and Grid[0] = max(delf, bands[0]) */ grid0 = (symmetry == NEGATIVE) && (delf > bands[0]) ? delf : bands[0]; j=0; for (band=0; band < numband; band++) { lowf = (band==0 ? grid0 : bands[2*band]); highf = bands[2*band + 1]; k = (int)((highf - lowf)/delf + 0.5); /* .5 for rounding */ if (band == 0 && symmetry == NEGATIVE) k--; for (i=0; i<k; i++) { D[j] = des[2*band] + i*(des[2*band+1]-des[2*band])/(k-1); W[j] = weight[band]; Grid[j] = lowf; lowf += delf; j++; } Grid[j-1] = highf; } /* * Similar to above, if odd symmetry, last grid point can't be .5 * - but, if there are even taps, leave the last grid point at .5 */ if ((symmetry == NEGATIVE) && (Grid[gridsize-1] > (0.5 - delf)) && (numtaps % 2)) { Grid[gridsize-1] = 0.5-delf; } } /******************** * InitialGuess *============== * Places Extremal Frequencies evenly throughout the dense grid. * * * INPUT: * ------ * int r - 1/2 the number of filter coefficients * int gridsize - Number of elements in the dense frequency grid * * OUTPUT: * ------- * int Ext[] - Extremal indexes to dense frequency grid [r+1] ********************/ void InitialGuess(int r, int Ext[], int gridsize) { int i; for (i=0; i<=r; i++) Ext[i] = i * (gridsize-1) / r; } /*********************** * CalcParms *=========== * * * INPUT: * ------ * int r - 1/2 the number of filter coefficients * int Ext[] - Extremal indexes to dense frequency grid [r+1] * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize] * double D[] - Desired response on the dense grid [gridsize] * double W[] - Weight function on the dense grid [gridsize] * * OUTPUT: * ------- * double ad[] - 'b' in Oppenheim & Schafer [r+1] * double x[] - [r+1] * double y[] - 'C' in Oppenheim & Schafer [r+1] ***********************/ void CalcParms(int r, int Ext[], double Grid[], double D[], double W[], double ad[], double x[], double y[]) { int i, j, k, ld; double sign, xi, delta, denom, numer; /* * Find x[] */ for (i=0; i<=r; i++) x[i] = cos(Pi2 * Grid[Ext[i]]); /* * Calculate ad[] - Oppenheim & Schafer eq 7.132 */ ld = (r-1)/15 + 1; /* Skips around to avoid round errors */ for (i=0; i<=r; i++) { denom = 1.0; xi = x[i]; for (j=0; j<ld; j++) { for (k=j; k<=r; k+=ld) if (k != i) denom *= 2.0*(xi - x[k]); } if (fabs(denom)<0.00001) denom = 0.00001; ad[i] = 1.0/denom; } /* * Calculate delta - Oppenheim & Schafer eq 7.131 */ numer = denom = 0; sign = 1; for (i=0; i<=r; i++) { numer += ad[i] * D[Ext[i]]; denom += sign * ad[i]/W[Ext[i]]; sign = -sign; } delta = numer/denom; sign = 1; /* * Calculate y[] - Oppenheim & Schafer eq 7.133b */ for (i=0; i<=r; i++) { y[i] = D[Ext[i]] - sign * delta/W[Ext[i]]; sign = -sign; } } /********************* * ComputeA *========== * Using values calculated in CalcParms, ComputeA calculates the * actual filter response at a given frequency (freq). Uses * eq 7.133a from Oppenheim & Schafer. * * * INPUT: * ------ * double freq - Frequency (0 to 0.5) at which to calculate A * int r - 1/2 the number of filter coefficients * double ad[] - 'b' in Oppenheim & Schafer [r+1] * double x[] - [r+1] * double y[] - 'C' in Oppenheim & Schafer [r+1] * * OUTPUT: * ------- * Returns double value of A[freq] *********************/ double ComputeA(double freq, int r, double ad[], double x[], double y[]) { int i; double xc, c, denom, numer; denom = numer = 0; xc = cos(Pi2 * freq); for (i=0; i<=r; i++) { c = xc - x[i]; if (fabs(c) < 1.0e-7) { numer = y[i]; denom = 1; break; } c = ad[i]/c; denom += c; numer += c*y[i]; } return numer/denom; } /************************ * CalcError *=========== * Calculates the Error function from the desired frequency response * on the dense grid (D[]), the weight function on the dense grid (W[]), * and the present response calculation (A[]) * * * INPUT: * ------ * int r - 1/2 the number of filter coefficients * double ad[] - [r+1] * double x[] - [r+1] * double y[] - [r+1] * int gridsize - Number of elements in the dense frequency grid * double Grid[] - Frequencies on the dense grid [gridsize] * double D[] - Desired response on the dense grid [gridsize] * double W[] - Weight function on the desnse grid [gridsize] * * OUTPUT: * ------- * double E[] - Error function on dense grid [gridsize] ************************/ void CalcError(int r, double ad[], double x[], double y[], int gridsize, double Grid[], double D[], double W[], double E[]) { int i; double A; for (i=0; i<gridsize; i++) { A = ComputeA(Grid[i], r, ad, x, y); E[i] = W[i] * (D[i] - A); } } /************************ * Search *======== * Searches for the maxima/minima of the error curve. If more than * r+1 extrema are found, it uses the following heuristic (thanks * Chris Hanson): * 1) Adjacent non-alternating extrema deleted first. * 2) If there are more than one excess extrema, delete the * one with the smallest error. This will create a non-alternation * condition that is fixed by 1). * 3) If there is exactly one excess extremum, delete the smaller * of the first/last extremum * * * INPUT: * ------ * int r - 1/2 the number of filter coefficients * int Ext[] - Indexes to Grid[] of extremal frequencies [r+1] * int gridsize - Number of elements in the dense frequency grid * double E[] - Array of error values. [gridsize] * OUTPUT: * ------- * int Ext[] - New indexes to extremal frequencies [r+1] ************************/ int Search(int r, int Ext[], int gridsize, double E[]) { int i, j, k, l, extra; /* Counters */ int up, alt; int *foundExt; /* Array of found extremals */ /* * Allocate enough space for found extremals. */ foundExt = (int *)malloc((2*r) * sizeof(int)); k = 0; /* * Check for extremum at 0. */ if (((E[0]>0.0) && (E[0]>E[1])) || ((E[0]<0.0) && (E[0]<E[1]))) foundExt[k++] = 0; /* * Check for extrema inside dense grid */ for (i=1; i<gridsize-1; i++) { if (((E[i]>=E[i-1]) && (E[i]>E[i+1]) && (E[i]>0.0)) || ((E[i]<=E[i-1]) && (E[i]<E[i+1]) && (E[i]<0.0))) { // PAK: we sometimes get too many extremal frequencies if (k >= 2*r) return -3; foundExt[k++] = i; } } /* * Check for extremum at 0.5 */ j = gridsize-1; if (((E[j]>0.0) && (E[j]>E[j-1])) || ((E[j]<0.0) && (E[j]<E[j-1]))) { if (k >= 2*r) return -3; foundExt[k++] = j; } // PAK: we sometimes get not enough extremal frequencies if (k < r+1) return -2; /* * Remove extra extremals */ extra = k - (r+1); assert(extra >= 0); while (extra > 0) { if (E[foundExt[0]] > 0.0) up = 1; /* first one is a maxima */ else up = 0; /* first one is a minima */ l=0; alt = 1; for (j=1; j<k; j++) { if (fabs(E[foundExt[j]]) < fabs(E[foundExt[l]])) l = j; /* new smallest error. */ if ((up) && (E[foundExt[j]] < 0.0)) up = 0; /* switch to a minima */ else if ((!up) && (E[foundExt[j]] > 0.0)) up = 1; /* switch to a maxima */ else { alt = 0; // PAK: break now and you will delete the smallest overall // extremal. If you want to delete the smallest of the // pair of non-alternating extremals, then you must do: // // if (fabs(E[foundExt[j]]) < fabs(E[foundExt[j-1]])) l=j; // else l=j-1; break; /* Ooops, found two non-alternating */ } /* extrema. Delete smallest of them */ } /* if the loop finishes, all extrema are alternating */ /* * If there's only one extremal and all are alternating, * delete the smallest of the first/last extremals. */ if ((alt) && (extra == 1)) { if (fabs(E[foundExt[k-1]]) < fabs(E[foundExt[0]])) /* Delete last extremal */ l = k-1; // PAK: changed from l = foundExt[k-1]; else /* Delete first extremal */ l = 0; // PAK: changed from l = foundExt[0]; } for (j=l; j<k-1; j++) /* Loop that does the deletion */ { foundExt[j] = foundExt[j+1]; assert(foundExt[j]<gridsize); } k--; extra--; } for (i=0; i<=r; i++) { assert(foundExt[i]<gridsize); Ext[i] = foundExt[i]; /* Copy found extremals to Ext[] */ } free(foundExt); return 0; } /********************* * FreqSample *============ * Simple frequency sampling algorithm to determine the impulse * response h[] from A's found in ComputeA * * * INPUT: * ------ * int N - Number of filter coefficients * double A[] - Sample points of desired response [N/2] * int symmetry - Symmetry of desired filter * * OUTPUT: * ------- * double h[] - Impulse Response of final filter [N] *********************/ void FreqSample(int N, double A[], double h[], int symm) { int n, k; double x, val, M; M = (N-1.0)/2.0; if (symm == POSITIVE) { if (N%2) { for (n=0; n<N; n++) { val = A[0]; x = Pi2 * (n - M)/N; for (k=1; k<=M; k++) val += 2.0 * A[k] * cos(x*k); h[n] = val/N; } } else { for (n=0; n<N; n++) { val = A[0]; x = Pi2 * (n - M)/N; for (k=1; k<=(N/2-1); k++) val += 2.0 * A[k] * cos(x*k); h[n] = val/N; } } } else { if (N%2) { for (n=0; n<N; n++) { val = 0; x = Pi2 * (n - M)/N; for (k=1; k<=M; k++) val += 2.0 * A[k] * sin(x*k); h[n] = val/N; } } else { for (n=0; n<N; n++) { val = A[N/2] * sin(Pi * (n - M)); x = Pi2 * (n - M)/N; for (k=1; k<=(N/2-1); k++) val += 2.0 * A[k] * sin(x*k); h[n] = val/N; } } } } /******************* * isDone *======== * Checks to see if the error function is small enough to consider * the result to have converged. * * INPUT: * ------ * int r - 1/2 the number of filter coefficients * int Ext[] - Indexes to extremal frequencies [r+1] * double E[] - Error function on the dense grid [gridsize] * * OUTPUT: * ------- * Returns 1 if the result converged * Returns 0 if the result has not converged ********************/ int isDone(int r, int Ext[], double E[]) { int i; double min, max, current; min = max = fabs(E[Ext[0]]); for (i=1; i<=r; i++) { current = fabs(E[Ext[i]]); if (current < min) min = current; if (current > max) max = current; } return (((max-min)/max) < 0.0001); } /******************** * remez *======= * Calculates the optimal (in the Chebyshev/minimax sense) * FIR filter impulse response given a set of band edges, * the desired response on those bands, and the weight given to * the error in those bands. * * INPUT: * ------ * int numtaps - Number of filter coefficients * int numband - Number of bands in filter specification * double bands[] - User-specified band edges [2 * numband] * double des[] - User-specified band responses [numband] * double weight[] - User-specified error weights [numband] * int type - Type of filter * * OUTPUT: * ------- * double h[] - Impulse response of final filter [numtaps] * returns - true on success, false on failure to converge ********************/ int remez(double h[], int numtaps, int numband, const double bands[], const double des[], const double weight[], int type, int griddensity) { double *Grid, *W, *D, *E; int i, iter, gridsize, r, *Ext; double *taps, c; double *x, *y, *ad; int symmetry; if (type == BANDPASS) symmetry = POSITIVE; else symmetry = NEGATIVE; r = numtaps/2; /* number of extrema */ if ((numtaps%2) && (symmetry == POSITIVE)) r++; /* * Predict dense grid size in advance for memory allocation * .5 is so we round up, not truncate */ gridsize = 0; for (i=0; i<numband; i++) { gridsize += (int)(2*r*griddensity*(bands[2*i+1] - bands[2*i]) + .5); } if (symmetry == NEGATIVE) { gridsize--; } /* * Dynamically allocate memory for arrays with proper sizes */ Grid = (double *)malloc(gridsize * sizeof(double)); D = (double *)malloc(gridsize * sizeof(double)); W = (double *)malloc(gridsize * sizeof(double)); E = (double *)malloc(gridsize * sizeof(double)); Ext = (int *)malloc((r+1) * sizeof(int)); taps = (double *)malloc((r+1) * sizeof(double)); x = (double *)malloc((r+1) * sizeof(double)); y = (double *)malloc((r+1) * sizeof(double)); ad = (double *)malloc((r+1) * sizeof(double)); /* * Create dense frequency grid */ CreateDenseGrid(r, numtaps, numband, bands, des, weight, gridsize, Grid, D, W, symmetry, griddensity); InitialGuess(r, Ext, gridsize); /* * For Differentiator: (fix grid) */ if (type == DIFFERENTIATOR) { for (i=0; i<gridsize; i++) { /* D[i] = D[i]*Grid[i]; */ if (D[i] > 0.0001) W[i] = W[i]/Grid[i]; } } /* * For odd or Negative symmetry filters, alter the * D[] and W[] according to Parks McClellan */ if (symmetry == POSITIVE) { if (numtaps % 2 == 0) { for (i=0; i<gridsize; i++) { c = cos(Pi * Grid[i]); D[i] /= c; W[i] *= c; } } } else { if (numtaps % 2) { for (i=0; i<gridsize; i++) { c = sin(Pi2 * Grid[i]); D[i] /= c; W[i] *= c; } } else { for (i=0; i<gridsize; i++) { c = sin(Pi * Grid[i]); D[i] /= c; W[i] *= c; } } } /* * Perform the Remez Exchange algorithm */ for (iter=0; iter<MAXITERATIONS; iter++) { CalcParms(r, Ext, Grid, D, W, ad, x, y); CalcError(r, ad, x, y, gridsize, Grid, D, W, E); int err = Search(r, Ext, gridsize, E); if (err) return err; for(i=0; i <= r; i++) assert(Ext[i]<gridsize); if (isDone(r, Ext, E)) break; } CalcParms(r, Ext, Grid, D, W, ad, x, y); /* * Find the 'taps' of the filter for use with Frequency * Sampling. If odd or Negative symmetry, fix the taps * according to Parks McClellan */ for (i=0; i<=numtaps/2; i++) { if (symmetry == POSITIVE) { if (numtaps%2) c = 1; else c = cos(Pi * (double)i/numtaps); } else { if (numtaps%2) c = sin(Pi2 * (double)i/numtaps); else c = sin(Pi * (double)i/numtaps); } taps[i] = ComputeA((double)i/numtaps, r, ad, x, y)*c; } /* * Frequency sampling design with calculated taps */ FreqSample(numtaps, taps, h, symmetry); /* * Delete allocated memory */ free(Grid); free(W); free(D); free(E); free(Ext); free(x); free(y); free(ad); return iter<MAXITERATIONS?0:-1; } /* == Octave interface starts here ====================================== */ DEFUN_DLD (remez, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {@var{b} =} remez (@var{n}, @var{f}, @var{a})\n\ @deftypefnx {Loadable Function} {@var{b} =} remez (@var{n}, @var{f}, @var{a}, @var{w})\n\ @deftypefnx {Loadable Function} {@var{b} =} remez (@var{n}, @var{f}, @var{a}, @var{w}, @var{ftype})\n\ @deftypefnx {Loadable Function} {@var{b} =} remez (@var{n}, @var{f}, @var{a}, @var{w}, @var{ftype}, @var{griddensity})\n\ Parks-McClellan optimal FIR filter design.\n\ @table @var\n\ @item n\n\ gives the filter order, where the generated filter length taps is n+1\n\ @item f\n\ gives frequency at the band edges [b1 e1 b2 e2 b3 e3 @dots{}]\n\ @item a\n\ gives amplitude at the band edges [a(b1) a(e1) a(b2) a(e2) @dots{}]\n\ @item w\n\ gives weighting applied to each band\n\ @item ftype\n\ is \"bandpass\", \"hilbert\" or \"differentiator\"\n\ @item griddensity\n\ determines how accurately the filter will be\n\ constructed. The minimum value is 16, but higher numbers are\n\ slower to compute.\n\ @end table\n\ \n\ Frequency is in the range (0, 1), with 1 being the Nyquist frequency.\n\ @end deftypefn") { octave_value_list retval; int i; int nargin = args.length(); if (nargin < 3 || nargin > 6) { print_usage (); return retval; } int numtaps = octave::math::nint (args(0).double_value ()) + 1; if (numtaps < 4) { error("remez: number of taps must be an integer greater than 3"); return retval; } ColumnVector o_bands(args(1).vector_value()); int numbands = o_bands.numel()/2; OCTAVE_LOCAL_BUFFER(double, bands, numbands*2); if (numbands < 1 || o_bands.numel()%2 == 1) { error("remez: must have an even number of band edges"); return retval; } for (i=1; i < o_bands.numel(); i++) { if (o_bands(i)<o_bands(i-1)) { error("band edges must be nondecreasing"); return retval; } } if (o_bands(0) < 0 || o_bands(1) > 1) { error("band edges must be in the range [0,1]"); return retval; } for(i=0; i < 2*numbands; i++) bands[i] = o_bands(i)/2.0; ColumnVector o_response(args(2).vector_value()); OCTAVE_LOCAL_BUFFER (double, response, numbands*2); if (o_response.numel() != o_bands.numel()) { error("remez: must have one response magnitude for each band edge"); return retval; } for(i=0; i < 2*numbands; i++) response[i] = o_response(i); std::string stype = std::string("bandpass"); int density = 16; OCTAVE_LOCAL_BUFFER (double, weight, numbands); for (i=0; i < numbands; i++) weight[i] = 1.0; if (nargin > 3) { if (args(3).is_string()) stype = args(3).string_value(); else if (args(3).is_real_matrix() || args(3).is_real_scalar()) { ColumnVector o_weight(args(3).vector_value()); if (o_weight.numel() != numbands) { error("remez: need one weight for each band [=length(band)/2]"); return retval; } for (i=0; i < numbands; i++) weight[i] = o_weight(i); } else { error("remez: incorrect argument list"); return retval; } } if (nargin > 4) { if (args(4).is_string() && !args(3).is_string()) stype = args(4).string_value(); else if (args(4).is_real_scalar()) density = octave::math::nint (args(4).double_value ()); else { error("remez: incorrect argument list"); return retval; } } if (nargin > 5) { if (args(5).is_real_scalar() && !args(4).is_real_scalar()) density = octave::math::nint (args(5).double_value ()); else { error("remez: incorrect argument list"); return retval; } } int itype; if (stype == "bandpass") itype = BANDPASS; else if (stype == "differentiator") itype = DIFFERENTIATOR; else if (stype == "hilbert") itype = HILBERT; else { error("remez: unknown ftype '%s'", stype.data()); return retval; } if (density < 16) { error("remez: griddensity is too low; must be greater than 16"); return retval; } OCTAVE_LOCAL_BUFFER (double, coeff, numtaps+5); int err = remez(coeff,numtaps,numbands,bands,response,weight,itype,density); if (err == -1) warning("remez: -- failed to converge -- returned filter may be bad."); else if (err == -2) { error("remez: insufficient extremals--cannot continue"); return retval; } else if (err == -3) { error("remez: too many extremals--cannot continue"); return retval; } ColumnVector h(numtaps); while(numtaps--) h(numtaps) = coeff[numtaps]; return octave_value(h); } /* %!test %! b = [ %! 0.0415131831103279 %! 0.0581639884202646 %! -0.0281579212691008 %! -0.0535575358002337 %! -0.0617245915143180 %! 0.0507753178978075 %! 0.2079018331396460 %! 0.3327160895375440 %! 0.3327160895375440 %! 0.2079018331396460 %! 0.0507753178978075 %! -0.0617245915143180 %! -0.0535575358002337 %! -0.0281579212691008 %! 0.0581639884202646 %! 0.0415131831103279]; %! assert(remez(15,[0,0.3,0.4,1],[1,1,0,0]),b,1e-14); */ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/src/sosfilt.cc�������������������������������������������������������������������������0000644�0000000�0000000�00000005322�14673270174�012523� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright (C) 2008 Eric Chassande-Mottin, CNRS (France) <ecm@apc.univ-paris7.fr> 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; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ #include <octave/oct.h> #include <octave/defun-dld.h> #include <octave/error.h> #include <octave/pager.h> #include <octave/quit.h> #include <octave/variables.h> #include "octave-compat.h" DEFUN_DLD (sosfilt, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {@var{y} =} sosfilt (@var{sos}, @var{x})\n\ Second order section IIR filtering of @var{x}. The second order section\n\ filter is described by the matrix @var{sos} with:\n\ \n\ @multitable {col 1} {this is column two}\n\ @item @tab [ @var{B1} @var{A1} ]@*\n\ @item @var{sos} = @tab [ @dots{} ],@*\n\ @item @tab [ @var{BN} @var{AN} ]@*\n\ @end multitable\n\ \n\ where @code{@var{B1} = [b0 b1 b2]} and @code{@var{A1} = [1 a1 a2]} for\n\ section 1, etc. The b0 entry must be nonzero for each section.\n\ @end deftypefn\n") { octave_value_list retval; int nargin = args.length (); if (nargin != 2) { print_usage (); return retval; } Matrix sos( args(0).matrix_value() ); if (sos.columns() != 6) { error("Second-order section matrix must be a non-empty Lx6 matrix"); return retval; } Matrix x( args(1).matrix_value() ); int n=x.rows(); int m=x.columns(); bool isrowvector=false; if ((n==1)&&(m>1)) // if row vector, transpose to column vector { x=x.transpose(); n=x.rows(); m=x.columns(); isrowvector=true; } Matrix y(n,m,0.0); for (int k=0; k<m; k++) { for (int j=0; j<sos.rows(); j++) { double v0=0.0, v1=0.0, v2=0.0; double a0 = sos(j,3); double a1 = sos(j,4)/a0; double a2 = sos(j,5)/a0; double b0 = sos(j,0)/a0; double b1 = sos(j,1)/a0; double b2 = sos(j,2)/a0; for (int i=0; i<n; i++) { v0=x(i,k)-a1*v1-a2*v2; y(i,k)=b0*v0+b1*v1+b2*v2; v2=v1; v1=v0; } x.insert(y.column(k),0,k); } } if (isrowvector) y=y.transpose(); retval(0)=y; return retval; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������signal-1.4.6/src/upfirdn.cc�������������������������������������������������������������������������0000644�0000000�0000000�00000006143�14673270174�012511� 0����������������������������������������������������������������������������������������������������ustar�00�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Copyright (C) 2008 Eric Chassande-Mottin, CNRS (France) <ecm@apc.univ-paris7.fr> 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; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ #include <octave/oct.h> #include <octave/defun-dld.h> #include <octave/error.h> #include <octave/pager.h> #include <octave/quit.h> #include <octave/variables.h> #include "octave-compat.h" template<class MT> MT upfirdn (MT &x, ColumnVector &h, octave_idx_type p, octave_idx_type q) { octave_idx_type rx = x.rows (); octave_idx_type cx = x.columns (); bool isrowvector = false; if ((rx == 1) && (cx > 1)) // if row vector, transpose to column vector { x = x.transpose (); rx = x.rows (); cx = x.columns (); isrowvector = true; } octave_idx_type Lh = h.numel (); const octave_idx_type Ly = ceil (static_cast<double> ((rx-1)*p + Lh) / static_cast<double> (q)); MT y (Ly, cx, 0.0); octave_idx_type zero = 0; for (octave_idx_type c = 0; c < cx; c++) for (octave_idx_type m = 0; m < Ly; m++) { const octave_idx_type n = (m * q) / p; const octave_idx_type lm = (m * q) % p; y (m,c) = 0.0; for (octave_idx_type k = std::max (zero, n-rx+1); k <= n && k*p + lm < Lh; k++) y (m,c) += h (k*p + lm) * x (n-k, c); } if (isrowvector) y = y.transpose (); return y; } DEFUN_DLD (upfirdn, args,, "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {@var{y} =} upfirdn (@var{x}, @var{h}, @var{p}, @var{q})\n\ Upsample, FIR filtering, and downsample.\n\ @end deftypefn\n") { octave_value_list retval; const int nargin = args.length (); if (nargin != 4) { print_usage (); return retval; } ColumnVector h (args (1).vector_value ()); octave_idx_type p = args (2).idx_type_value (); octave_idx_type q = args (3).idx_type_value (); // Do the dispatching if (octave::signal::isreal (args (0))) { Matrix x = args (0).matrix_value (); Matrix y = upfirdn (x, h, p, q); retval (0) = y; } else if (octave::signal::iscomplex (args (0))) { ComplexMatrix x = args (0).complex_matrix_value (); ComplexMatrix y = upfirdn (x, h, p, q); retval (0) = y; } else { err_wrong_type_arg ("upfirdn", args(0)); return retval; } return retval; } /* %!assert (isequal (upfirdn (1:100, 1, 1, 1), 1:100)) %!assert (isequal (upfirdn (1:100, 1, 1, 2), 1:2:100)) %% Test input validation %!error upfirdn () %!error upfirdn (1,2) %!error upfirdn (1,2,3) %!error upfirdn (1,2,3,4,5) */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������