Mercurial > forge
changeset 11566:60b2ba2eb51d octave-forge
signal: remove from svn tree after move to hg
author | carandraug |
---|---|
date | Mon, 18 Mar 2013 21:05:16 +0000 |
parents | 0bc8e2131356 |
children | b379b9a32196 |
files | main/signal/COPYING main/signal/DESCRIPTION main/signal/INDEX main/signal/NEWS main/signal/inst/.svnignore main/signal/inst/__power.m main/signal/inst/ar_psd.m main/signal/inst/arburg.m main/signal/inst/aryule.m main/signal/inst/barthannwin.m main/signal/inst/besselap.m main/signal/inst/besself.m main/signal/inst/bilinear.m main/signal/inst/bitrevorder.m main/signal/inst/blackmanharris.m main/signal/inst/blackmannuttall.m main/signal/inst/bohmanwin.m main/signal/inst/boxcar.m main/signal/inst/buffer.m main/signal/inst/buttap.m main/signal/inst/butter.m main/signal/inst/buttord.m main/signal/inst/cceps.m main/signal/inst/cheb.m main/signal/inst/cheb1ap.m main/signal/inst/cheb1ord.m main/signal/inst/cheb2ap.m main/signal/inst/cheb2ord.m main/signal/inst/chebwin.m main/signal/inst/cheby1.m main/signal/inst/cheby2.m main/signal/inst/chirp.m main/signal/inst/clustersegment.m main/signal/inst/cmorwavf.m main/signal/inst/cohere.m main/signal/inst/convmtx.m main/signal/inst/cplxreal.m main/signal/inst/cpsd.m main/signal/inst/csd.m main/signal/inst/czt.m main/signal/inst/data2fun.m main/signal/inst/dct.m main/signal/inst/dct2.m main/signal/inst/dctmtx.m main/signal/inst/decimate.m main/signal/inst/dftmtx.m main/signal/inst/diric.m main/signal/inst/downsample.m main/signal/inst/dst.m main/signal/inst/dwt.m main/signal/inst/ellip.m main/signal/inst/ellipap.m main/signal/inst/ellipord.m main/signal/inst/fht.m main/signal/inst/filtfilt.m main/signal/inst/filtic.m main/signal/inst/findpeaks.m main/signal/inst/fir1.m main/signal/inst/fir2.m main/signal/inst/firls.m main/signal/inst/flattopwin.m main/signal/inst/fracshift.m main/signal/inst/freqs.m main/signal/inst/freqs_plot.m main/signal/inst/fwhm.m main/signal/inst/fwht.m main/signal/inst/gauspuls.m main/signal/inst/gaussian.m main/signal/inst/gausswin.m main/signal/inst/gmonopuls.m main/signal/inst/grpdelay.m main/signal/inst/hann.m main/signal/inst/hilbert.m main/signal/inst/idct.m main/signal/inst/idct2.m main/signal/inst/idst.m main/signal/inst/ifht.m main/signal/inst/ifwht.m main/signal/inst/iirlp2mb.m main/signal/inst/impinvar.m main/signal/inst/impz.m main/signal/inst/interp.m main/signal/inst/invfreq.m main/signal/inst/invfreqs.m main/signal/inst/invfreqz.m main/signal/inst/invimpinvar.m main/signal/inst/kaiser.m main/signal/inst/kaiserord.m main/signal/inst/levinson.m main/signal/inst/marcumq.m main/signal/inst/mexihat.m main/signal/inst/meyeraux.m main/signal/inst/morlet.m main/signal/inst/movingrms.m main/signal/inst/mscohere.m main/signal/inst/ncauer.m main/signal/inst/nuttallwin.m main/signal/inst/parzenwin.m main/signal/inst/pburg.m main/signal/inst/pei_tseng_notch.m main/signal/inst/polystab.m main/signal/inst/private/__fwht_opts__.m main/signal/inst/private/h1_z_deriv.m main/signal/inst/private/inv_residue.m main/signal/inst/private/polyrev.m main/signal/inst/private/to_real.m main/signal/inst/pulstran.m main/signal/inst/pwelch.m main/signal/inst/pyulear.m main/signal/inst/qp_kaiser.m main/signal/inst/rceps.m main/signal/inst/rectpuls.m main/signal/inst/rectwin.m main/signal/inst/resample.m main/signal/inst/residued.m main/signal/inst/residuez.m main/signal/inst/sampled2continuous.m main/signal/inst/sawtooth.m main/signal/inst/schtrig.m main/signal/inst/sftrans.m main/signal/inst/sgolay.m main/signal/inst/sgolayfilt.m main/signal/inst/shanwavf.m main/signal/inst/sigmoid_train.m main/signal/inst/sos2tf.m main/signal/inst/sos2zp.m main/signal/inst/specgram.m main/signal/inst/square.m main/signal/inst/ss2tf.m main/signal/inst/ss2zp.m main/signal/inst/tf2sos.m main/signal/inst/tf2ss.m main/signal/inst/tf2zp.m main/signal/inst/tfe.m main/signal/inst/tfestimate.m main/signal/inst/triang.m main/signal/inst/tripuls.m main/signal/inst/tukeywin.m main/signal/inst/upsample.m main/signal/inst/welchwin.m main/signal/inst/window.m main/signal/inst/wkeep.m main/signal/inst/wrev.m main/signal/inst/xcorr.m main/signal/inst/xcorr2.m main/signal/inst/xcov.m main/signal/inst/zerocrossing.m main/signal/inst/zp2sos.m main/signal/inst/zp2ss.m main/signal/inst/zp2tf.m main/signal/inst/zplane.m main/signal/src/.svnignore main/signal/src/Makefile main/signal/src/__fwht__.cc main/signal/src/cl2bp.cc main/signal/src/cl2bp_lib.cc main/signal/src/cl2bp_lib.h main/signal/src/medfilt1.cc main/signal/src/remez.cc main/signal/src/sosfilt.cc main/signal/src/upfirdn.cc |
diffstat | 161 files changed, 0 insertions(+), 17939 deletions(-) [+] |
line wrap: on
line diff
--- a/main/signal/COPYING Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - 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. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <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 <http://www.gnu.org/licenses/>. - -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: - - <program> Copyright (C) <year> <name of author> - 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 -<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 -<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- a/main/signal/DESCRIPTION Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -Name: Signal -Version: 1.2.1 -Date: 2013-03-17 -Author: various authors -Maintainer: Octave-Forge community <octave-dev@lists.sourceforge.net> -Title: Signal Processing. -Description: Signal processing tools, including filtering, windowing and display functions. -Depends: octave (>= 3.6.0), specfun, control (>= 2.2.3), general (>= 1.3.2) -## depends on specfun because of ellipke. When it moves to octave core, dependency can be removed -Autoload: no -License: GPLv3+, public domain -Url: http://octave.sf.net
--- a/main/signal/INDEX Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -signal >> Signal processing -Signals - diric - gauspuls - gmonopuls - pulstran - tripuls - rectpuls - sawtooth - square - chirp - specgram - buffer - mexihat - meyeraux - morlet - shanwavf - cmorwavf - sigmoid_train -Filtering - filtfilt - filtic - sgolayfilt - sosfilt - medfilt1 - movingrms -Filter analysis - freqs freqs_plot - grpdelay - impz - zplane - fwhm -Filter conversion - convmtx - residuez - residued - sos2tf - sos2zp - ss2tf - ss2zp - tf2sos - tf2ss - tf2zp - zp2sos - zp2ss - zp2tf - polystab -IIR Filter design - besself - buttap - butter - cheb - cheb1ap - cheb2ap - cheby1 - cheby2 - ellipap - ellip - ncauer - buttord - cheb1ord - cheb2ord - ellipord - besselap - sftrans - bilinear - impinvar - invimpinvar - iirlp2mb - pei_tseng_notch -FIR filter design - fir1 - fir2 - firls - kaiserord - remez - sgolay - qp_kaiser - cl2bp -Transforms - czt - dctmtx - dct2 - idct2 - dct - idct - dst - idst - dftmtx - hilbert - rceps - cceps - cplxreal - bitrevorder - dwt - fht - ifht - fwht - ifwht -Power spectrum analysis - pwelch - tfe - tfestimate - cohere - csd - ar_psd - cpsd - mscohere - pburg - pyulear - xcorr - xcorr2 - xcov - __power -Window functions - window - barthannwin - blackmanharris - blackmannuttall - bohmanwin - boxcar - chebwin flattopwin - hann - kaiser - nuttallwin - triang - gaussian - gausswin - tukeywin - rectwin - welchwin - parzenwin -System identification - arburg - aryule - invfreq - invfreqs - invfreqz - levinson -Sample rate change - decimate - interp - downsample - upsample - resample - upfirdn - data2fun -Utility - buffer - findpeaks - fracshift - marcumq - wkeep - wrev - zerocrossing - sampled2continuous - schtrig - clustersegment
--- a/main/signal/NEWS Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -Summary of important user-visible changes for releases of the signal package - -=============================================================================== -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!
--- a/main/signal/inst/.svnignore Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -PKG_ADD -*.octlink -*.oct
--- a/main/signal/inst/__power.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: [P, w] = __power (b, a, [, nfft [, Fs]] [, range] [, units]) -## -## 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. - -## TODO: consider folding this into freqz --- just one more parameter to -## TODO: 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 -
--- a/main/signal/inst/ar_psd.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,291 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% Usage: -%% [psd,f_out] = ar_psd(a,v,freq,Fs,range,method,plot_type) -%% -%% 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". This function runs on octave and matlab. -%% -%% 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 %% [vector] 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 %% [real scalar] square of the moving-average coefficient 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 returned values are not required by the caller, the spectrum -%% is plotted and nothing is returned. -%% psd %% [real vector] estimate of power-spectral density -%% f_out %% [real vector] frequency values -%% -%% N.B. arburg runs in octave and matlab, and does not depend on octave-forge -%% or signal-processing-toolbox functions. -%% -%% 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 -%% - -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 areguments - 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.' ); - end - 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.' ); - end - Fs = arg; - %% - else - error( 'ar_psd: control arg must be string.' ); - end - %% - %% 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 ); - end - end -%% 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' ); - end - 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; - end - end - %% - %% 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; - end - fft_out = polyval( a(len_coeffs:-1:1), exp( (-i*2*pi/Fs) * freq ) ); - end - %% - %% 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); - end - %% - %% 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)]; - end - %% - %% 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)); - end - end -end
--- a/main/signal/inst/arburg.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% [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 %% [vector] sampled data -%% -%% poles %% [integer scalar] number of poles in the AR model or -%% %% limit to the number of poles if a -%% %% valid "stop_crit" is provided. -%% -%% 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). Recognised 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 %% [polynomial/vector] list of (P+1) autoregression coeffic- -%% %% ients; 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 %% [real scalar] mean square of residual noise from the -%% %% whitening operation of the Burg lattice filter. -%% -%% k %% [column vector] 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) arburg runs in octave and matlab, does not depend on octave forge -%% or signal-processing-toolbox functions. -%% (4) 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 biassed 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 - - -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 recognised' ); - end - else - use_inf_crit = 0; - use_FPE = 0; - end - %% - %% 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; - end - %% 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; - end - %% - %% (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; - end - end - %% 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; - end - 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; - end - end - %% end of for loop - %% - varargout{1} = [1 a]; - varargout{2} = v; - if ( nargout>=3 ) - varargout{3} = k; - end -end -end - -%%
--- a/main/signal/inst/aryule.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: [a, v, k] = aryule (x, p) -## -## fits an AR (p)-model with Yule-Walker estimates. -## x = data vector to estimate -## a: AR coefficients -## v: variance of white noise -## k: reflection coeffients 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. - -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')
--- a/main/signal/inst/barthannwin.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{w}] =} barthannwin(@var{L}) -## Compute the modified Bartlett-Hann window of lenght L. -## @seealso{rectwin, bartlett} -## @end deftypefn - -function [w] = barthannwin(L) - if (nargin < 1) - print_usage; - elseif (! isscalar(L) || L < 0) - error("L must be a positive integer"); - endif - L = round(L); - - if (L == 1) - w = 1; - else - N = L-1; - n = 0:N; - - w = 0.62 -0.48.*abs(n./(L-1) - 0.5)+0.38*cos(2.*pi*(n./(L-1)-0.5)); - w = w'; - endif -endfunction
--- a/main/signal/inst/besselap.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Return bessel analog filter prototype. -## -## References: -## -## http://en.wikipedia.org/wiki/Bessel_polynomials - -function [zero, pole, gain] = besselap (n) - - if (nargin>1 || nargin<1) - print_usage; - end - - ## interpret the input parameters - if (!(length(n)==1 && n == round(n) && n > 0)) - error ("besselap: filter order n must be a positive integer"); - end - - 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
--- a/main/signal/inst/besself.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## 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 -## -## [b,a] = besself(n, [Wl, Wh]) -## band pass filter with edges pi*Wl and pi*Wh radians -## -## [b,a] = besself(n, [Wl, Wh], 'stop') -## band reject filter with edges pi*Wl and pi*Wh 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. - -function [a, b, c, d] = besself (n, W, varargin) - - if (nargin>4 || nargin<2) || (nargout>4 || nargout<2) - print_usage; - end - - ## interpret the input parameters - if (!(length(n)==1 && n == round(n) && n > 0)) - error ("besself: filter order n must be a positive integer"); - end - - stop = 0; - digital = 0; - for i=1:length(varargin) - switch varargin{i} - case 's', digital = 0; - case 'z', digital = 1; - case { 'high', 'stop' }, stop = 1; - case { 'low', 'pass' }, stop = 0; - otherwise, error ("besself: expected [high|stop] or [s|z]"); - endswitch - endfor - - - [r, c]=size(W); - if (!(length(W)<=2 && (r==1 || c==1))) - error ("besself: frequency must be given as w0 or [w0, w1]"); - elseif (!(length(W)==1 || length(W) == 2)) - error ("besself: only one filter band allowed"); - elseif (length(W)==2 && !(W(1) < W(2))) - error ("besself: first band edge must be smaller than second"); - endif - - if ( digital && !all(W >= 0 & W <= 1)) - error ("besself: critical frequencies must be in (0 1)"); - elseif ( !digital && !all(W >= 0 )) - error ("besself: critical frequencies must be in (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
--- a/main/signal/inst/bilinear.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: [Zz, Zp, Zg] = bilinear(Sz, Sp, Sg, T) -## [Zb, Za] = bilinear(Sb, Sa, T) -## -## 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. - -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; - end - - 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"); - end - -## ---------------- ------------------------- ------------------------ -## 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); - end - - if nargout==2, [Zz, Zp] = zp2tf(Zz, Zp, Zg); endif -endfunction
--- a/main/signal/inst/bitrevorder.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{y} @var{i}] =} bitrevorder(@var{x}) -## Reorder x in the bit reversed order -## @seealso{fft,ifft} -## @end deftypefn - -function [y i] = bitrevorder(x) - - if(nargin < 1 || nargin >1) - print_usage; - elseif(log2(length(x)) ~= floor(log2(length(x)))) - error('x must have a length equal to a power of 2'); - end - - old_ind = 0:length(x)-1; - new_ind = bi2de(fliplr(de2bi(old_ind))); - i = new_ind + 1; - - y(old_ind+1) = x(i); - -endfunction - -## The following functions, de2bi and bi2de, are from the communications package. -## However, the communications package is already dependent on the signal -## package and to avoid circular dependencies their code was copied here. Anyway, -## in the future bitrevorder should be rewritten as to not use this functions -## at all (and pkg can be fixed to support circular dependencies on pkg load -## as it already does for pkg install). - -## note that aside copying the code from the communication package, their input -## check was removed since in this context they were always being called with -## nargin == 1 - -function b = de2bi (d, n, p, f) - - p = 2; - n = floor ( log (max (max (d), 1)) ./ log (p) ) + 1; - f = 'right-msb'; - - d = d(:); - if ( any (d < 0) || any (d != floor (d)) ) - error ("de2bi: d must only contain non-negative integers"); - endif - - if (isempty (n)) - n = floor ( log (max (max (d), 1)) ./ log (p) ) + 1; - endif - - power = ones (length (d), 1) * (p .^ [0 : n-1] ); - d = d * ones (1, n); - b = floor (rem (d, p*power) ./ power); - - if (strcmp (f, 'left-msb')) - b = b(:,columns(b):-1:1); - elseif (!strcmp (f, 'right-msb')) - error ("de2bi: unrecognized flag"); - endif - -endfunction - - -function d = bi2de (b, p, f) - - p = 2; - f = 'right-msb'; - - if ( any (b(:) < 0) || any (b(:) != floor (b(:))) || any (b(:) > p - 1) ) - error ("bi2de: d must only contain integers in the range [0, p-1]"); - endif - - if (strcmp (f, 'left-msb')) - b = b(:,size(b,2):-1:1); - elseif (!strcmp (f, 'right-msb')) - error ("bi2de: unrecognized flag"); - endif - - if (length (b) == 0) - d = []; - else - d = b * ( p .^ [ 0 : (columns(b)-1) ]' ); - endif - -endfunction
--- a/main/signal/inst/blackmanharris.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{w}] =} blackmanharris(@var{L}) -## Compute the Blackman-Harris window. -## @seealso{rectwin, bartlett} -## @end deftypefn - -function [w] = blackmanharris (L) - if (nargin < 1) - print_usage; - elseif(! isscalar(L)) - error("L must be a number"); - endif - - if (L == 1) - w = 1; - else - N = L-1; - a0 = 0.35875; - a1 = 0.48829; - a2 = 0.14128; - a3 = 0.01168; - n = (0 : N)'; - w = a0 - a1.*cos(2.*pi.*n./N) + a2.*cos(4.*pi.*n./N) - a3.*cos(6.*pi.*n./N); - endif -endfunction
--- a/main/signal/inst/blackmannuttall.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{w}] =} blackmannuttall(@var{L}) -## Compute the Blackman-Nuttall window. -## @seealso{nuttallwin, kaiser} -## @end deftypefn - -function [w] = blackmannuttall(L) - if (nargin < 1) - print_usage; - elseif (! isscalar(L)) - error("L must be a number"); - endif - - if (L == 1) - w = 1; - else - N = L-1; - a0 = 0.3635819; - a1 = 0.4891775; - a2 = 0.1365995; - a3 = 0.0106411; - n = 0:N; - w = a0 - a1.*cos(2.*pi.*n./N) + a2.*cos(4.*pi.*n./N) - a3.*cos(6.*pi.*n./N); - w = w.'; - endif -endfunction
--- a/main/signal/inst/bohmanwin.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{w}] =} bohmanwin(@var{L}) -## Compute the Bohman window of lenght L. -## @seealso{rectwin, bartlett} -## @end deftypefn - -function [w] = bohmanwin(L) - if (nargin < 1) - print_usage - elseif(! isscalar(L)) - error("L must be a number"); - elseif(L < 0) - error('L must be positive'); - end - - if(L ~= floor(L)) - L = round(L); - warning('L rounded to the nearest integer.'); - end - - if(L == 0) - w = []; - - elseif(L == 1) - w = 1; - - else - N = L-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'; - end -endfunction
--- a/main/signal/inst/boxcar.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: w = boxcar (n) -## -## Returns the filter coefficients of a rectangular window of length n. - -function w = boxcar (n) - - if (nargin != 1) - print_usage; - elseif !isscalar(n) || n != floor(n) || n <= 0 - error ("boxcar: n must be an integer > 0"); - endif - - w = ones(n, 1); - -endfunction
--- a/main/signal/inst/buffer.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,275 +0,0 @@ -## Copyright (C) 2008 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; if not, see <http://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 inetger"); - endif - if (nargin < 3) - p = 0; - elseif (!isscalar (p) || p != floor (p) || p >= n) - error ("buffer: p must be an inetger 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; - while (in > 0) - y (1 : in, off) = opt(off:end); - off++; - in = in - 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]);
--- a/main/signal/inst/buttap.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -## 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; if not, see <http://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 only for matlab compatibility 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
--- a/main/signal/inst/butter.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,176 +0,0 @@ -## 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> -## -## 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/>. - -## Generate a butterworth filter. -## Default is a discrete space (Z) filter. -## -## [b,a] = butter(n, Wc) -## low pass filter with cutoff pi*Wc radians -## -## [b,a] = butter(n, Wc, 'high') -## high pass filter with cutoff pi*Wc radians -## -## [b,a] = butter(n, [Wl, Wh]) -## band pass filter with edges pi*Wl and pi*Wh radians -## -## [b,a] = butter(n, [Wl, Wh], 'stop') -## band reject filter with edges pi*Wl and pi*Wh radians -## -## [z,p,g] = butter(...) -## return filter as zero-pole-gain rather than coefficients of the -## numerator and denominator polynomials. -## -## [...] = butter(...,'s') -## return a Laplace space filter, W can be larger than 1. -## -## [a,b,c,d] = butter(...) -## return state-space matrices -## -## References: -## -## Proakis & Manolakis (1992). Digital Signal Processing. New York: -## Macmillan Publishing Company. - -function [a, b, c, d] = butter (n, W, varargin) - - if (nargin>4 || nargin<2) || (nargout>4 || nargout<2) - print_usage; - end - - ## interpret the input parameters - if (!(length(n)==1 && n == round(n) && n > 0)) - error ("butter: filter order n must be a positive integer"); - end - - stop = 0; - digital = 1; - for i=1:length(varargin) - switch varargin{i} - case 's', digital = 0; - case 'z', digital = 1; - case { 'high', 'stop' }, stop = 1; - case { 'low', 'pass' }, stop = 0; - otherwise, error ("butter: expected [high|stop] or [s|z]"); - endswitch - endfor - - - [r, c]=size(W); - if (!(length(W)<=2 && (r==1 || c==1))) - error ("butter: frequency must be given as w0 or [w0, w1]"); - elseif (!(length(W)==1 || length(W) == 2)) - error ("butter: only one filter band allowed"); - elseif (length(W)==2 && !(W(1) < W(2))) - error ("butter: first band edge must be smaller than second"); - endif - - if ( digital && !all(W >= 0 & W <= 1)) - error ("butter: critical frequencies must be in (0 1)"); - elseif ( !digital && !all(W >= 0 )) - error ("butter: critical frequencies must be in (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 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; end # pure real value at exp(i*pi) - zero = []; - gain = C^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 - -%!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 ) - -%!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;")
--- a/main/signal/inst/buttord.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Compute butterworth filter order and cutoff for the desired response -## characteristics. Rp is the allowable decibels of ripple in the pass -## band. Rs is the minimum attenuation in the stop band. -## -## [n, Wc] = buttord(Wp, Ws, Rp, Rs) -## Low pass (Wp<Ws) or high pass (Wp>Ws) filter design. Wp is the -## pass band edge and Ws is the stop band edge. Frequencies are -## normalized to [0,1], corresponding to the range [0,Fs/2]. -## -## [n, Wc] = buttord([Wp1, Wp2], [Ws1, Ws2], Rp, Rs) -## Band pass (Ws1<Wp1<Wp2<Ws2) or band reject (Wp1<Ws1<Ws2<Wp2) -## filter design. Wp gives the edges of the pass band, and Ws gives -## the edges of the stop band. -## -## Theory: |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. For high pass filters, subtracting the band edges -## from Fs/2, performing the test, and swapping the resulting Wc back -## works beautifully. For bandpass and bandstop filters this process -## significantly overdesigns. Artificially dividing N by 2 in this case -## helps a lot, but it still overdesigns. -## -## See also: butter - -function [n, Wc] = buttord(Wp, Ws, Rp, Rs) - if nargin != 4 - print_usage; - elseif length(Wp) != length(Ws) - error("buttord: Wp and Ws must have the same length"); - elseif length(Wp) != 1 && length(Wp) != 2 - error("buttord: Wp,Ws must have length 1 or 2"); - elseif length(Wp) == 2 && (all(Wp>Ws) || all(Ws>Wp) || diff(Wp)<=0 || diff(Ws)<=0) - error("buttord: Wp(1)<Ws(1)<Ws(2)<Wp(2) or Ws(1)<Wp(1)<Wp(2)<Ws(2)"); - end - - if length(Wp) == 2 - warning("buttord: seems to overdesign bandpass and bandreject filters"); - end - - T = 2; - - ## if high pass, reverse the sense of the test - stop = find(Wp > Ws); - Wp(stop) = 1-Wp(stop); # stop will be at most length 1, so no need to - Ws(stop) = 1-Ws(stop); # subtract from ones(1,length(stop)) - - ## warp the target frequencies according to the bilinear transform - Ws = (2/T)*tan(pi*Ws./T); - Wp = (2/T)*tan(pi*Wp./T); - - ## compute minimum n which satisfies all band edge conditions - ## the factor 1/length(Wp) is an artificial correction for the - ## band pass/stop case, which otherwise significantly overdesigns. - qs = log(10^(Rs/10) - 1); - qp = log(10^(Rp/10) - 1); - n = ceil(max(0.5*(qs - qp)./log(Ws./Wp))/length(Wp)); - - ## compute -3dB cutoff given Wp, Rp and n - Wc = exp(log(Wp) - qp/2/n); - - ## unwarp the returned frequency - Wc = atan(T/2*Wc)*T/pi; - - ## if high pass, reverse the sense of the test - Wc(stop) = 1-Wc(stop); - -endfunction
--- a/main/signal/inst/cceps.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -## Copyright (C) 1994 Dept of Probability Theory and Statistics TU Wien <Andreas.Weingessel@ci.tuwien.ac.at> -## -## This program is free software; you can redistribute it and/or modify it under -## the terms of the GNU General Public License as published by the Free Software -## Foundation; either version 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/>. - -## usage: cceps (x [, correct]) -## -## Returns 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. - -## Author: Andreas Weingessel <Andreas.Weingessel@ci.tuwien.ac.at> -## Apr 1, 1994 -## Last modifified by AW on Nov 8, 1994 - -function cep = cceps (x, c) - - if (nargin == 1) - c = 0; - 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: bad signal x, ", ... - "some Fourier coefficients are zero."]; - - F = fft (x); - if (min (abs (F)) == 0) - error (bad_signal_message); - endif - - # determine if correction necessary - half = fix (nr / 2); - cor = 0; - 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
--- a/main/signal/inst/cheb.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Usage: 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)). - -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
--- a/main/signal/inst/cheb1ap.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -## 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; if not, see <http://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 only for matlab compatibility and is equivalent to -## @code{cheby1 (@var{n}, @var{Rp}, 1, "s")} -## -## @seealso{cheby1} -## @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"); -endfunction
--- a/main/signal/inst/cheb1ord.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -## Copyright (C) 2000 Paul Kienzle <pkienzle@users.sf.net> -## Copyright (C) 2000 Laurent S. Mazet -## -## 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/>. - -## Compute chebyshev type I filter order and cutoff for the desired response -## characteristics. Rp is the allowable decibels of ripple in the pass -## band. Rs is the minimum attenuation in the stop band. -## -## [n, Wc] = cheb1ord(Wp, Ws, Rp, Rs) -## Low pass (Wp<Ws) or high pass (Wp>Ws) filter design. Wp is the -## pass band edge and Ws is the stop band edge. Frequencies are -## normalized to [0,1], corresponding to the range [0,Fs/2]. -## -## [n, Wc] = cheb1ord([Wp1, Wp2], [Ws1, Ws2], Rp, Rs) -## Band pass (Ws1<Wp1<Wp2<Ws2) or band reject (Wp1<Ws1<Ws2<Wp2) -## filter design. Wp gives the edges of the pass band, and Ws gives -## the edges of the stop band. -## -## See also: cheby1 - -function [n, Wc] = cheb1ord(Wp, Ws, Rp, Rs) - - if nargin != 4 - print_usage; - elseif length(Wp) != length(Ws) - error("cheb1ord: Wp and Ws must have the same length"); - elseif length(Wp) != 1 && length(Wp) != 2 - error("cheb1ord: Wp,Ws must have length 1 or 2"); - elseif length(Wp) == 2 && ... - (all(Wp>Ws) || all(Ws>Wp) || diff(Wp)<=0 || diff(Ws)<=0) - error("cheb1ord: Wp(1)<Ws(1)<Ws(2)<Wp(2) or Ws(1)<Wp(1)<Wp(2)<Ws(2)"); - end - - T = 2; - - ## returned frequency is the same as the input frequency - Wc = Wp; - - ## warp the target frequencies according to the bilinear transform - Ws = (2/T)*tan(pi*Ws./T); - Wp = (2/T)*tan(pi*Wp./T); - - if (Wp(1) < Ws(1)) - ## low pass - if (length(Wp) == 1) - Wa = Ws/Wp; - else - ## band reject - error ("band reject is not implement yet."); - endif; - else - ## if high pass, reverse the sense of the test - if (length(Wp) == 1) - Wa = Wp/Ws; - else - ## band pass - Wa=(Ws.^2 - Wp(1)*Wp(2))./(Ws*(Wp(1)-Wp(2))); - endif; - endif; - Wa = min(abs(Wa)); - - ## 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)); - -endfunction - -%!demo -%! Fs = 10000; -%! [n, Wc] = cheb1ord (1000/(Fs/2), 1200/(Fs/2), 0.5, 29); -%! -%! subplot (221); -%! axis ([ 0, 1500, -1, 0]); -%! title("Pass band Wp=1000 Rp=0.5"); -%! xlabel("Frequency (Hz)"); -%! ylabel("Attenuation (dB)"); -%! grid; -%! plot ([0, 1000, 1000, 0, 0], [0, 0, -0.5, -0.5, 0], ";;"); -%! hold on; -%! [b, a] = cheby1 (n, 0.5, Wc); -%! [h, w] = freqz (b, a, [], Fs); -%! plot (w, 20*log10(abs(h)), ";;"); -%! hold off; -%! -%! subplot (222); -%! axis ([ 0, Fs/2, -250, 0]); -%! title("Stop band Ws=1200 Rs=29"); -%! xlabel("Frequency (Hz)"); -%! ylabel("Attenuation (dB)"); -%! grid; -%! plot ([1200, Fs/2, Fs/2, 1200, 1200], [-29, -29, -500, -500, -29], ";;"); -%! hold on; -%! [b, a] = cheby1 (n, 0.5, Wc); -%! [h, w] = freqz (b, a, [], Fs); -%! plot (w, 20*log10(abs(h)), ";;"); -%! hold off; -%! -%! subplot (223); -%! axis ([ 990, 1010, -0.6, -0.4]); -%! title("Pass band detail Wp=1000 Rp=0.5"); -%! xlabel("Frequency (Hz)"); -%! ylabel("Attenuation (dB)"); -%! grid; -%! plot ([0, 1000, 1000, 0, 0], [0, 0, -0.5, -0.5, 0], ";;"); -%! hold on; -%! [b, a] = cheby1 (n, 0.5, Wc); -%! [h, w] = freqz (b, a, [990:1010], Fs); -%! plot (w, 20*log10(abs(h)), ";filter n;"); -%! [b, a] = cheby1 (n-1, 0.5, Wc); -%! [h, w] = freqz (b, a, [990:1010], Fs); -%! plot (w, 20*log10(abs(h)), ";filter n-1;"); -%! [b, a] = cheby1 (n+1, 0.5, Wc); -%! [h, w] = freqz (b, a, [990:1010], Fs); -%! plot (w, 20*log10(abs(h)), ";filter n+1;"); -%! hold off; -%! -%! subplot (224); -%! axis ([ 1190, 1210, -40, -20]); -%! title("Stop band detail Wp=1200 Rp=29"); -%! xlabel("Frequency (Hz)"); -%! ylabel("Attenuation (dB)"); -%! grid; -%! plot ([1200, Fs/2, Fs/2, 1200, 1200], [-29, -29, -500, -500, -29], ";;"); -%! hold on; -%! [b, a] = cheby1 (n, 0.5, Wc); -%! [h, w] = freqz (b, a, [1190:1210], Fs); -%! plot (w, 20*log10(abs(h)), ";filter n;"); -%! [b, a] = cheby1 (n-1, 0.5, Wc); -%! [h, w] = freqz (b, a, [1190:1210], Fs); -%! plot (w, 20*log10(abs(h)), ";filter n-1;"); -%! [b, a] = cheby1 (n+1, 0.5, Wc); -%! [h, w] = freqz (b, a, [1190:1210], Fs); -%! plot (w, 20*log10(abs(h)), ";filter n+1;"); -%! hold off;
--- a/main/signal/inst/cheb2ap.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -## 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; if not, see <http://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 only for matlab compatibility and is equivalent to -## @code{cheby2 (@var{n}, @var{Rs}, 1, "s")} -## -## @seealso{cheby2} -## @end deftypefn - -function [z, p, g] = cheb2ap (n, Rp) - 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
--- a/main/signal/inst/cheb2ord.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Compute chebyshev type II filter order and cutoff for the desired response -## characteristics. Rp is the allowable decibels of ripple in the pass -## band. Rs is the minimum attenuation in the stop band. -## -## [n, Wc] = cheb2ord(Wp, Ws, Rp, Rs) -## Low pass (Wp<Ws) or high pass (Wp>Ws) filter design. Wp is the -## pass band edge and Ws is the stop band edge. Frequencies are -## normalized to [0,1], corresponding to the range [0,Fs/2]. -## -## [n, Wc] = cheb2ord([Wp1, Wp2], [Ws1, Ws2], Rp, Rs) -## Band pass (Ws1<Wp1<Wp2<Ws2) or band reject (Wp1<Ws1<Ws2<Wp2) -## filter design. Wp gives the edges of the pass band, and Ws gives -## the edges of the stop band. -## -## Theory: -## -## See also: cheby2 - -function [n, Wc] = cheb2ord(Wp, Ws, Rp, Rs) - - if nargin != 4 - print_usage; - elseif length(Wp) != length(Ws) - error("cheb2ord: Wp and Ws must have the same length"); - elseif length(Wp) != 1 && length(Wp) != 2 - error("cheb2ord: Wp,Ws must have length 1 or 2"); - elseif length(Wp) == 2 && ... - (all(Wp>Ws) || all(Ws>Wp) || diff(Wp)<=0 || diff(Ws)<=0) - error("cheb2ord: Wp(1)<Ws(1)<Ws(2)<Wp(2) or Ws(1)<Wp(1)<Wp(2)<Ws(2)"); - end - - T = 2; - - ## returned frequency is the same as the input frequency - Wc = Ws; - - ## warp the target frequencies according to the bilinear transform - Ws = (2/T)*tan(pi*Ws./T); - Wp = (2/T)*tan(pi*Wp./T); - - if (Wp(1) < Ws(1)) - ## low pass - if (length(Wp) == 1) - Wa = Wp/Ws; - else - ## band reject - error ("band reject is not implement yet."); - endif; - else - ## if high pass, reverse the sense of the test - if (length(Wp) == 1) - Wa = Ws/Wp; - else - ## band pass - Wa=(Wp.^2 - Ws(1)*Ws(2))./(Wp*(Ws(1)-Ws(2))); - endif; - endif; - Wa = min(abs(Wa)); - - ## 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(1/Wa)); - -endfunction - -%!demo -%! Fs = 10000; -%! [n, Wc] = cheb2ord (1000/(Fs/2), 1200/(Fs/2), 0.5, 29); -%! -%! subplot (221); -%! plot ([0, 1000, 1000, 0, 0], [0, 0, -0.5, -0.5, 0], ";;"); -%! hold on; -%! grid; -%! title("Pass band Wp=1000 Rp=0.0"); -%! xlabel("Frequency (Hz)"); -%! ylabel("Attenuation (dB)"); -%! [b, a] = cheby2 (n, 29, Wc); -%! [h, w] = freqz (b, a, [], Fs); -%! plot (w, 20*log10(abs(h)), ";;"); -%! axis ([ 0, 1500, -1, 0]); -%! hold off; -%! -%! subplot (222); -%! plot ([1200, Fs/2, Fs/2, 1200, 1200], [-29, -29, -500, -500, -29], ";;"); -%! hold on; -%! axis ([ 0, Fs/2, -250, 0]); -%! title("Stop band Ws=1200 Rs=29"); -%! xlabel("Frequency (Hz)"); -%! ylabel("Attenuation (dB)"); -%! grid; -%! [b, a] = cheby2 (n, 29, Wc); -%! [h, w] = freqz (b, a, [], Fs); -%! plot (w, 20*log10(abs(h)), ";;"); -%! hold off; -%! -%! subplot (223); -%! plot ([0, 1000, 1000, 0, 0], [0, 0, -0.5, -0.5, 0], ";;"); -%! hold on; -%! axis ([ 800, 1010, -0.6, -0.0]); -%! title("Pass band detail Wp=1000 Rp=0.5"); -%! xlabel("Frequency (Hz)"); -%! ylabel("Attenuation (dB)"); -%! grid; -%! [b, a] = cheby2 (n, 29, Wc); -%! [h, w] = freqz (b, a, [800:1010], Fs); -%! plot (w, 20*log10(abs(h)), "r;filter n;"); -%! [b, a] = cheby2 (n-1, 29, Wc); -%! [h, w] = freqz (b, a, [800:1010], Fs); -%! plot (w, 20*log10(abs(h)), "b;filter n-1;"); -%! [b, a] = cheby2 (n+1, 29, Wc); -%! [h, w] = freqz (b, a, [800:1010], Fs); -%! plot (w, 20*log10(abs(h)), "g;filter n+1;"); -%! hold off; -%! -%! subplot (224); -%! plot ([1200, Fs/2, Fs/2, 1200, 1200], [-29, -29, -500, -500, -29], ";;"); -%! hold on; -%! axis ([ 1190, 1210, -40, -20]); -%! title("Stop band detail Wp=1200 Rp=29"); -%! xlabel("Frequency (Hz)"); -%! ylabel("Attenuation (dB)"); -%! grid; -%! [b, a] = cheby2 (n, 29, Wc); -%! [h, w] = freqz (b, a, [1190:1210], Fs); -%! plot (w, 20*log10(abs(h)), "r;filter n;"); -%! [b, a] = cheby2 (n-1, 29, Wc); -%! [h, w] = freqz (b, a, [1190:1210], Fs); -%! plot (w, 20*log10(abs(h)), "b;filter n-1;"); -%! [b, a] = cheby2 (n+1, 29, Wc); -%! [h, w] = freqz (b, a, [1190:1210], Fs); -%! plot (w, 20*log10(abs(h)), "g;filter n+1;"); -%! hold off;
--- a/main/signal/inst/chebwin.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Usage: chebwin (L, at) -## -## Returns the filter coefficients of the L-point Dolph-Chebyshev window -## with at dB of attenuation in the stop-band of the corresponding -## Fourier transform. 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(L-1, beta * cos(pi * k/L)) -## W(k) = ------------------------------- -## Cheb(L-1, beta) -## -## with -## -## beta = cosh(1/(L-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 - -function w = chebwin (L, at) - - if (nargin < 1 || nargin > 2) - print_usage; - elseif (nargin == 1) - at = 100; - endif - - if !(isscalar (L) && (L == round(L)) && (L > 0)) - error ("chebwin: L has to be a positive integer"); - elseif !(isscalar (at) && (at == real (at))) - error ("chebwin: at has to be a real scalar"); - endif - - if (L == 1) - w = 1; - else - # beta calculation - gamma = 10^(-at/20); - beta = cosh(1/(L-1) * acosh(1/gamma)); - # freq. scale - k = (0:L-1); - x = beta*cos(pi*k/L); - # Chebyshev window (freq. domain) - p = cheb(L-1, x); - # inverse Fourier transform - if (rem(L,2)) - w = real(fft(p)); - M = (L+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/L * (0:L-1)); - w = real(fft(p)); - M = L/2+1; - w = w/w(2); - w = [w(M:-1:2) w(2:M)]'; - endif - endif - - w = w ./ max (w (:)); -endfunction
--- a/main/signal/inst/cheby1.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Generate an Chebyshev type I filter with Rp dB of pass band 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. - -function [a,b,c,d] = cheby1(n, Rp, W, varargin) - - if (nargin>5 || nargin<3) || (nargout>4 || nargout<2) - print_usage; - endif - - ## interpret the input parameters - if (!(length(n)==1 && n == round(n) && n > 0)) - error ("cheby1: filter order n must be a positive integer"); - endif - - stop = 0; - digital = 1; - for i=1:length(varargin) - switch varargin{i} - case 's', digital = 0; - case 'z', digital = 1; - case { 'high', 'stop' }, stop = 1; - case { 'low', 'pass' }, stop = 0; - otherwise, error ("cheby1: expected [high|stop] or [s|z]"); - endswitch - endfor - - [r, c]=size(W); - if (!(length(W)<=2 && (r==1 || c==1))) - error ("cheby1: frequency must be given as w0 or [w0, w1]"); - elseif (!(length(W)==1 || length(W) == 2)) - error ("cheby1: only one filter band allowed"); - elseif (length(W)==2 && !(W(1) < W(2))) - error ("cheby1: first band edge must be smaller than second"); - endif - - if ( digital && !all(W >= 0 & W <= 1)) - error ("cheby1: critical frequencies must be in (0 1)"); - elseif ( !digital && !all(W >= 0 )) - error ("cheby1: critical frequencies must be in (0 inf)"); - endif - - if (Rp < 0) - error("cheby1: passband ripple must be positive decibels"); - end - - ## 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 - 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
--- a/main/signal/inst/cheby2.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Generate an Chebyshev type II filter with Rs dB of stop band 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. - -function [a,b,c,d] = cheby2(n, Rs, W, varargin) - - if (nargin>5 || nargin<3) || (nargout>4 || nargout<2) - print_usage; - end - - ## interpret the input parameters - if (!(length(n)==1 && n == round(n) && n > 0)) - error ("cheby2: filter order n must be a positive integer"); - end - - - stop = 0; - digital = 1; - for i=1:length(varargin) - switch varargin{i} - case 's', digital = 0; - case 'z', digital = 1; - case { 'high', 'stop' }, stop = 1; - case { 'low', 'pass' }, stop = 0; - otherwise, error ("cheby2: expected [high|stop] or [s|z]"); - endswitch - endfor - - [r, c]=size(W); - if (!(length(W)<=2 && (r==1 || c==1))) - error ("cheby2: frequency must be given as w0 or [w0, w1]"); - elseif (!(length(W)==1 || length(W) == 2)) - error ("cheby2: only one filter band allowed"); - elseif (length(W)==2 && !(W(1) < W(2))) - error ("cheby2: first band edge must be smaller than second"); - endif - - if ( digital && !all(W >= 0 & W <= 1)) - error ("cheby2: critical frequencies must be in (0 1)"); - elseif ( !digital && !all(W >= 0 )) - error ("cheby2: critical frequencies must be in (0 inf)"); - endif - - if (Rs < 0) - error("cheby2: stopband attenuation must be positive decibels"); - end - - ## 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 - 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
--- a/main/signal/inst/chirp.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -## Copyright (C) 1999-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; if not, see <http://www.gnu.org/licenses/>. - -## usage: y = chirp(t [, f0 [, t1 [, f1 [, form [, 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 ] -## form: 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 -## -## Example -## specgram(chirp([0:0.001:5])); # linear, 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)) + 2*pi*f0*t + phase); - -function y = chirp(t, f0, t1, f1, form, phase) - - if nargin < 1 || nargin > 6 - print_usage; - endif - if nargin < 2, f0 = []; endif - if nargin < 3, t1 = []; endif - if nargin < 4, f1 = []; endif - if nargin < 5, form = []; endif - if nargin < 6, phase = []; endif - - if isempty(f0), f0 = 0; endif - if isempty(t1), t1 = 1; endif - if isempty(f1), f1 = 100; endif - if isempty(form), form = "linear"; endif - if isempty(phase), phase = 0; endif - - phase = 2*pi*phase/360; - - if strcmp(form, "linear") - a = pi*(f1 - f0)/t1; - b = 2*pi*f0; - y = cos(a*t.^2 + b*t + phase); - elseif strcmp(form, "quadratic") - a = (2/3*pi*(f1-f0)/t1/t1); - b = 2*pi*f0; - y = cos(a*t.^3 + b*t + phase); - elseif strcmp(form, "logarithmic") - a = 2*pi*t1/log(f1-f0); - b = 2*pi*f0; - x = (f1-f0)^(1/t1); - y = cos(a*x.^t + b*t + phase); - else - error("chirp doesn't understand '%s'",form); - endif - -endfunction - -%!demo -%! specgram(chirp([0:0.001:5]),[],1000); # linear, 0-100Hz in 1 sec -%! %------------------------------------------------------------ -%! % 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 -%! specgram(chirp([-2:0.001:15], 400, 10, 100, 'quadratic')); -%! %------------------------------------------------------------ -%! % Shows a quadratic chirp of 400 Hz at t=0 and 100 Hz at t=10 -%! % Time goes from -2 to 15 seconds. - -%!demo -%! specgram(chirp([0:1/8000:5], 200, 2, 500, "logarithmic"),[],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.
--- a/main/signal/inst/clustersegment.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -## Copyright (c) 2010 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; if not, see <http://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 result is returned in a cell of size -## 1-by-Np, being Np the numer of rows in @var{unos}. Each element of the cell -## has two rows. The first row is the inital 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. -## -## @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; - end - - if xhi(i,end)==1 - % last event was up - contRange{i}(end+1) = Na; - end - - tLen = length(contRange{i}); - if tLen ~=0 - contRange{i}=reshape(contRange{i},2,tLen/2); - end - - end - - if Np == 1 - contRange = cell2mat (contRange); - end - -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)
--- a/main/signal/inst/cmorwavf.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{psi,x}] =} cmorwavf (@var{lb,ub,n,fb,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
--- a/main/signal/inst/cohere.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% Usage: -%% [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. -%% - -function [varargout] = cohere(varargin) -%% - if ( nargin<2 ) - error( 'cohere: Need at least 2 args. Use help cohere.' ); - end - 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} = []; - end - end - 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; - end - pwelch(saved_compatib); - saved_compatib = 0; -end
--- a/main/signal/inst/convmtx.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -## 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; if not, see <http://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])
--- a/main/signal/inst/cplxreal.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% -*- texinfo -*- -%% @deftypefn {Function File} {[@var{zc}, @var{zr}] =} cplxreal (@var{z}, @var{thresh}) -%% Split the vector z into its complex (@var{zc}) and real (@var{zr}) elements, -%% eliminating one of each complex-conjugate pair. -%% -%% INPUTS:@* -%% @itemize -%% @item -%% @var{z} = row- or column-vector of complex numbers@* -%% @item -%% @var{thresh} = tolerance threshold for numerical comparisons (default = 100*eps) -%% @end itemize -%% -%% RETURNED:@* -%% @itemize -%% @item -%% @var{zc} = elements of @var{z} having positive imaginary parts@* -%% @item -%% @var{zr} = elements of @var{z} having zero imaginary part@* -%% @end itemize -%% -%% Each complex element of @var{z} is assumed to have a complex-conjugate -%% counterpart elsewhere in @var{z} as well. Elements are declared real -%% if their imaginary parts have magnitude less than @var{thresh}. -%% -%% @seealso{cplxpair} -%% @end deftypefn - -function [zc,zr] = cplxreal (z, thresh = 100*eps) - - % interesting for testing: if nargin<2, thresh=1E-3; end - - if isempty(z) - zc=[]; - zr=[]; - else - zcp = cplxpair(z); % sort complex pairs, real roots at end - nz = length(z); - nzrsec = 0; - i=nz; - while i && abs(imag(zcp(i)))<thresh % determine no. of real values - zcp(i) = real(zcp(i)); - nzrsec = nzrsec+1; - i=i-1; - end - nzsect2 = nz-nzrsec; - if mod(nzsect2,2)~=0 - error('cplxreal: Odd number of complex values!'); - end - nzsec = nzsect2/2; - zc = zcp(2:2:nzsect2); - zr = zcp(nzsect2+1:nz); - end -endfunction - -%!test -%! [zc,zr] = cplxreal(roots([1 0 0 1])); -%! assert({zc,zr},{0.5+i*sin(pi/3),-1},10*eps);
--- a/main/signal/inst/cpsd.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% Usage: -%% [Pxx,freq] = cpsd(x,y,window,overlap,Nfft,Fs,range) -%% -%% Estimate cross power spectrum of data "x" and "y" by the Welch (1967) -%% periodogram/FFT method. -%% See "help pwelch" for description of arguments, hints and references - -function [varargout] = cpsd(varargin) - - %% Check fixed argument - if (nargin < 2 || nargin > 7) - print_usage (); - end - 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} = []; - end - end - 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; - end -end
--- a/main/signal/inst/csd.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% Usage: -%% [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. - -function [varargout] = csd(varargin) - - %% Check fixed argument - if ( nargin<2 ) - error( 'csd: Need at least 2 args. Use help csd.' ); - end - 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} = []; - end - end - 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; - end - pwelch(saved_compatib); -end
--- a/main/signal/inst/czt.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage y=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. - -## 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);
--- a/main/signal/inst/data2fun.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,167 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% -*- texinfo -*- -%% @deftypefn {Function File} {[@var{fhandle}, @var{fullname}] = } data2fun (@var{ti}, @var{yi}) -%% @deftypefnx {Function File} {[ @dots{} ] = } data2fun (@var{ti}, @var{yi},@var{property},@var{value}) -%% Creates 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 property-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{tmpnam} and the file is created in the current directory. @var{value} -%% must not have an extension, since .m will be appended. -%% Numerical value 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) - - %% 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); - end - - if given.file - %% TODO: check that file will be in the path. Otherwise fhabdle(0) fails. - - if !isempty(varargin{idx(1)+1}) - - [DIR fname] = fileparts(varargin{idx(1)+1}); - - else - - [DIR fname] = fileparts (tmpnam (pwd (),"agen_")); - - end - - interp_args(idx(1)+[0 1]) = []; - end - - if isempty(interp_args) - - interp_args = {"spline"}; - - end - end - - 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"... - " end\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); - - disp(["Function generated: " fullfname ]); - fhandle = eval(["@" fname]); - - else - fullfname = ""; - fhandle = @(t_) ppval (pp, t_); - - end - -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"]; - end - -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 -%! [fhandle fname] = data2fun(t,y,"file","testdata2fun"); -%! yt = testdata2fun(t); -%! -%! assert(y,yt); -%! assert(y,fhandle(t)); -%! -%! delete(fname); -%! delete([fname(1:end-2) ".mat"]); - -%!test -%! [fhandle fname] = data2fun(t,y,"file",""); -%! yt = testdata2fun(t); -%! -%! assert(y,yt); -%! assert(y,fhandle(t)); -%! -%! delete(fname); -%! delete([fname(1:end-2) ".mat"]); - -%!test -%! [fhandle fname] = data2fun(t,y,"file","testdata2fun","interp","linear"); -%! yt = testdata2fun(t); -%! -%! assert(y,yt); -%! assert(y,fhandle(t)); -%! -%! delete(fname); -%! delete([fname(1:end-2) ".mat"]);
--- a/main/signal/inst/dct.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## y = dct (x, n) -## Computes 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 even -## length. -## -## The discrete cosine transform X of 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 - -## 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
--- a/main/signal/inst/dct2.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## y = dct2 (x) -## Computes the 2-D discrete cosine transform of matrix x -## -## y = dct2 (x, m, n) or y = dct2 (x, [m n]) -## Computes the 2-D DCT of x after padding or trimming rows to m and -## columns to n. - -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
--- a/main/signal/inst/dctmtx.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## T = dctmtx (n) -## Return the DCT transformation matrix of size n x n. -## -## If A is an n x 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 - -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
--- a/main/signal/inst/decimate.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: y = decimate(x, q [, n] [, ftype]) -## -## Downsample the signal x by a factor of q, using an order n filter -## of ftype 'fir' or 'iir'. By default, an order 8 Chebyshev type I -## filter is used or a 30 point FIR filter if ftype is 'fir'. 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); # 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 - -function y = decimate(x, q, n, ftype) - - if nargin < 1 || nargin > 4 - print_usage; - elseif q != fix(q) - error("decimate only works with integer q."); - endif - - if nargin<3 - ftype='iir'; - n=[]; - elseif nargin==3 - if ischar(n) - ftype=n; - n=[]; - else - ftype='iir'; - endif - endif - - fir = strcmp(ftype, 'fir'); - if isempty(n) - if fir, n=30; else n=8; endif - endif - - if fir - b = fir1(n, 1/q); - y=fftfilt(b, 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.
--- a/main/signal/inst/dftmtx.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{d} = } dftmtx (@var{n}) -## -## If @var{n} is a scalar, produces a @var{n}-by-@var{n} matrix @var{d} -## such that the Fourier transform of a column vector of length @var{n} -## is given by @code{dftmtx(@var{n}) * x} and the inverse Fourier transform -## is given by @code{inv(dftmtx(@var{n})) * x}. In general this is less -## efficient than calling the @dfn{fft} and @dfn{ifft} directly. -## @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
--- a/main/signal/inst/diric.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -## 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; if not, see <http://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
--- a/main/signal/inst/downsample.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -## 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 nth 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 nth 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; end - - if phase > n - 1 - warning("This is incompatible with Matlab (phase = 0:n-1). See ... - octave-forge signal package release notes for details.") - end - - if isvector(x) - y = x(phase + 1:n:end); - else - y = x(phase + 1:n:end,:); - end -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]);
--- a/main/signal/inst/dst.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -## 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)); end - # 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)
--- a/main/signal/inst/dwt.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{ca} @var{cd}] =} dwt(@var{x,lo_d,hi_d}) -## Comupte de discrete wavelet transform of x with one level. -## @end deftypefn - -function [ca cd] = dwt(x,lo_d,hi_d) - if (nargin < 3|| nargin > 3) - print_usage; - elseif(~isvector(x) || ~isvector(lo_d) || ~isvector(hi_d)) - error('x, hi_d and lo_d must be vectors'); - end - - h = filter(hi_d,1,x); - g = filter(lo_d,1,x); - - cd = downsample(h,2); - ca = downsample(g,2); -endfunction
--- a/main/signal/inst/ellip.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## N-ellip 0.2.1 -##usage: [Zz, Zp, Zg] = ellip(n, Rp, Rs, Wp, stype,'s') -## -## Generate an Elliptic or Cauer filter (discrete and contnuious). -## -## [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. -## - Kienzle, Paul, functions from Octave-Forge, 1999 (http://octave.sf.net). - - -function [a,b,c,d] = ellip(n, Rp, Rs, W, varargin) - - if (nargin>6 || nargin<4) || (nargout>4 || nargout<2) - print_usage; - endif - - ## interpret the input parameters - if (!(length(n)==1 && n == round(n) && n > 0)) - error ("ellip: filter order n must be a positive integer"); - endif - - - stop = 0; - digital = 1; - for i=1:length(varargin) - switch varargin{i} - case 's', digital = 0; - case 'z', digital = 1; - case { 'high', 'stop' }, stop = 1; - case { 'low', 'pass' }, stop = 0; - otherwise, error ("ellip: expected [high|stop] or [s|z]"); - endswitch - endfor - - [r, c]=size(W); - if (!(length(W)<=2 && (r==1 || c==1))) - error ("ellip: frequency must be given as w0 or [w0, w1]"); - elseif (!(length(W)==1 || length(W) == 2)) - error ("ellip: only one filter band allowed"); - elseif (length(W)==2 && !(W(1) < W(2))) - error ("ellip: first band edge must be smaller than second"); - endif - - if ( digital && !all(W >= 0 & W <= 1)) - error ("ellip: critical frequencies must be in (0 1)"); - elseif ( !digital && !all(W >= 0 )) - error ("ellip: critical frequencies must be in (0 inf)"); - endif - - if (Rp < 0) - error("ellip: passband ripple must be positive decibels"); - endif - - if (Rs < 0) - error("ellip: stopband ripple must be positive decibels"); - end - - - ##Prewarp the digital frequencies - if digital - T = 2; # sampling frequency of 2 Hz - W = 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 - 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 -%! clc -%! disp('---------------------------> NELLIP 0.2 EXAMPLE <-------------------------') -%! x=input("Let's calculate the filter order: [ENTER]"); -%! disp("") -%! x=input("[n, Ws] = ellipord([.1 .2],.4,1,90); [ENTER]"); -%! [n, Ws] = ellipord([.1 .2],.4,1,90) -%! disp("") -%! x=input("Let's calculate the filter: [ENTER]"); -%! disp("") -%! x=input("[b,a]=ellip(5,1,90,[.1,.2]); [ENTER]"); -%! [b,a]=ellip(5,1,90,[.1,.2]) -%! disp("") -%! x=input("Let's calculate the frequency response: [ENTER]"); -%! disp("") -%! x=input("[h,w]=freqz(b,a); [ENTER]"); -%! [h,w]=freqz(b,a); -%! -%! xlabel("Frequency"); -%! ylabel("abs(H[w])[dB]"); -%! axis([0,1,-100,0]); -%! plot(w./pi, 20*log10(abs(h)), ';;') -%! -%! hold('on'); -%! x=ones(1,length(h)); -%! plot(w./pi, x.*-1, ';-1 dB;') -%! plot(w./pi, x.*-90, ';-90 dB;') -%! hold('off'); -%! -%! xlabel("") -%! ylabel("") -%! clc
--- a/main/signal/inst/ellipap.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -## 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; if not, see <http://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 only for matlab compatibility 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
--- a/main/signal/inst/ellipord.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: [n,wp] = ellipord(wp,ws, rp,rs) -## -## Calculate the order for the elliptic filter (discrete) -## wp: Cutoff frequency -## ws: Stopband edge -## rp: decibels of ripple in the passband. -## rs: decibels of ripple in the stopband. -## -## References: -## -## - Lamar, Marcus Vinicius, Notas de aula da disciplina TE 456 - Circuitos -## Analogicos II, UFPR, 2001/2002. - -function [n, Wp] = ellipord(Wp, Ws, Rp, Rs) - - [rp, cp]=size(Wp); - [rs, cs]=size(Ws); - if ( !(length(Wp)<=2 && (rp==1 || cp==1) && length(Ws)<=2 && (rs==1 || cs==1)) ) - error ("ellipord: frequency must be given as w0 or [w0, w1]"); - elseif (!all(Wp >= 0 & Wp <= 1 & Ws >= 0 & Ws <= 1)) ##### - error ("ellipord: critical frequencies must be in (0 1)"); - elseif (!(length(Wp)==1 || length(Wp) == 2 & length(Ws)==1 || length(Ws) == 2)) - error ("ellipord: only one filter band allowed"); - elseif (length(Wp)==2 && !(Wp(1) < Wp(2))) - error ("ellipord: first band edge must be smaller than second"); - elseif (length(Ws)==2 && !(length(Wp)==2)) - error ("ellipord: you must specify band pass borders."); - elseif (length(Wp)==2 && length(Ws)==2 && !(Ws(1) < Wp(1) && Ws(2) > Wp(2)) ) - error ("ellipord: ( Wp(1), Wp(2) ) must be inside of interval ( Ws(1), Ws(2) )"); - elseif (length(Wp)==2 && length(Ws)==1 && !(Ws < Wp(1) || Ws > Wp(2)) ) - error ("ellipord: Ws must be out of interval ( Wp(1), Wp(2) )"); - endif - - # sampling frequency of 2 Hz - T = 2; - - Wpw = tan(pi.*Wp./T); # prewarp - Wsw = tan(pi.*Ws./T); # prewarp - - ##pass/stop band to low pass filter transform: - if (length(Wpw)==2 && length(Wsw)==2) - wp=1; - w02 = Wpw(1) * Wpw(2); # Central frequency of stop/pass band (square) - w3 = w02/Wsw(2); - w4 = w02/Wsw(1); - if (w3 > Wsw(1)) - ws = (Wsw(2)-w3)/(Wpw(2)-Wpw(1)); - elseif (w4 < Wsw(2)) - ws = (w4-Wsw(1))/(Wpw(2)-Wpw(1)); - else - ws = (Wsw(2)-Wsw(1))/(Wpw(2)-Wpw(1)); - endif - elseif (length(Wpw)==2 && length(Wsw)==1) - wp=1; - w02 = Wpw(1) * Wpw(2); - if (Wsw > Wpw(2)) - w3 = w02/Wsw; - ws = (Wsw - w3)/(Wpw(2) - Wpw(1)); - else - w4 = w02/Wsw; - ws = (w4 - Wsw)/(Wpw(2) - Wpw(1)); - endif - 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)); -endfunction
--- a/main/signal/inst/fht.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn{Function File} {m = } fht ( d, n, dim ) -## @cindex linear algebra -## The function fht calculates Fast Hartley Transform -## where @var{d} is the real input vector (matrix), and @var{m} -## is the real-transform vector. For matrices 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(); - end - - if ( nargin == 3 ) - Y = fft(d,n,dim); - elseif ( nargin == 2 ) - Y = fft(d,n); - else - Y = fft(d); - end - - 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; -# end - -end -%! -%!assert( fht([1 2 3 4]),[10 -4 -2 0] ) -%!
--- a/main/signal/inst/filtfilt.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: 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); % 10 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;') - - -## TODO: (pkienzle) 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; - end - 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; end - if lb < n, b(n) = 0; end - - ## 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 - end - 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); - -%!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);
--- a/main/signal/inst/filtic.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## 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 - -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 - -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); -
--- a/main/signal/inst/findpeaks.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,275 +0,0 @@ -## 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; if not, see <http://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 intercal here 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 crosses the @asis{"baseline"} value. The -## width of the peak is calculated by @command{diff(roots)}. -## @end table -## -## This function accepts property-value pair given in the list below: -## -## @table @asis -## @item "MinPeakHeight" -## Minimum peak height (positive scalar). Only peaks that exceed this -## value will be returned. For data taking positive and negative values -## use the option "DoubleSided". Default value @code{2*std (abs (detrend -## (data,0)))}. -## -## @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. -## Default value 4. -## -## @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 neighborhood size is equal to the value of -## @asis{"MinPeakDistance"}. The width is evaluated at the half height -## of the peak with baseline at "MinPeakHeight". Default value 2. -## -## @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) - - # --- Parse arguments --- # - __data__ = abs (detrend (data,0)); - - posscal = @(x)isscalar (x) && x >= 0; - - parser = inputParser (); - parser.FunctionName = "findpeaks"; - parser = addParamValue (parser,"MinPeakHeight", 2*std (__data__),posscal); - parser = addParamValue (parser,"MinPeakDistance",4,posscal); - parser = addParamValue (parser,"MinPeakWidth",2,posscal); - parser = addSwitch (parser,"DoubleSided"); - - parser = parse(parser,varargin{:}); - - minH = parser.Results.MinPeakHeight; - minD = parser.Results.MinPeakDistance; - minW = parser.Results.MinPeakWidth; - dSided = parser.Results.DoubleSided; - - clear parser posscal - # ------ # - - if dSided - [data __data__] = deal (__data__, data); - elseif min(data)<0 - error ("findpeaks:InvalidArgument", - 'Data contains negative values. You may want to "DoubleSided" option'); - end - - % Rough stimates 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. - idx = find (df1.*circshift(df1,1)<0 & df2<0)-1; - - % 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 (idx_s - idx_s'); - 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 - end - - endwhile - idx = idx_pruned; - end - - % 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% - if minW > 0 - %% 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 = length(idx); - np = length(data); - struct_count = 0; - for i=1:n - ind = (round (max(idx(i)-minD/2,1)) : ... - round (min(idx(i)+minD/2,np)))'; - pp = polyfit (ind,data(ind),2); - H = pp(3) - pp(2)^2/(4*pp(1)); - - %% 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"); - - rz = roots ([pp(1:2) pp(3)-mean([H,minH])]); - width = abs (diff (rz)); - if width < minW || pp(1) > 0 || H < minH || data(idx(i)) < 0.99*H - idx_pruned = setdiff (idx_pruned, idx(i)); - elseif nargout >= 1 - struct_count++; - extra.parabol(struct_count).x = ind([1 end]); - extra.parabol(struct_count).pp = pp; - - extra.roots(struct_count,1:2) = rz; - extra.height(struct_count) = H; - extra.baseline(struct_count) = mean([H,minH]); - end - - %% debug -# set(h(2),"xdata",idx_pruned,"ydata",data(idx_pruned)) -# pause(0.2) - - end - end - idx = idx_pruned; - - if dSided - pks = __data__(idx); - else - pks = data(idx); - end - - if nargout >=1 - varargout{1} = extra; - end -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),'.m') -%! subplot(1,2,2) -%! plot(t,data2,t(idx2),data2(idx2),".m;>2*std;",t(idx3),data2(idx3),"or;>0.1;") -%! 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),'.r') -%! subplot(1,2,2) -%! plot(t,data,t(idx2),data(idx2),'.r') -%! -%! #---------------------------------------------------------------------------- -%! # Noisy data may need tunning of the parameters. In the 2nd example, -%! # MinPeakDistance is used as a smoother of the peaks.
--- a/main/signal/inst/fir1.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: b = fir1(n, w [, type] [, window] [, noscale]) -## -## Produce an order n FIR filter with the given frequency cutoff, -## returning the n+1 filter coefficients in b. -## -## n: order of the filter (1 less than the length of the filter) -## w: band edges -## strictly increasing vector in range [0, 1] -## singleton for highpass or lowpass, vector pair for bandpass or -## bandstop, or vector for alternating pass/stop filter. -## type: choose between pass and stop bands -## 'high' for highpass filter, cutoff at w -## 'stop' for bandstop filter, edges at w = [lo, hi] -## 'DC-0' for bandstop as first band of multiband filter -## 'DC-1' for bandpass as first band of multiband filter -## window: smoothing window -## defaults to hamming(n+1) row vector -## returned filter is the same shape as the smoothing window -## noscale: choose whether to normalize or not -## 'scale': set the magnitude of the center of the first passband to 1 -## 'noscale': don't normalize -## -## To apply the filter, use the return vector b: -## 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')); - -## TODO: Consider using exact expression (in terms of sinc) for the -## TODO: impulse response rather than relying on fir2. -## TODO: Find reference to the requirement that order be even for -## TODO: filters that end high. Figure out what to do with the -## TODO: 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);end - if isempty(arg) continue; end # 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; - end - 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, 512, 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'));
--- a/main/signal/inst/fir2.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,197 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: b = fir2(n, f, m [, grid_n [, ramp_n]] [, window]) -## -## Produce an FIR filter of order n with arbitrary frequency response, -## returning the n+1 filter coefficients in b. -## -## n: order of the filter (1 less than the length of the filter) -## f: frequency at band edges -## f is a vector of nondecreasing elements in [0,1] -## the first element must be 0 and the last element must be 1 -## if elements are identical, it indicates a jump in freq. response -## m: magnitude at band edges -## m is a vector of length(f) -## grid_n: length of ideal frequency response function -## defaults to 512, should be a power of 2 bigger than n/2 -## ramp_n: transition width for jumps in filter response -## defaults to grid_n/25; a wider ramp gives wider transitions -## but has better stopband characteristics. -## window: smoothing window -## defaults to hamming(n+1) row vector -## returned filter is the same shape as the smoothing window -## -## To apply the filter, use the return vector b: -## y=filter(b,1,x); -## Note that plot(f,m) shows target response. -## -## 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;'); - -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 - - ## 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 -%!test -%! 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)) - -%!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]; -%! -%! title('Theoretical/Synthesized CLASS spectrum'); -%! xlabel('Normalized frequency (Fs=2)'); -%! ylabel('Magnitude'); -%! -%! 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; -%! xlabel(''); ylabel(''); title('');
--- a/main/signal/inst/firls.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## b = firls(N, F, A); -## 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. -## -## 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. -## -## A specifies the amplitude of the desired response at each band edge. -## -## W is an optional 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 - -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
--- a/main/signal/inst/flattopwin.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -## Author: Paul Kienzle <pkienzle@users.sf.net> (2004) -## This program is granted to the public domain. - -## flattopwin(L, [periodic|symmetric]) -## -## Return the window 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/(L-1) for i=0:L-1 for a symmetric window, or -## w = i/L for i=0:L-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. - -function w = flattopwin (L, sym) - if nargin == 0 || nargin > 2 - print_usage; - endif - - divisor = L-1; - if nargin > 1 - match = strmatch(sym,['periodic';'symmetric']); - if isempty(match), - error("window type must be periodic or symmetric"); - elseif match == 1 - divisor = L; - else - divisor = L-1; - endif - endif - - if (L == 1) - w = 1; - else - x = 2*pi*[0:L-1]'/divisor; - 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
--- a/main/signal/inst/fracshift.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- 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. -## @end deftypefn -## @seealso{circshift} - -## 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 nargchk(2,3,nargin) - print_usage; - endif; - - ## if the delay is an exact integer, use circshift - if d==fix(d) - y=circshift(x,d); - return - endif; - - ## filter design if required - - if (nargin < 4) - - ## properties of the interpolation filter - - log10_rejection = -3.0; - stopband_cutoff_f = 1.0 / 2.0; - roll_off_width = stopband_cutoff_f / 10; - - ## determine filter length - ## use empirical formula from [1] 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*stopband_cutoff_f*sinc(2*stopband_cutoff_f*(t-(d-fix(d)))); - - ## determine parameter of Kaiser window - ## use empirical formula from [1] 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 (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; - - 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("fracshift.m: the filter h should be a vector"); - 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); - y = xfilt(offset+1:offset+Ly,:); - - y=circshift(y,fix(d)); - - if isrowvector, - y=y.'; - endif - -endfunction - -%!test -%! N=1024; -%! d=1.5; -%! t=(0:N-1)-N/2; -%! tt=t-d; -%! err=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); -%! [y,h]=fracshift(x,d); -%! xx=exp(-tt'.^2/(2*sigma)).*sin(2*pi*f0*tt' + phi0); -%! err(n+1)=max(abs(y-xx)); -%! endfor; -%! rolloff=.1; -%! rejection=10^-3; -%! idx_inband=1:ceil((1-rolloff)*N/2)-1; -%! assert(max(err(idx_inband))<rejection); - -%!test -%! N=1024; -%! d=7/6; -%! t=(0:N-1)-N/2; -%! tt=t-d; -%! err=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); -%! [y,h]=fracshift(x,d); -%! xx=exp(-tt'.^2/(2*sigma)).*sin(2*pi*f0*tt' + phi0); -%! err(n+1)=max(abs(y-xx)); -%! endfor; -%! rolloff=.1; -%! rejection=10^-3; -%! idx_inband=1:ceil((1-rolloff)*N/2)-1; -%! assert(max(err(idx_inband))<rejection); - -%!test -%! N=1024; -%! p=6; -%! q=7; -%! d1=64; -%! d2=d1*p/q; -%! t=128; -%! n=zeros(N,1); -%! n(N/2+(-t:t))=randn(2*t+1,1); -%! [b a]=butter(10,.25); -%! 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);
--- a/main/signal/inst/freqs.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Usage: H = 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); - -function [H] = freqs(B,A,W) - - if (nargin ~= 3 || nargout>1) - print_usage; - end - - H = polyval(B,j*W)./polyval(A,j*W); - - if nargout<1 - freqs_plot(W,H); - end - -endfunction - -%!demo -%! B = [1 2]; -%! A = [1 1]; -%! w = linspace(0,4,128); -%! freqs(B,A,w);
--- a/main/signal/inst/freqs_plot.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -## 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; if not, see <http://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
--- a/main/signal/inst/fwhm.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -%% Author: Petr Mikulik (2009) -%% This program is granted to the public domain. - -%% 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. -%% Syntax: -%% f = fwhm({x, } y {, 'zero'|'min' {, 'rlevel', rlevel}}) -%% f = fwhm({x, } y {, 'alevel', alevel}) -%% Examples: -%% f = fwhm(y) -%% f = fwhm(x, y) -%% f = fwhm(x, y, 'zero') -%% f = fwhm(x, y, 'min') -%% f = fwhm(x, y, 'alevel', 15.3) -%% f = fwhm(x, y, 'zero', 'rlevel', 0.5) -%% f = fwhm(x, y, 'min', 'rlevel', 0.1) -%% -%% 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). -%% -%% Compatibility: Octave 3.x, Matlab - -function myfwhm = fwhm (y, varargin) - - if nargin < 1 || nargin > 5 - print_usage; - end - 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; - end - 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'); - end - level = varargin{k}; - if ~isreal(level) || length(level) > 1 - error('argument of "alevel" must be real number'); - end - k = k+1; - break - end - if any(strcmp(varargin{k}, {'zero', 'min'})) - opt = varargin{k}; - k = k+1; - end - if k > length(varargin) break; end - if strcmp(varargin{k}, 'rlevel') - k = k+1; - if k > length(varargin) - error('option "rlevel" requires an argument'); - end - 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)'); - end - k = k+1; - break - end - break - end - if k ~= length(varargin)+1 - error('fwhm: extraneous option(s)'); - end - end - - % test the y matrix - [nr, nc] = size(y); - if (nr == 1 && nc > 1) - y = y'; nr = nc; nc = 1; - end - - if length(x) ~= nr - error('dimension of input arguments do not match'); - end - - % 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); - end - end - - % 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); - end - [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; - end - end -end - -%!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);
--- a/main/signal/inst/fwht.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -## Copyright (C) 2013 Mike Miller <mtmiller@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; if not, see <http://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 - -## Author: Mike Miller - -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 input validation -%!error fwht (); -%!error fwht (1, 2, 3, 4); -%!error fwht (0, 0); -%!error fwht (0, 5); -%!error fwht (0, [], "invalid");
--- a/main/signal/inst/gauspuls.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{y}] =} gauspuls(@var{t},@var{fc},@var{bw}) -## Return the Gaussian modulated sinusoidal pulse. -## @end deftypefn - -function [y] = gauspuls(t, fc = 1e3, bw = 0.5) - if nargin<1, print_usage; end - if fc < 0 , error("fc must be positive"); end - if bw <= 0, error("bw must be stricltly positive"); end - - 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
--- a/main/signal/inst/gaussian.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: w = gaussian(n, a) -## -## Generate an n-point gaussian convolution window of the given -## width. Use larger a for a narrower window. Use larger n for -## longer tails. -## -## w = exp ( -(a*x)^2/2 ) -## -## for x = linspace ( -(n-1)/2, (n-1)/2, n ). -## -## 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). - -function x = gaussian(n, w) - - if nargin < 1 || nargin > 2 - print_usage; - end - if nargin == 1, w = 1; endif - x = exp(-0.5*(([0:n-1]'-(n-1)/2)*w).^2); - -endfunction
--- a/main/signal/inst/gausswin.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: w = gausswin(L, a) -## -## Generate an L-point gaussian window of the given width. Use larger a -## for a narrow window. Use larger L for a smoother curve. -## -## w = exp ( -(a*x)^2/2 ) -## -## for x = linspace(-(L-1)/L, (L-1)/L, L) - -function x = gausswin(L, w) - - if nargin < 1 || nargin > 2 - print_usage; - end - if nargin == 1, w = 2.5; endif - x = exp ( -0.5 * ( w/L * [ -(L-1) : 2 : L-1 ]' ) .^ 2 ); - -endfunction
--- a/main/signal/inst/gmonopuls.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -## 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; if not, see <http://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; end - if fc < 0 , error("fc must be positive"); end - y = 2*sqrt(exp(1)) .* pi.*t.*fc.*exp(-2 .* (pi.*t.*fc).^2); -endfunction
--- a/main/signal/inst/grpdelay.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,321 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## 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 - -function [gd,w] = grpdelay(b,a=1,nfft=512,whole,Fs) - - if (nargin<1 || nargin>5) - print_usage; - end - HzFlag=0; - if length(nfft)>1 - if nargin>4 - print_usage(); - elseif nargin>3 % grpdelay(B,A,F,Fs) - Fs = whole; - HzFlag=1; - else % grpdelay(B,A,W) - Fs = 1; - end - 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=1; - whole = ''; - end - if nargin<3, nfft=512; end - if nargin<2, a=1; end - else - HzFlag=1; - end - - if isempty(nfft), nfft = 512; end - if ~strcmp(whole,'whole'), nfft = 2*nfft; end - w = Fs*[0:nfft-1]/nfft; - end - - if ~HzFlag, w = w * 2*pi; end - - oa = length(a)-1; % order of a(z) - if oa<0, a=1; oa=0; end % a can be [] - ob = length(b)-1; % order of b(z) - if ob<0, b=1; ob=0; end % b can be [] as well - 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('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))); - end - gd = real(num ./ den) - oa; - - if strcmp(whole,'whole')==0 - 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 - end - - % 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'; - end - xlabel(['Frequency (', funits, ')']); - ylabel('Group delay (samples)'); - plot(w(1:ns), gd(1:ns), ';;'); - unwind_protect_cleanup - grid('on'); - end_unwind_protect - end -end - -% ------------------------ 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. -%! %-------------------------------------------------------------- -%! title ('Zero at z = -0.9'); -%! 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; -%! -%!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)]); -%! title ('Two Zeros and Two Poles'); -%! 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; - -%!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); -%! title(sprintf('b = fir1(%d,2*%d/%d);',nb,Fc,Fs)); -%! xlabel('Normalized Frequency (cycles/sample)'); -%! ylabel('Amplitude Response (dB)'); -%! grid('on'); -%! plot(f,20*log10(abs(H))); -%! subplot(212); -%! del = nb/2; % should equal this -%! title(sprintf('Group Delay in Pass-Band (Expect %d samples)',del)); -%! ylabel('Group Delay (samples)'); -%! axis([0, 0.2, del-1, del+1]); -%! plot(f,gd); -%! axis(); - -%!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); -%! title('[b,a] = cheby1(3, 3, 2*[1000, 3000]/Fs, \'stop\');'); -%! xlabel('Frequency (Hz)'); -%! ylabel('Amplitude Response'); -%! grid('on'); -%! plot(f,abs(H)); -%! subplot(212); -%! title('[gd,f] = grpdelay(b,a,[],Fs);'); -%! ylabel('Group Delay (samples)'); -%! plot(f,gd); - - -% ------------------------ 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 -%! 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);
--- a/main/signal/inst/hann.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -% w = hann(n) -% see hanning -function w = hann(n), w=hanning(n);
--- a/main/signal/inst/hilbert.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,149 +0,0 @@ -## 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; if not, see <http://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 dim. -## @end deftypefn - -function f=hilbert(f, N = [], dim = []) - - % ------ PRE: initialization and dimension shifting --------- - - if (nargin<1 || nargin>3) - print_usage; - end - - if ~isreal(f) - warning ('HILBERT: ignoring imaginary part of signal'); - f = real (f); - end - - 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); - end - - else - if (numel(dim)~=1 || ~isnumeric(dim)) - error('HILBERT: dim must be a scalar.'); - end - if rem(dim,1)~=0 - error('HILBERT: dim must be an integer.'); - end - if (dim<1) || (dim>D) - error('HILBERT: dim must be in the range from 1 to %d.',D); - end - - end - - 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.'); - end - - if dim>1 - order=[dim, 1:dim-1,dim+1:D]; - - % Put the desired dimension first. - f=permute(f,order); - - end - - Ls=size(f,1); - - % If N is empty it is set to be the length of the transform. - if isempty(N) - N=Ls; - end - - % 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); - end - - % ------- 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)]; - end - - f=ifft(f); - end - - % ------- POST: Restoration of dimensions ------------ - - % Restore the original, permuted shape. - f=reshape(f,permutedsize); - - if dim>1 - % Undo the permutation. - f=ipermute(f,order); - end - -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)|;');
--- a/main/signal/inst/idct.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## y = dct (x, n) -## Computes 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 of 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: idct, dct2, idct2, dctmtx - -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
--- a/main/signal/inst/idct2.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## y = idct2 (x) -## Computes the inverse 2-D discrete cosine transform of matrix x -## -## y = idct2 (x, m, n) or y = idct2 (x, [m n]) -## Computes the 2-D inverse DCT of x after padding or trimming rows to m and -## columns to n. - -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
--- a/main/signal/inst/idst.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -## 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); end - end - x = dst(y, n) * 2/(n+1); - -endfunction - -%!test -%! x = log(gausswin(32)); -%! assert(x, idst(dst(x)), 100*eps)
--- a/main/signal/inst/ifht.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn{Function File} {m = } ifht ( d, n, dim ) -## @cindex linear algebra -## The function ifht calculates Fast Hartley Transform -## where @var{d} is the real input vector (matrix), and @var{m} -## is the real-transform vector. For matrices 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] = 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(); - end - - if ( nargin == 3 ) - Y = ifft(d,n,dim); - elseif ( nargin == 2 ) - Y = ifft(d,n); - else - Y = ifft(d); - end - - 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; -# end - -end - -%!assert(ifht(fht(1:4)),[1 2 3 4])
--- a/main/signal/inst/ifwht.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -## Copyright (C) 2013 Mike Miller <mtmiller@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; if not, see <http://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 - -## Author: Mike Miller - -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");
--- a/main/signal/inst/iirlp2mb.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,318 +0,0 @@ -## 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; if not, see <http://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 tranformation 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
--- a/main/signal/inst/impinvar.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -## 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; if not, see <http://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 specificied, 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 40 (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; % Contstant 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); -%!assert(stozerr([1 1],[1 2 1],100),0,0.0001); -%!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);
--- a/main/signal/inst/impz.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: [x, t] = impz(b [, a, n, fs]) -## -## 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 - -## TODO: Call equivalent function from control toolbox since it is -## TODO: probably more sophisticated than this one, and since it -## TODO: is silly to maintain two different versions of essentially -## TODO: the same thing. -function [x_r, t_r] = impz(b, a = [1], n = [], fs = 1) - - if nargin == 0 || nargin > 4 - print_usage; - end - - 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; - end - end - - # 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; - end - end - end - n = n + length(b); - elseif isempty(n) - n = length(b); - end - - if length(a) == 1 - x = fftfilt(b/a, [1, zeros(1,n-1)]); - else - x = filter(b, a, [1, zeros(1,n-1)]); - end - t = [0:n-1]/fs; - - if nargout >= 1 x_r = x; end; - if nargout >= 2 t_r = t; end; - if nargout == 0 - unwind_protect - title "Impulse Response"; - if (fs > 1000) - t = t * 1000; - xlabel("Time (msec)"); - else - xlabel("Time (sec)"); - end - plot(t, x, "^r;;"); - unwind_protect_cleanup - title ("") - xlabel ("") - end_unwind_protect - end - -endfunction
--- a/main/signal/inst/interp.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: 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 - -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.
--- a/main/signal/inst/invfreq.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,234 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% usage: [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 - -%% TODO: implement Steiglitz-McBride iterations -%% TODO: improve numerical stability for high order filters (matlab is a bit better) -%% TODO: 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; end - n = max(nA, nB); - m = n+1; mA = nA+1; mB = nB+1; - nF = length(F); - if nF ~= length(H), disp('invfreqz: length of H and F must be the same'); end; - if nargin < 5 || isempty(W), W = ones(1, nF); end; - if nargin < 6, iter = []; end - if nargin < 7 tol = []; end - if nargin < 8 || isempty(tr), tr = ''; end - if nargin < 9, plane = 'z'; end - if nargin < 10, varargin = {}; end - if iter~=[], disp('no implementation for iter yet'),end - if tol ~=[], disp('no implementation for tol yet'),end - if (plane ~= 'z' && plane ~= 's'), disp('invfreqz: Error in plane argument'), end - - [reg, prop ] = parseparams(varargin); - %# should we normalise 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 - end - 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'); - end - otherwise %# FIXME: just skip it for now - disp(sprintf("Ignoring unkown argument %s", varargin{indi})); - indi = indi + 1; - end - end - end - - 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(' ') - end - - 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; - end - s = exp(-s); - case 's' - if max(F) > 1e6 && n > 5, - if ~norm, - disp('Be carefull, 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; - end - end - end - - 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)); - end; - 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; - end - for k = 1+min(nA, nB):max(nA, nB)-1, - if k <= nB, Rr(:, 1+k) = Zk; end - if k <= nA, Rr(:, mB+k) = -Zk.*H; end - Zk = Zk.*s; - end - k = k+1; - if k <= nB, Rr(:, 1+k) = Zk; end - if k <= nA, Rr(:, mB+k) = -Zk.*H; end - - %# 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); - end - - 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 normalised -- unscale coefficients - Zk = Fmax.^[n:-1:0].'; - for k = nB:-1:1+zB, B(k) = B(k)/Zk(k); end - for k = nA:-1:1, A(k) = A(k)/Zk(k); end - end - end -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); -%! xlabel("Frequency (rad/sample)"); -%! ylabel("Magnitude"); -%! plot(w,[abs(H), abs(Hh)]) -%! legend('Original','Measured'); -%! err = norm(H-Hh); -%! disp(sprintf('L2 norm of frequency response error = %f',err));
--- a/main/signal/inst/invfreqs.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% Usage: [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)); - -% TODO: 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)); - end - end - end - end - end - - % 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); -%! xlabel("Frequency (rad/sec)"); -%! ylabel("Magnitude"); -%! plot(w,[abs(H0); abs(Hh)]) -%! legend('Original','Measured'); -%! err = norm(H0-Hh); -%! disp(sprintf('L2 norm of frequency response error = %f',err));
--- a/main/signal/inst/invfreqz.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% usage: [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 frequncy (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))); - -%% TODO: 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)); - end - end - end - end -end - - -% 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); -%! xlabel("Frequency (rad/sample)"); -%! ylabel("Magnitude"); -%! plot(w,[abs(H0) abs(Hh)]) -%! legend('Original','Measured'); -%! err = norm(H0-Hh); -%! disp(sprintf('L2 norm of frequency response error = %f',err));
--- a/main/signal/inst/invimpinvar.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,149 +0,0 @@ -## 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; if not, see <http://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 specificied, 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);
--- a/main/signal/inst/kaiser.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: kaiser (L, beta) -## -## Returns the filter coefficients of the L-point Kaiser window with -## 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 L centered about x=0 is: -## -## besseli(0, beta * sqrt(1-(2*x/L).^2)) -## k(x) = -------------------------------------, L/2 <= x <= L/2 -## besseli(0, beta) -## -## See also: kaiserord - -function w = kaiser (L, beta = 0.5) - - if (nargin < 1) - print_usage; - elseif !(isscalar (L) && (L == round (L)) && (L > 0)) - error ("kaiser: L has to be a positive integer"); - elseif !(isscalar (beta) && (beta == real (beta))) - error ("kaiser: beta has to be a real scalar"); - endif - - if (L == 1) - w = 1; - else - m = L - 1; - k = (0 : m)'; - k = 2 * beta / m * sqrt (k .* (m - k)); - w = besseli (0, k) / besseli (0, beta); - endif - -endfunction - -%!demo -%! % use demo("kaiserord");
--- a/main/signal/inst/kaiserord.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: [n, Wn, beta, ftype] = kaiserord(f, m, dev [, fs]) -## -## Returns the parameters needed for fir1 to produce a filter of the -## desired specification from a kaiser window: -## n: order of the filter (length of filter minus 1) -## Wn: band edges for use in fir1 -## beta: parameter for kaiser window of length n+1 -## ftype: choose between pass and stop bands -## b = fir1(n,Wn,kaiser(n+1,beta),ftype,'noscale'); -## -## f: frequency bands, given as pairs, with the first half of the -## first pair assumed to start at 0 and the last half of the last -## pair assumed to end at 1. It is important to separate the -## band edges, since narrow transition regions require large order -## filters. -## m: magnitude within each band. Should be non-zero for pass band -## and zero for stop band. All passbands must have the same -## magnitude, or you will get the error that pass and stop bands -## must be strictly alternating. -## dev: deviation within each band. Since all bands in the resulting -## filter have the same deviation, only the minimum deviation is -## used. In this version, a single scalar will work just as well. -## fs: sampling rate. Used to convert the frequency specification into -## the [0, 1], where 1 corresponds to the Nyquist frequency, fs/2. -## -## 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); -## freqz(fir1(n,w,kaiser(n+1,beta),ftype,'noscale'),1,[],11025); - -## TODO: order is underestimated for the final test case: 2 stop bands. -## TODO: octave> ftest("kaiserord") # shows test cases - -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. - -%!# XXX FIXME XXX extend demo to show detail at criteria box corners
--- a/main/signal/inst/levinson.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: [a, v, ref] = 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 - -## Based on: -## yulewalker.m -## Copyright (C) 1995 Friedrich Leisch <Friedrich.Leisch@ci.tuwien.ac.at> -## GPL license - -## TODO: Matlab doesn't return reflection coefficients and -## TODO: errors in addition to the polynomial a. -## TODO: What is the difference between aryule, levinson, -## TODO: 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
--- a/main/signal/inst/marcumq.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,385 +0,0 @@ -## 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; if not, see <http://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(); - end - if ( any(a<0) || any(b<0) ) - error("Parameters to marcumq must be positive"); - end - if ( any(M<0) || any(floor(M)~=M) ) - error("M must be a positive integer"); - end - - [a,b,M] = tablify(a,b,M); - - Q = arrayfun(@mq, a,b,M,tol); - -end - -% 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; - end - if (a==0) - k = 0:(M-1); - Q = exp(-b^2/2)*sum(b.^(2*k)./(2.^k .* factorial(k))); - N = 0; - return; - end - - % 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); - for k=1:M-1 - t = (d+1/d)*besseli(k,z,1); - S = S + t; - d = d*x; - end - N=k++; - else - s = -1; - c = 1; - x = b/a; - k = M; - d = x^M; - S = 0; - N = 0; - end - - 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; -end - -% Tests for number and validity of arguments. -% -%!error -%! fail(marcumq(1)) -%!error -%! fail(marcumq(-1,1,1,1,1)) -%!error -%! fail(marcumq(-1,1)) -%!error -%! fail(marcumq(1,-1)) -%!error -%! fail(marcumq(1,1,-1)) -%!error -%! fail(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 discrepency 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.000000]; -%! -%! 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.000000]; -%! -%! 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.000000]; -%! -%! 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);
--- a/main/signal/inst/mexihat.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{psi,x}] =} mexihat(@var{lb,ub,n}) -## Compute the Mexican hat wavelet. -## @end deftypefn - -function [psi,x] = mexihat(lb,ub,n) - if (nargin < 3); print_usage; end - - 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
--- a/main/signal/inst/meyeraux.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -## 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; if not, see <http://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; end - - y = 35.*x.^4-84.*x.^5+70.*x.^6-20.*x.^7; -endfunction
--- a/main/signal/inst/morlet.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{psi,x}] =} morlet(@var{lb,ub,n}) -## Compute the Morlet wavelet. -## @end deftypefn - -function [psi,x] = morlet(lb,ub,n) - if (nargin < 3); print_usage; end - - if (n <= 0) - error("n must be strictly positive"); - endif - x = linspace(lb,ub,n); - psi = cos(5.*x) .* exp(-x.^2/2) ; -endfunction
--- a/main/signal/inst/movingrms.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{rmsx},@var{w}] =} movingrms (@var{x},@var{w},@var{rc},@var{Fs}=1) -## Calculates moving RMS value of the signal in @var{x}. -## -## The signla is convoluted against a sigmoid window of width @var{w} and risetime -## @var{rc}. The units of these to parameters are relative ot the vlaue 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); - end - 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); -%! -%! close all -%! figure () -%! -%! 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); -%! -%! close all -%! figure () -%! -%! 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.
--- a/main/signal/inst/mscohere.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% Usage: -%% [Pxx,freq]=mscohere(x,y,window,overlap,Nfft,Fs,range) -%% -%% Estimate (mean square) coherence of signals "x" and "y". -%% Use the Welch (1967) periodogram/FFT method. -%% See "help pwelch" for description of arguments, hints and references - - -function [varargout] = mscohere(varargin) - %% - %% Check fixed argument - if (nargin < 2 || nargin > 7) - print_usage (); - end - 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} = []; - end - end - 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; - end -end
--- a/main/signal/inst/ncauer.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: [Zz, Zp, Zg] = ncauer(Rp, Rs, n) -## -## Analog prototype for Cauer filter. -## [z, p, g]=ncauer(Rp, Rs, ws) -## Rp = Passband ripple -## Rs = Stopband ripple -## Ws = Desired order -## -## 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. - -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); - end - for m=1 : 30 - sig02=sig02+(-1)^m * q^(m^2) * cosh(2*m*l); - end - 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; - end - # - wi=zeros(1,r); - for ii=1 : r - if rem(n,2) - mu=ii; - else - mu=ii-1/2; - end - 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)); - end - soma2=0; - for m=1 : 30 - soma2 = soma2 + 2*((-1)^m * q^(m^2) * cos((2*m*pi*mu)/n)); - end - wi(ii)=(soma1/(1+soma2)); - end - # - 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); - end - - ##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]; - end - - ## - 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
--- a/main/signal/inst/nuttallwin.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{w}] =} nuttallwin(@var{L}) -## Compute the Blackman-Harris window defined by Nuttall of length L. -## @seealso{blackman, blackmanharris} -## @end deftypefn - -function [w] = nuttallwin(L) - if (nargin != 1); print_usage; end - - if(L < 0) - error('L must be positive'); - end - - if(L ~= floor(L)) - L = round(L); - warning('L rounded to the nearest integer.'); - end - - if (L == 1) - w = 1; - else - N = L-1; - a0 = 0.355768; - a1 = 0.487396; - a2 = 0.144232; - a3 = 0.012604; - n = -N/2:N/2; - w = a0 + a1.*cos(2.*pi.*n./N) + a2.*cos(4.*pi.*n./N) + a3.*cos(6.*pi.*n./N); - w = w'; - endif -endfunction
--- a/main/signal/inst/parzenwin.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{w}] =} parzenwin(@var{L}) -## Compute the Parzen window of lenght L. -## @seealso{rectwin, bartlett} -## @end deftypefn - -function w = parzenwin (L) - if(nargin != 1) - print_usage; - elseif(L < 0) - error('L must be positive'); - end - - if(L ~= floor(L)) - L = round(L); - end - - N = L-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)./(L/2)).^2 + 6*(abs(n1)./(L/2)).^3; - w2 = 2.*(1-abs(n2)./(L/2)).^3; - w3 = 2.*(1-abs(n3)./(L/2)).^3; - w = [w3 w1 w2]'; -endfunction
--- a/main/signal/inst/pburg.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% usage: -%% [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). Recognised 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". - -function [psd,f_out]=pburg(x,poles,varargin) - %% - if ( nargin<2 ) - error( 'pburg: need at least 2 args. Use "help pburg"' ); - end - 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={}; - end - end - end - %% - [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{:}); - end -end - -%!demo -%! fflush(stdout); -%! rand('seed',2038014164); -%! a = [ 1.0 -1.6216505 1.1102795 -0.4621741 0.2075552 -0.018756746 ]; -%! signal = detrend(filter(0.70181,a,rand(1,16384))); -%! % frequency shift by modulating with exp(j.omega.t) -%! skewed = signal.*exp(2*pi*i*2/25*[1:16384]); -%! Fs = 25; -%! hold on -%! pburg(signal,3,[],Fs); -%! input('Onesided 3-pole spectrum. Press ENTER', 's' ); -%! pburg(signal,4,[],Fs,'whole'); -%! input('Twosided 4-pole spectrum of same data. Press ENTER', 's' ); -%! pburg(signal,5,128,Fs,'shift', 'semilogy'); -%! input('Twosided, centred zero-frequency, 5-pole. Press ENTER', 's' ); -%! pburg(skewed,7,128,Fs,'AKICc','shift','semilogy'); -%! input('Complex data, AKICc chooses no. of poles. Press ENTER', 's' ); -%! user_freq=[-0.2:0.02:0.2]*Fs; -%! pburg(skewed,7,user_freq,Fs,'AKICc','semilogy'); -%! input('User-specified frequency values. Press ENTER', 's' ); -%! hold off -%! clf
--- a/main/signal/inst/pei_tseng_notch.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -## 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; if not, see <http://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 - -## TODO: 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 (:)'; - - - ##Normalise appropriately - frequencies *= pi; - bandwidths *= pi; - M2 = 2 * length ( frequencies ); - - - ##Splice centre and offset frequencies ( Equation 11 ) - omega = vec ( [ frequencies - bandwidths / 2; frequencies ] ); - - ##Splice centre 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;")
--- a/main/signal/inst/polystab.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## b = polystab(a) -## -## Stabalize 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
--- a/main/signal/inst/private/__fwht_opts__.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -## Copyright (C) 2013 Mike Miller <mtmiller@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; if not, see <http://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 - -## Author: Mike Miller - -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 (idx_bin) + 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
--- a/main/signal/inst/private/h1_z_deriv.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Adapted by Carnë Draug on 2011 <carandraug+dev@gmail.com> - -## This function is necessary for impinvar and invimpinvar of the signal package - -## 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
--- a/main/signal/inst/private/inv_residue.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Adapted by Carnë Draug on 2011 <carandraug+dev@gmail.com> - -## This function is necessary for impinvar and invimpinvar of the signal package - -## 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 contstant 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
--- a/main/signal/inst/private/polyrev.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Adapted by Carnë Draug on 2011 <carandraug+dev@gmail.com> - -## This function is necessary for impinvar and invimpinvar of the signal package - -## Reverse the coefficients of a polynomial -function p_out = polyrev (p_in) - p_out = p_in(end:-1:1); -endfunction
--- a/main/signal/inst/private/to_real.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Adapted by Carnë Draug on 2011 <carandraug+dev@gmail.com> - -## This function is necessary for impinvar and invimpinvar of the signal package - -## Round complex number to nearest real number -function p_out = to_real(p_in) - p_out = abs(p_in) .* sign(real(p_in)); -endfunction
--- a/main/signal/inst/pulstran.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: y=pulstran(t,d,'func',...) -## y=pulstran(t,d,p,Fs,'interp') -## -## 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); - -## TODO: Make it faster. It is currently unusable for anything real. -## TODO: It may not be possible to speed it up with the present interface. -## TODO: 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); title("rectpuls"); -%! auplot(pulstran(t', d', 'rectpuls', w), fs); -%! hold on; plot(d*1000,ones(size(d)),'g*;pulse;'); hold off; -%! -%! subplot(223); title("sinc => band limited interpolation"); -%! auplot(pulstran(f0*t, [f0*d', a], 'sinc'), fs); -%! hold on; plot(d*1000,a,'g*;pulse;'); hold off; -%! -%! subplot(222); title("interpolated boxcar"); -%! pulse = boxcar(30); # pulse width of 3 ms at 10 kHz -%! auplot(pulstran(t, d', pulse, 10000), fs); -%! hold on; plot(d*1000,ones(size(d)),'g*;pulse;'); hold off; -%! -%! subplot(224); title("interpolated asymmetric sin"); -%! pulse = sin(2*pi*[0:0.0001:w]/w).*[w:-0.0001:0]; -%! auplot(pulstran(t', [d', a], pulse', 10000), fs); -%! hold on; plot(d*1000,a*w,'g*;pulse;'); hold off; title(""); -%! -%! %---------------------------------------------------------- -%! % Should see (1) rectangular pulses centered on *, -%! % (2) rectangular pulses to the right of *, -%! % (3) smooth interpolation between the *'s, and -%! % (4) asymetric sines to the right of *
--- a/main/signal/inst/pwelch.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,955 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% USAGE: -%% [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 between 0 and 1; 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 behaviour -%% 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] Paul Kienzle (1999-2001): "pwelch", http://octave.sourceforge.net/ - -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; - end - 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' ); - end - %% 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(:); - end - %% - %% 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.' ); - end - %% force COLUMN vector - y = varargin{1}(:); - arg2_is_y = 1; - break; - end - end - %% - %% 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; - end - elseif ( strcmp(arg, 'cross' ) ) - if ( ~do_cross ) - n_results = n_results+1; - do_cross = n_results; - end - elseif ( strcmp(arg, 'trans' ) ) - if ( ~do_trans ) - n_results = n_results+1; - do_trans = n_results; - end - elseif ( strcmp(arg, 'coher' ) ) - if ( ~do_coher ) - n_results = n_results+1; - do_coher = n_results; - end - elseif ( strcmp(arg, 'ypower' ) ) - if ( ~do_ypower ) - n_results = n_results+1; - do_ypower = n_results; - end - else - error( 'pwelch: string arg %d illegal value: %s', iarg+1, arg ); - end - %% 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' ); - end - %% - %% 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; - end - %% - %% -- "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; - end - %% - %% 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(:); - end - else - is_win = 0; - end - 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) || any(arg<0) ) ) - error( 'pwelch: arg %d (window) vector must be real and >=0',iarg+1); - end - 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 ); - end - 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 ); - end - Nfft = arg; - %% - else - error( 'pwelch: arg %d must be string', iarg+1 ); - end - end - if ( conf>0 && (n_results && ~do_power ) ) - error('pwelch: can give confidence interval for x power spectrum only' ); - end - %% - %% 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; - end - 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 ); - end - 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; - end - %% make Hann window (don't depend on sigproc) - xx = seg_len - 1; - window = 0.5 - 0.5 * cos( (2*pi/xx)*[0:xx].' ); - end - %% - %% 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 ); - end - %% make Hamming window (don't depend on sigproc) - xx = seg_len - 1; - window = 0.54 - 0.46 * cos( (2*pi/xx)*[0:xx].' ); - end - if ( isempty(Nfft) ) - Nfft = max( 256, 2^ceil(log(seg_len)*nearly_one/log_two) ); - end - %% - %% 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; - end - %% make Hamming window (don't depend on sigproc) - xx = seg_len - 1; - window = 0.54 - 0.46 * cos( (2*pi/xx)*[0:xx].' ); - end - %% Now we know segment length, - %% so we can set default overlap as number of samples - if ( ~isempty(overlap) ) - overlap = fix(seg_len * overlap / 100 ); - end - if ( isempty(Nfft) ) - Nfft = max( 256, 2^ceil(log(seg_len)*nearly_one/log_two) ); - end - %% - %% 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; - end - seg_len = 2 ^ ceil( log(sqrt(x_len/(1-overlap)))*nearly_one/log_two ); - end - %% make Hamming window (don't depend on sigproc) - xx = seg_len - 1; - window = 0.54 - 0.46 * cos( (2*pi/xx)*[0:xx].' ); - end - %% Now we know segment length, - %% so we can set default overlap as number of samples - if ( ~isempty(overlap) ) - overlap = fix(seg_len * overlap); - end - %% - %% calculate FFT length - if ( isempty(Nfft) ) - Nfft = seg_len; - end - if ( is_sloppy ) - Nfft = 2 ^ ceil( log(Nfft) * nearly_one / log_two ); - end - end - %% end of compatibility options - %% - %% minimum FFT length is seg_len - Nfft = max( Nfft, seg_len ); - %% Mean square of window is required for normalising 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 ); - end - %% - %% 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)]; - end - x_len = seg_len; - end - %% 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; - end - if ( arg2_is_y || need_Pxy) - y = y - sum( y(1:x_len) ) / x_len; - end - end - %% - %% 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 = []; - end - 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); - end - fft_x = fft(xx); - end - 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); - end - fft_y = fft(yy); - end - 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; - end - end - if ( need_Pxy ) - %% Pxy (cross power spectrum) is complex. Do not force to be real. - Pxy = Pxy + fft_y .* conj(fft_x); - end - if ( need_Pyy ) - %% force Pyy to be real - Pyy = Pyy + real(fft_y .* conj(fft_y)); - end - n_ffts = n_ffts +1; - end - %% - %% 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); - end - end - %% - %% 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]; - end - end - if ( need_Pxy ) - Pxy = Pxy(1:psd_len) + conj([0; Pxy(Nfft:-1:psd_len+1); 0]); - end - if ( need_Pyy ) - Pyy = Pyy(1:psd_len) + [0; Pyy(Nfft:-1:psd_len+1); 0]; - end - 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)]; - end - end - if ( need_Pxy ) - Pxy = Pxy(1:psd_len) + conj([0; Pxy(Nfft:-1:psd_len+1)]); - end - if ( need_Pyy ) - Pyy = Pyy(1:psd_len) + [0; Pyy(Nfft:-1:psd_len+1)]; - end - end - else %% two-sided (and shifted) - psd_len = Nfft; - end - %% 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; - end - end - if ( do_cross ) - spectra(:,do_cross) = Pxy / scale; - spect_type(do_cross) = 2; - end - if ( do_trans ) - spectra(:,do_trans) = Pxy ./ Pxx; - spect_type(do_trans) = 3; - end - if ( do_coher ) - %% force coherence to be real - spectra(:,do_coher) = real(Pxy .* conj(Pxy)) ./ Pxx ./ Pyy; - spect_type(do_coher) = 4; - end - if ( do_ypower ) - spectra(:,do_ypower) = Pyy / scale; - spect_type(do_ypower) = 5; - end - 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,:)]; - end - end - %% - %% RETURN RESULTS or PLOT - if ( nargout>=2 && conf>0 ) - varargout{2} = Vxx; - end - if ( nargout>=(2+(conf>0)) ) - %% frequency is 2nd or 3rd return value, - %% depends on if 2nd is confidence interval - varargout{2+(conf>0)} = freq; - end - 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 = []; - end - if ( n_results > 1 ) - figure(); - end - 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))]); - end - 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))); - end - title( char(plot_title(spect_type(ii),:)) ); - ylabel( 'phase' ); - end - end %for - end - end -end - -%!demo -%! fflush(stdout); -%! rand('seed',2038014164); -%! 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]); -%! Fs = 25; % sampling frequency -%! hold off -%! pwelch([]); -%! pwelch(signal); -%! disp('Default settings: Fs=1Hz, overlap=0.5, no padding' ) -%! input('Onesided power spectral density (real data). Press ENTER', 's' ); -%! hold on -%! pwelch(skewed); -%! disp('Frequency-shifted complex data. Twosided wrap-around spectrum.' ); -%! input('Area is same as one-sided spectrum. Press ENTER', 's' ); -%! pwelch(signal,'shift','semilogy'); -%! input('Twosided, centred zero-frequency, lin-log plot. Press ENTER', 's' ); -%! hold off -%! figure(); -%! pwelch(skewed,[],[],[],Fs,'shift','semilogy'); -%! input('Actual Fs=25 Hz. Note change of scales. Press ENTER', 's' ); -%! pwelch(skewed,[],[],[],Fs,0.95,'shift','semilogy'); -%! input('Spectral density with 95% confidence interval. Press ENTER', 's' ); -%! pwelch('R12+'); -%! pwelch(signal,'squared'); -%! input('Spectral density with Matlab R12 defaults. Press ENTER', 's' ); -%! figure(); -%! pwelch([]); -%! pwelch(signal,3640,[],4096,2*pi,[],'no-strip'); -%! input('Same spectrum with 95% confidence interval. Press ENTER', 's' ); -%! figure(); -%! pwelch(signal,[],[],[],2*pi,0.95,'no-strip'); -%! input('95% confidence interval with native defaults. Press ENTER', 's' ); -%! pwelch(signal,64,[],[],2*pi,'no-strip'); -%! input('Only 32 frequency values in this spectrum. Press ENTER', 's' ); -%! hold on -%! pwelch(signal,64,[],256,2*pi,'no-strip'); -%! input('4:1 zero padding gives artificial smoothing. Press ENTER', 's' ); -%! figure(); -%! pwelch('psd'); -%! pwelch(signal,'squared'); -%! input('Just like Matlab spectrum.welch(...) defaults. Press ENTER', 's' ); -%! hold off -%! pwelch({}); -%! pwelch(white,signal,'trans','coher','short') -%! input('Transfer and coherence functions. Press ENTER', 's' ); -%! disp('Use "close all" to remove plotting windows.' );
--- a/main/signal/inst/pyulear.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% usage: -%% [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". - -function [psd,f_out]=pyulear(x,poles,varargin) - %% - if ( nargin<2 ) - error( 'pburg: need at least 2 args. Use "help pburg"' ); - end - %% - [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{:}); - end -end - -%!demo -%! fflush(stdout); -%! rand('seed',2038014164); -%! a = [ 1.0 -1.6216505 1.1102795 -0.4621741 0.2075552 -0.018756746 ]; -%! signal = detrend(filter(0.70181,a,rand(1,16384))); -%! % frequency shift by modulating with exp(j.omega.t) -%! skewed = signal.*exp(2*pi*i*2/25*[1:16384]); -%! Fs = 25; -%! hold on -%! pyulear(signal,3,[],Fs); -%! disp( 'Results from this demo should be nearly the same as pburg demo' ); -%! input('Onesided 3-pole spectrum. Press ENTER', 's' ); -%! pyulear(signal,4,[],Fs,'whole'); -%! input('Twosided 4-pole spectrum of same data. Press ENTER', 's' ); -%! pyulear(signal,5,128,Fs,'shift', 'semilogy'); -%! input('Twosided, centred zero-frequency, 5-pole. Press ENTER', 's' ); -%! pyulear(skewed,7,128,Fs,'shift','semilogy'); -%! input('Complex data, frequency-shifted. Press ENTER', 's' ); -%! user_freq=[-0.2:0.02:0.2]*Fs; -%! pyulear(skewed,7,user_freq,Fs,'semilogy'); -%! input('User-specified frequency values. Press ENTER', 's' ); -%! hold off -%! clf
--- a/main/signal/inst/qp_kaiser.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Usage: 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 -## ommited at all. - -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
--- a/main/signal/inst/rceps.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: [y, xm] = rceps(x) -## Produce the cepstrum of the signal x, and if desired, the minimum -## phase reconstruction of the signal x. If x is a matrix, do so -## for each column of the matrix. -## -## 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 in x -## [y, xm] = rceps(x.*hanning(1024)); # cepstrum and min phase reconstruction -## -## Reference -## Programs for digital signal processing. IEEE Press. -## New York: John Wiley & Sons. 1979. - -function [y, ym] = rceps(x) - if (nargin != 1) - print_usage; - end - 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:n/2+1), zeros(1,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:n/2+1,:); zeros(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 - -%!error rceps -%!error rceps(1,2) # too many arguments - -%!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 -%! #XXX FIXME XXX 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.'); -%! tol = 1e-14; -%! assert(yt.', y, tol); -%! assert(xmt.', xm, tol); - -%% 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)); - -%!demo -%! f0=70; Fs=10000; # 100 Hz fundamental, 10kHz 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); -%! auplot(x,Fs,'b',';signal;'); -%! hold on; auplot(xm,Fs,'g',';reconstruction;'); -%! hold off; -%! subplot(312); -%! axis("ticy"); -%! plot(w,log(abs(hx)), ";magnitude;", ... -%! w,log(abs(hxm)),";reconstruction;"); -%! subplot(313); -%! axis("on"); -%! plot(w,unwrap(arg(hx))/(2*pi), ";phase;",... -%! w,unwrap(arg(hxm))/(2*pi),";reconstruction;"); -%! figure(2); auplot(y,Fs,';cepstrum;'); -%! %------------------------------------------------------------- -%! % 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.
--- a/main/signal/inst/rectpuls.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: 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 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 -## auplot(pulstran(0:1/fs:4/f0, 0:1/f0:4/f0, 'rectpuls', w), fs); -## -## See also: pulstran - -function y = rectpuls(t, w = 1) - - if nargin<1 || nargin>2, - print_usage; - endif - - y = zeros(size(t)); - idx = find(t>=-w/2 & t < w/2); - try wfi = warning("off", "Octave:fortran-indexing"); - catch wfi = 0; - end - unwind_protect - y(idx) = ones(size(idx)); - unwind_protect_cleanup - warning(wfi); - end_unwind_protect -endfunction - -%!assert(rectpuls(0:1/100:0.3,.1), rectpuls([0:1/100:0.3]',.1)'); -%!assert(isempty(rectpuls([],.1))); -%!demo -%! fs = 11025; # arbitrary sample rate -%! f0 = 100; # pulse train sample rate -%! w = 0.3/f0; # pulse width 1/10th the distance between pulses -%! ylabel("amplitude"); xlabel("time (ms)"); -%! title("graph shows 3 ms pulses at 0,10,20,30 and 40 ms"); -%! auplot(pulstran(0:1/fs:4/f0, 0:1/f0:4/f0, 'rectpuls', w), fs); -%! title(""); xlabel(""); ylabel("");
--- a/main/signal/inst/rectwin.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{w}] =} rectwin(@var{L}) -## Return the filter coefficients of a rectangle window of length L. -## @seealso{hamming, hanning} -## @end deftypefn - -function w = rectwin(L) - if (nargin < 1); print_usage; end - w = ones(round(L),1); -endfunction
--- a/main/signal/inst/resample.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -## 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; if not, see <http://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=p/great_common_divisor; - q=q/great_common_divisor; - endif - - ## filter design if required - - if (nargin < 4) - - ## properties of the antialiasing filter - - log10_rejection = -3.0; - stopband_cutoff_f = 1.0/(2.0 * 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);
--- a/main/signal/inst/residued.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -%% 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; if not, see <http://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 (@code{residued}) 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)}. -%% Say @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 -%% Say @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"); - end - 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); - end - [r,p,f2,m] = residuez(NUM,DEN); - if f2, error('f2 not empty as expected'); end -end - -%!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.
--- a/main/signal/inst/residuez.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -%% 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; if not, see <http://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)}. -%% Say @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 -%% Say @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"); - end - 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); - if f, f = conj(fliplr(f)); end -end - -%!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);
--- a/main/signal/inst/sampled2continuous.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## Usage: -## -## 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. - -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 -end
--- a/main/signal/inst/sawtooth.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -## 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; if not, see <http://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
--- a/main/signal/inst/schtrig.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{rmsx},@var{w}] =} schtrig (@var{x},@var{lvl},@var{rst}=1) -## Implements a multisignal Schmitt trigger with levels @var{lvl}. -## -## The triger works along the first dimension of the array @var{x}. When @code{@var{rst}==1} -## the state of the trigger for all signals is set to the low state (i.e. 0). -## -## Run @code{demo schtrig} to see an example. -## -## @seealso{clustersegment} -## @end deftypefn - -function v = schtrig (x, lvl, rst = 1) - - persistent st0; - - if length(lvl) == 1 - lvl = abs (lvl)*[1 -1]; - else - lvl = sort(lvl,'descend'); - end - - [nT nc] = size(x); - - v = NA (nT, nc); - - if rst || isempty(st0) - st0 = zeros(1,nc); - printf ("Trigger initialized!\n"); - flush (stdout); - end - - 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'); - - for i=1:nc - % Record the state at the begining 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); - end - end - end - - 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); -%! -%! h = plot(t,x,t,v); -%! set (h([1 3]),'color','b'); -%! set (h([2 4]),'color',[0 1 0.5]); -%! set (h,'linewidth',2); -%! line([0; 1],lvl([1; 1]),'color','r'); -%! line([0;1],lvl([2;2]),'color','b')
--- a/main/signal/inst/sftrans.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: [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. - -function [Sz, Sp, Sg] = sftrans(Sz, Sp, Sg, W, stop) - - if (nargin != 5) - print_usage; - end - - 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"); - end - - 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))]; - end - end - 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))]; - end - end - end - 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)]; - end - end - 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; - end - end -endfunction
--- a/main/signal/inst/sgolay.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## 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 - -## 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,:); - end - ## 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);
--- a/main/signal/inst/sgolayfilt.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## y = sgolayfilt (x, p, n [, m [, ts]]) -## 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. -## -## y = sgolayfilt (x, F) -## Smooth the data in x with smoothing filter F 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 - -## TODO: 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); title("boxcar"); -%! axis([1 40 -2 15]); -%! 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;"); title(""); -%! -%! x=x+randn(size(x))/2; -%! subplot(122); title("boxcar+noise"); -%! 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;"); title(""); - -%!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); title("sinusoid"); -%! axis([0 1 -1.5 2.5]); -%! 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;"); title(""); -%! -%! x=x+0.2*randn(size(x)); % signal+noise -%! subplot(122); title("sinusoid+noise"); -%! 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;"); title("");
--- a/main/signal/inst/shanwavf.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{psi,x}] =} shanwavf (@var{lb,ub,n,fb,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
--- a/main/signal/inst/sigmoid_train.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% -*- texinfo -*- -%% @deftypefn {Function File} @var{y} = sigmoid_train(@var{t}, @var{ranges}, @var{rc}) -%% -%% Evaluates 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 sigmod @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 a array that defines the rising and falling time -%% constants of each sigmoids. Its size must equal the size of @var{ranges}. -%% -%% Run @code{demo sigmoid_train} to some examples of the use of this function. -%% -%% @end deftypefn - -function envelope = 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]) - - %% All bumps have different time constant but are symmetric - if length(timeconstant) ~= nRanges - error('signalError','Length of time constant must equal number of ranges.') - end - if isrow (timeconstant) - timeconstant = timeconstant'; - end - timeconstant = repmat (timeconstant,1,2); - - end - - %% Make sure t is horizontal - flag_transposed = false; - if iscolumn (t) - t = t.'; - flag_transposed = true; - end - [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; - - % 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.'; - end - -end - -%!demo -%! % Vectorized -%! t = linspace (0, 2, 500); -%! range = [0.1 0.4; 0.6 0.8; 1 2]; -%! rc = [1e-2 1e-2; 1e-3 1e-3; 2e-2 2e-2]; -%! y = sigmoid_train (t, range, rc); -%! -%! close all -%! 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'); -%! end -%! 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 -%! % 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); -%! -%! close all -%! 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'); -%! end -%! 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.
--- a/main/signal/inst/sos2tf.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -%% 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; if not, see <http://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{Bscale}) -%% Convert series second-order sections to direct form @math{H(z) = B(z)/A(z)}. -%% -%% INPUTS: -%% @itemize -%% -%% @item -%% @var{sos} = matrix of series second-order sections, one per row:@* -%% @var{sos} = [@var{B1}.' @var{A1}.'; ...; @var{BN}.' @var{AN}.'], where@* -%% @code{@var{B1}.'==[b0 b1 b2] and @var{A1}.'==[1 a1 a2]} for -%% section 1, etc.@* -%% b0 must be nonzero for each section.@* -%% See @code{filter()} for documentation of the -%% second-order direct-form filter coefficients @var{B}i and @var{A}i. -%% -%% @item -%% @var{Bscale} 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 digital filter @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, Bscale = 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'); - end - - A = 1; - B = 1; - - for i=1:N - B = conv(B, sos(i,1:3)); - A = conv(A, sos(i,4:6)); - end - - nB = length(B); - while nB && B(nB)==0 - B=B(1:nB-1); - nB=length(B); - end - - nA = length(A); - while nA && A(nA)==0 - A=A(1:nA-1); - nA=length(A); - end - B = B * Bscale; - -endfunction - -%!test -%! B=[1 1]; -%! A=[1 0.5]; -%! [sos,g] = tf2sos(B,A); -%! [Bh,Ah] = sos2tf(sos,g); -%! assert({Bh,Ah},{B,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({Bh,Ah},{B,A},100*eps);
--- a/main/signal/inst/sos2zp.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% -*- texinfo -*- -%% @deftypefn {Function File} {[@var{z}, @var{p}, @var{g}] =} sos2zp (@var{sos}) -%% @deftypefnx {Function File} {[@var{z}, @var{p}, @var{g}] =} sos2zp (@var{sos}, @var{Bscale}) -%% 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:@* -%% @var{sos} = [@var{B1}.' @var{A1}.'; ...; @var{BN}.' @var{AN}.'], where@* -%% @code{@var{B1}.'==[b0 b1 b2] and @var{A1}.'==[1 a1 a2]} for -%% section 1, etc.@* -%% b0 must be nonzero for each section. -%% See @code{filter()} for documentation of the -%% second-order direct-form filter coefficients @var{B}i and @var{A}i. -%% -%% @item -%% @var{Bscale} 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{g} = overall gain = @var{B}(Inf) -%% @end itemize -%% -%% EXAMPLE: -%% @example -%% [z,p,g] = sos2zp([1 0 1, 1 0 -0.81; 1 0 0, 1 0 0.49]) -%% => z = [i; -i; 0; 0], p = [0.9, -0.9, 0.7i, -0.7i], g=1 -%% @end example -%% -%% @seealso{zp2sos sos2tf tf2sos zp2tf tf2zp} -%% @end deftypefn - -function [z,p,g] = sos2zp (sos, Bscale = 1) - - if (nargin < 1 || nargin > 2) - print_usage; - endif - - gains = sos(:,1); % All b0 coeffs - g = prod(gains)*Bscale; % pole-zero gain - if g==0, error('sos2zp: one or more section gains is zero'); end - sos(:,1:3) = sos(:,1:3)./ [gains gains gains]; - - [N,m] = size(sos); - if m~=6, error('sos2zp: sos matrix should be N by 6'); end - - z = zeros(2*N,1); - p = zeros(2*N,1); - for i=1:N - ndx = [2*i-1:2*i]; - zi = roots(sos(i,1:3)); - z(ndx) = zi; - pi = roots(sos(i,4:6)); - p(ndx) = pi; - end -end - -%!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);
--- a/main/signal/inst/specgram.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,219 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: [S [, f [, t]]] = specgram(x [, n [, Fs [, window [, overlap]]]]) -## -## Generate a spectrogram for the signal. This chops the signal into -## overlapping slices, windows each slice and applies a Fourier -## transform to determine the frequency components at that slice. -## -## x: vector of samples -## n: size of fourier transform window, or [] for default=256 -## Fs: sample rate, or [] for default=2 Hz -## window: shape of the fourier transform window, or [] for default=hanning(n) -## Note: window length can be specified instead, in which case -## window=hanning(length) -## overlap: overlap with previous window, or [] for default=length(window)/2 -## -## Return values -## S is complex output of the FFT, one row per slice -## f is the frequency indices corresponding to the rows of S. -## t is the time indices corresponding to the columns of S. -## If no return value is requested, the spectrogram is displayed instead. -## -## 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, flipud(log(S))); # display in log scale -## -## 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,:)))); - -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; - ## make sure x is a vector - elseif columns(x) != 1 && rows(x) != 1 - error ("specgram data must be a vector"); - end - if columns(x) != 1, x = x'; end - - ## if only the window length is given, generate hanning window - if length(window) == 1, window = hanning(window); end - - ## should be extended to accept a vector of frequencies at which to - ## evaluate the fourier transform (via filterbank or chirp - ## z-transform) - if length(n)>1, - error("specgram doesn't handle frequency vectors yet"); - endif - - ## compute window offsets - win_size = length(window); - if (win_size > n) - n = win_size; - warning ("specgram fft size adjusted to %d", n); - end - 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; - end - 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); -%! disp("shows a diagonal from bottom left to top right"); -%! input("press enter:","s"); -%! -%! ## test of returned values -%! S = specgram(x, 2^nextpow2(window), Fs, window, window-step); -%! imagesc(20*log10(flipud(abs(S)))); -%! disp("same again, but this time using returned value"); - -%!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'
--- a/main/signal/inst/square.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -## 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, the square wave is +1 for -## that portion of the time. -## -## @verbatim -## on time -## duty cycle = ------------------ -## on time + off time -## @end verbatim -## -## @seealso{cos, sawtooth, sin, tripuls} -## @end deftypefn - -function v = square (t, duty = 0.5) - - if (nargin < 1 || nargin > 2) - print_usage; - endif - - t /= 2*pi; - v = ones(size(t)); - v(t-floor(t) >= duty) = -1; - -endfunction
--- a/main/signal/inst/ss2tf.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{num}, @var{den}] =} ss2tf (@var{a}, @var{b}, @var{c}, @var{d}) -## Conversion from transfer function to state-space. -## The state space system: -## @iftex -## @tex -## $$ \dot x = Ax + Bu $$ -## $$ y = Cx + Du $$ -## @end tex -## @end iftex -## @ifinfo -## @example -## . -## x = Ax + Bu -## y = Cx + Du -## @end example -## @end ifinfo -## -## is converted to a transfer function: -## @iftex -## @tex -## $$ G(s) = { { \rm num }(s) \over { \rm den }(s) } $$ -## @end tex -## @end iftex -## @ifinfo -## @example -## -## num(s) -## G(s)=------- -## den(s) -## @end example -## @end ifinfo -## -## @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
--- a/main/signal/inst/ss2zp.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{pol}, @var{zer}, @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
--- a/main/signal/inst/tf2sos.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% -*- texinfo -*- -%% @deftypefn {Function File} {[@var{sos}, @var{g}] =} 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: -%% @var{sos} = matrix of series second-order sections, one per row:@* -%% @var{sos} = [@var{B1}.' @var{A1}.'; ...; @var{BN}.' @var{AN}.'], where@* -%% @code{@var{B1}.'==[b0 b1 b2] and @var{A1}.'==[1 a1 a2]} for -%% section 1, etc.@* -%% b0 must be nonzero for each section (zeros at infinity not supported). -%% @var{Bscale} is an overall gain factor that effectively scales -%% any one of the @var{B}i vectors. -%% -%% 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,g] = tf2zp(B(:)',A(:)'); - sos = zp2sos(z,p,g); - -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);
--- a/main/signal/inst/tf2ss.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -## 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; if not, see <http://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: -## @iftex -## @tex -## $$ \dot x = Ax + Bu $$ -## $$ y = Cx + Du $$ -## @end tex -## @end iftex -## @ifinfo -## @example -## . -## x = Ax + Bu -## y = Cx + Du -## @end example -## @end ifinfo -## is obtained from a transfer function: -## @iftex -## @tex -## $$ G(s) = { { \rm num }(s) \over { \rm den }(s) } $$ -## @end tex -## @end iftex -## @ifinfo -## @example -## num(s) -## G(s)=------- -## den(s) -## @end example -## @end ifinfo -## -## 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
--- a/main/signal/inst/tf2zp.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{zer}, @var{pol}, @var{k}] =} tf2zp (@var{num}, @var{den}) -## Converts 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
--- a/main/signal/inst/tfe.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% Usage: -%% [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. - -function [varargout] = tfe(varargin) - %% - %% Check fixed argument - if ( nargin<2 ) - error( 'tfe: Need at least 2 args. Use help tfe.' ); - end - 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} = []; - end - end - 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; - end - pwelch(saved_compatib); -end
--- a/main/signal/inst/tfestimate.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% Usage: -%% [Pxx,freq]=tfestimate(x,y,window,overlap,Nfft,Fs,range) -%% -%% Estimate transfer function of system with input "x" and output "y". -%% Use the Welch (1967) periodogram/FFT method. -%% See "help pwelch" for description of arguments, hints and references. - -function [varargout] = tfestimate(varargin) - %% - %% Check fixed argument - if (nargin < 2 || nargin > 7) - print_usage (); - end - 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} = []; - end - end - 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; - end -end
--- a/main/signal/inst/triang.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: w = triang (L) -## -## Returns the filter coefficients of a triangular window of length L. -## Unlike the bartlett window, triang does not go to zero at the edges -## of the window. For odd L, triang(L) is equal to bartlett(L+2) except -## for the zeros at the edges of the window. - -function w = triang(L) - if (nargin != 1) - print_usage; - elseif (!isscalar(L) || L != fix (L) || L < 1) - error("triang: L has to be an integer > 0"); - endif - w = 1 - abs ([-(L-1):2:(L-1)]' / (L+rem(L,2))); -endfunction - -%!error triang -%!error triang(1,2) -%!error triang([1,2]); -%!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)); - -%!demo -%! subplot(221); axis([-1, 1, 0, 1.3]); grid("on"); -%! title("comparison with continuous for odd n"); -%! 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;"); -%! -%! subplot(222); axis([-1, 1, 0, 1.3]); grid("on"); -%! n=8; k=(n-1)/2; t=[-k:0.1:k]/(k+1/2); -%! title("note the higher peak for even n"); -%! plot(t,1+1/n-abs(t),";continuous;",[-k:k]/(k+1/2),triang(n),"g*;discrete;"); -%! -%! subplot(223); axis; grid("off"); -%! title("n odd, triang(n)==bartlett(n+2)"); -%! n=7; -%! plot(0:n+1,bartlett(n+2),"g-*;bartlett;",triang(n),"r-+;triang;"); -%! -%! subplot(224); axis; grid("off"); -%! title("n even, triang(n)!=bartlett(n+2)"); -%! n=8; -%! plot(0:n+1,bartlett(n+2),"g-*;bartlett;",triang(n),"r-+;triang;"); -%! -%! subplot(111); title("");
--- a/main/signal/inst/tripuls.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## usage: 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 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. -## -## Example -## fs = 11025; # arbitrary sample rate -## f0 = 100; # pulse train sample rate -## w = 0.3/f0; # pulse width 3/10th the distance between pulses -## auplot(pulstran(0:1/fs:4/f0, 0:1/f0:4/f0, 'tripuls', w), fs); -## -## See also: pulstran - -function y = tripuls (t, w = 1, skew = 0) - - if nargin<1 || nargin>3, - print_usage; - endif - - y = zeros(size(t)); - peak = skew*w/2; - try wfi = warning("off", "Octave:fortran-indexing"); - catch wfi = 0; - end - unwind_protect - 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 - unwind_protect_cleanup - warning(wfi); - end_unwind_protect -endfunction - -%!assert(tripuls(0:1/100:0.3,.1), tripuls([0:1/100:0.3]',.1)'); -%!assert(isempty(tripuls([],.1))); -%!demo -%! fs = 11025; # arbitrary sample rate -%! f0 = 100; # pulse train sample rate -%! w = 0.5/f0; # pulse width 1/10th the distance between pulses -%! subplot(211); ylabel("amplitude"); xlabel("time (ms)"); -%! title("graph shows 5 ms pulses at 0,10,20,30 and 40 ms"); -%! auplot(pulstran(0:1/fs:4/f0, 0:1/f0:4/f0, 'tripuls', w), fs); -%! subplot(212); -%! title("graph shows 5 ms pulses at 0,10,20,30 and 40 ms, skew -0.5"); -%! auplot(pulstran(0:1/fs:4/f0, 0:1/f0:4/f0, 'tripuls', w, -0.5), fs); -%! title(""); xlabel(""); ylabel("");
--- a/main/signal/inst/tukeywin.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{w} =} tukeywin (@var{L}, @var{r}) -## Return the filter coefficients of a Tukey window (also known as the -## cosine-tapered window) of length @var{L}. @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} -## egals 0 and a full box for @var{r} egals 1. By default @var{r} is set -## to 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. -## @end deftypefn - -function w = tukeywin (L, r = 1/2) - - if (nargin < 1 || nargin > 2) - print_usage; - 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 (L, 1); - case 1, - ## Hanning window - w = hanning (L); - otherwise - ## cosine-tapered window - t = linspace(0,1,L)(1:end/2)'; - w = (1 + cos(pi*(2*t/r-1)))/2; - w(floor(r*(L-1)/2)+2:end) = 1; - w = [w; ones(mod(L,2)); flipud(w)]; - endswitch - -endfunction - -%!demo -%! L = 100; -%! r = 1/3; -%! w = tukeywin (L, r); -%! title(sprintf("%d-point Tukey window, R = %d/%d", L, [p, q] = rat(r), q)); -%! plot(w);
--- a/main/signal/inst/upsample.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -## 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 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 n zeros. -## @seealso{decimate, downsample, interp, resample, upfirdn} -## @end deftypefn - -function y = upsample (x, n, phase = 0) - if nargin<2 || nargin>3, print_usage; end - - if phase > n - 1 - warning("This is incompatible with Matlab (phase = 0:n-1). See ... - octave-forge signal package release notes for details." ) - end - - [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.'; end - else - y = zeros(n*nr,nc); - y(phase + 1:n:end,:) = x; - end -end - -%!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]);
--- a/main/signal/inst/welchwin.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{w}] =} welchwin(@var{L},@var{c}) -## Returns a row vector containing a Welch window, given by -## @var{w}(n)=1-(n/N-1)^2, n=[0,1, ... @var{L}-1]. -## Argument @var{L} is the length of the window. -## Optional argument @var{c} specifies a "symmetric" window (the default), -## or a "periodic" window. -## -## A symmetric window has zero at each end and maximum in the middle; -## @var{L} must be an integer larger than 2. -## @code{if c=="symmetric", N=(L-1)/2} -## -## A periodic window wraps around the cyclic interval [0,1, ... @var{L}-1], -## and is intended for use with the DFT (functions fft(), -## periodogram() etc). -## @var{L} must be an integer larger than 1. -## @code{if c=="periodic", N=@var{L}/2}. -## -## @seealso{blackman, kaiser} -## @end deftypefn - -function [w] = welchwin(L,c) - if (nargin < 1 || nargin>2 ) - print_usage; - endif - symmetric=1; - if ( nargin==2 && ! isempty(c) ) - if ( ! ischar(c) || size(c,1) != 1 || - ( ! strcmp(c,'periodic') && ! strcmp(c,'symmetric') ) ) - error( "arg 2 (c) must be \"periodic\" or \"symmetric\"" ) - endif - symmetric = ! strcmp(c,'periodic'); - endif - ## - ## Periodic window is not properly defined if L<2. - ## Symmetric window is not properly defined if L<3. - min_L = 2 + symmetric; - if ( ! isreal(L) || ! isscalar(L) || L<min_L || fix(L) != L ) - error("arg 1 (L) must be an integer larger than %d", min_L-1 ); - endif - N = (L-symmetric)/2; - n = 0:L-1; - w = 1 - ((n-N)./N).^2; -endfunction; - -%!demo -%! printf( "Short symmetric windows\n" ); -%! welchwin(5) -%! welchwin(6) -%! welchwin(6,"symmetric") -%! welchwin(7) -%! input( "Press ENTER to continue", "s" ); -%! -%! printf( "Short periodic windows\n" ); -%! welchwin(6,"periodic") -%! welchwin(7,"periodic") -%! input( "Press ENTER to continue", "s" ); -%! -%! L=32; -%! printf( "Graph: single period of " ); -%! printf( "%d-point periodic (blue) and symmetric (red) windows\n", L ); -%! t=[0:L-1]; -%! xp=welchwin(L,"periodic"); -%! xs=welchwin(L,"symmetric"); -%! plot(t,xp,"b",t,xs,"r") -%! input( "Press ENTER to continue", "s" ); -%! -%! printf( "Graph: 4 periods of " ); -%! printf( "%d-point periodic (blue) and symmetric (red) windows\n", L ); -%! t2=[0:4*L-1]; -%! xp2=repmat(xp,1,4); -%! xs2=repmat(xs,1,4); -%! plot(t2,xp2,"b",t2,xs2,"r") -%! input( "Press ENTER to continue", "s" ); -%! -%! n=512; -%! s=fftshift(max(1.0e-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/L, L ); -%! semilogy(f,s)
--- a/main/signal/inst/window.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {@var{w} =} window (@var{f}, @var{n}, @var{opts}) -## Create a @var{n}-point windowing 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, n, varargin) - if (nargin == 0) - error ("window: UI tool not supported"); - elseif (nargin > 1) - w = feval (f, n, varargin{:}); - if (nargout > 0) - wout = w; - endif - else - print_usage (); - endif -endfunction
--- a/main/signal/inst/wkeep.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{y}] =} wkeep(@var{x,l,opt}) -## Extract the elements of x of size 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; end - if(isvector(x)) - - if(l > length(x)) - error('l must be or equal the size of x'); - end - - 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'); - end - 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'); - end - - 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'); - end - - y=x(firstr:firstr+l(1)-1,firstc:firstc+l(2)-1); - end - - end -end
--- a/main/signal/inst/wrev.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{y}] =} wrev(@var{x}) -## Reverse the order of the element of the vector x. -## @seealso{flipud, fliplr} -## @end deftypefn - -function y = wrev(x) - if (nargin < 1|| nargin > 1); print_usage; end - if(~isvector(x)) - error('x must be a vector'); - end - l = length(x); - k = 0:l-1; - y = x(l-k); -endfunction
--- a/main/signal/inst/xcorr.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,329 +0,0 @@ -## 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> -## -## 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{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 -## -## @iftex -## @tex -## $$ R_{xy}(k) = \sum_{i=1}^{N} x_{i+k} \conj(y_i), -## @end tex -## @end iftex -## @ifnottex -## @example -## N -## R_xy(k) = sum x_@{i+k@} conj(y_i), -## i=1 -## @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 unbiassed average, R(k)/(N-|k|), -## @item coeff -## 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, Y, maxlag, scale) - - if (nargin < 1 || nargin > 4) - print_usage; - endif - - ## assign arguments that are missing from the list - ## or reassign (right shift) them according to data type - 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 - - ## 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) || ischar(Y) || ! 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 colummn 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') - ## 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 uncessary 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 -##--------------------------------------------------------------
--- a/main/signal/inst/xcorr2.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -## 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; if not, see <http://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 negavtive 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(:))]);
--- a/main/signal/inst/xcov.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -## 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; if not, see <http://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 - - ## XXX FIXME XXX --- 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
--- a/main/signal/inst/zerocrossing.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -## 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; if not, see <http://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')
--- a/main/signal/inst/zp2sos.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -%% 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; if not, see <http://www.gnu.org/licenses/>. - -%% -*- texinfo -*- -%% @deftypefn {Function File} {[@var{sos}, @var{g}] =} zp2sos (@var{z}, @var{p}) -%% @deftypefnx {Function File} {[@var{sos}, @var{g}] =} zp2sos (@var{z}, @var{p}, @var{g}) -%% 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{g} = 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:@* -%% @var{sos} = [@var{B1}.' @var{A1}.'; ...; @var{BN}.' @var{AN}.'], where@* -%% @code{@var{B1}.'==[b0 b1 b2] and @var{A1}.'==[1 a1 a2]} for -%% section 1, etc.@* -%% b0 must be nonzero for each section.@* -%% 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{Bscale} is an overall gain factor that effectively scales -%% any one of the @var{B}i vectors. -%% @end itemize -%% -%% EXAMPLE: -%% @example -%% [z,p,g] = tf2zp([1 0 0 0 0 1],[1 0 0 0 0 .9]); -%% [sos,g] = zp2sos(z,p,g) -%% -%% 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{sos2pz sos2tf tf2sos zp2tf tf2zp} -%% @end deftypefn - -function [sos,g] = zp2sos(z,p,g) - - if nargin<3, g=1; end - if nargin<2, p=[]; end - - [zc,zr] = cplxreal(z); - [pc,pr] = cplxreal(p); - - % zc,zr,pc,pr - - nzc=length(zc); - npc=length(pc); - - nzr=length(zr); - npr=length(pr); - - % Pair up real zeros: - if nzr - if mod(nzr,2)==1, zr=[zr;0]; nzr=nzr+1; end - nzrsec = nzr/2; - zrms = -zr(1:2:nzr-1)-zr(2:2:nzr); - zrp = zr(1:2:nzr-1).*zr(2:2:nzr); - else - nzrsec = 0; - end - - % Pair up real poles: - if npr - if mod(npr,2)==1, pr=[pr;0]; npr=npr+1; end - nprsec = npr/2; - prms = -pr(1:2:npr-1)-pr(2:2:npr); - prp = pr(1:2:npr-1).*pr(2:2:npr); - else - nprsec = 0; - end - - nsecs = max(nzc+nzrsec,npc+nprsec); - - % Convert complex zeros and poles to real 2nd-order section form: - zcm2r = -2*real(zc); - zca2 = abs(zc).^2; - pcm2r = -2*real(pc); - pca2 = abs(pc).^2; - - sos = zeros(nsecs,6); - sos(:,1) = ones(nsecs,1); % all 2nd-order polynomials are monic - sos(:,4) = ones(nsecs,1); - - nzrl=nzc+nzrsec; % index of last real zero section - nprl=npc+nprsec; % index of last real pole section - - for i=1:nsecs - - if i<=nzc % lay down a complex zero pair: - sos(i,2:3) = [zcm2r(i) zca2(i)]; - elseif i<=nzrl % lay down a pair of real zeros: - sos(i,2:3) = [zrms(i-nzc) zrp(i-nzc)]; - end - - if i<=npc % lay down a complex pole pair: - sos(i,5:6) = [pcm2r(i) pca2(i)]; - elseif i<=nprl % lay down a pair of real poles: - sos(i,5:6) = [prms(i-npc) prp(i-npc)]; - end - end -end - -%!test -%! B=[1 0 0 0 0 1]; A=[1 0 0 0 0 .9]; -%! [z,p,g] = tf2zp(B,A); -%! [sos,g] = zp2sos(z,p,g); -%! [Bh,Ah] = sos2tf(sos,g); -%! assert({Bh,Ah},{B,A},100*eps);
--- a/main/signal/inst/zp2ss.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{a}, @var{b}, @var{c}, @var{d}] =} zp2ss (@var{zer}, @var{pol}, @var{k}) -## Conversion from zero / pole to state space. -## -## @strong{Inputs} -## @table @var -## @item zer -## @itemx pol -## 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{zer} means that @math{x-jy} is also in @var{zer}). -## @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: -## @iftex -## @tex -## $$ \dot x = Ax + Bu $$ -## $$ y = Cx + Du $$ -## @end tex -## @end iftex -## @ifinfo -## @example -## . -## x = Ax + Bu -## y = Cx + Du -## @end example -## @end ifinfo -## @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
--- a/main/signal/inst/zp2tf.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -## 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; if not, see <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {Function File} {[@var{num}, @var{den}] =} zp2tf (@var{zer}, @var{pol}, @var{k}) -## Converts zeros / poles to a transfer function. -## -## @strong{Inputs} -## @table @var -## @item zer -## @itemx pol -## 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
--- a/main/signal/inst/zplane.m Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -## Copyright (C) 1999, 2001 Paul Kienzle <pkienzle@users.sf.net> -## Copyright (C) 2004 Stefan van der Walt <stefan@sun.ac.za> -## -## 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/>. - -## usage: zplane(b [, a]) or zplane(z [, p]) -## -## Plot the poles and zeros. If the arguments are row vectors then they -## represent filter coefficients (numerator polynomial b and denominator -## polynomial a), but if they are column vectors or matrices then they -## represent poles and zeros. -## -## This is a horrid interface, but I didn't choose it; better would be -## to accept b,a or z,p,g like other functions. The saving grace is -## that poly(x) always returns a row vector and roots(x) always returns -## a column vector, so it is usually right. You must only be careful -## when you are creating filters by hand. -## -## 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) -## -## The denominator a defaults to 1, and the poles p defaults to []. - -## TODO: Consider a plot-like interface: -## TODO: zplane(x1,y1,fmt1,x2,y2,fmt2,...) -## TODO: with y_i or fmt_i optional as usual. This would allow -## TODO: legends and control over point colour and filters of -## TODO: different orders. -function zplane(z, p = []) - - if (nargin < 1 || nargin > 2) - print_usage; - end - 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; - - text(); - plot_with_labels(z, "o"); - plot_with_labels(p, "x"); - refresh; - - r = exp(2i*pi*[0:100]/100); - plot(real(r), imag(r),'k'); hold on; - axis equal; - grid on; - axis(1.05*[xmin, xmax, ymin, ymax]); - if (!isempty(p)) - h = plot(real(p), imag(p), "bx"); - set (h, 'MarkerSize', 7); - endif - if (!isempty(z)) - h = plot(real(z), imag(z), "bo"); - set (h, 'MarkerSize', 7); - endif - hold off; -endfunction - -function plot_with_labels(x, symbol) - if ( !isempty(x) ) - - x_u = unique(x(:)); - - for i = 1:length(x_u) - n = sum(x_u(i) == x(:)); - if (n > 1) - text(real(x_u(i)), imag(x_u(i)), [" " num2str(n)]); - endif - endfor - - col = "rgbcmy"; - for c = 1:columns(x) - plot(real( x(:,c) ), imag( x(:,c) ), [col(mod(c,6)),symbol ";;"]); - 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 plane"); -%! subplot(231); title("transfer function form"); zplane(sys_b, sys_a); -%! subplot(232); title("pole-zero form"); zplane(z,p); -%! subplot(233); title("empty p"); zplane(z); -%! subplot(234); title("empty a"); zplane(sys_b); -%! disp("The matrix plot has 2 sets of points, one inside the other"); -%! subplot(235); title("matrix"); zplane([z, 0.7*z], [p, 0.7*p]);
--- a/main/signal/src/.svnignore Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -PKG_ADD -*.octlink -*.oct
--- a/main/signal/src/Makefile Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -MKOCTFILE ?= mkoctfile - -all: __fwht__.oct cl2bp.oct remez.oct medfilt1.oct sosfilt.oct upfirdn.oct - -%.oct: %.cc - $(MKOCTFILE) -Wall -s $< - -cl2bp.o: cl2bp.cc cl2bp_lib.h - $(MKOCTFILE) -Wall -c $< - -cl2bp_lib.o: cl2bp_lib.cc cl2bp_lib.h - $(MKOCTFILE) -Wall -c $< - -cl2bp.oct: cl2bp.o cl2bp_lib.o - $(MKOCTFILE) -Wall -s $^ - -clean: - rm -f *.o octave-core core *.oct *~
--- a/main/signal/src/__fwht__.cc Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -// Copyright (C) 2013 Mike Miller <mtmiller@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; if not, see <http://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\n") -{ - 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 (); -}
--- a/main/signal/src/cl2bp.cc Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -// 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; if not, see <http://www.gnu.org/licenses/>. - -#include <octave/oct.h> - -#include "cl2bp_lib.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}\ - [, @var{gridsize}])\n\ -\n\ -Constrained L2 bandpass FIR filter design. This is a fast implementation of the algorithm\n\ -cited below. Compared to @dfn{remez}, it offers implicit specification of transition bands,\n\ -a higher likelihood of convergence, and an error criterion combining features of both L2 and\n\ -Chebyshev approaches.@*\n\ -Inputs:@*\n\ -@var{m}: degree of cosine polynomial, i.e. the number of output coefficients will be @var{m}*2+1@*\n\ -@var{w1}, @var{w2}: bandpass filter cutoffs in the range 0 <= @var{w1} < @var{w2} <= pi,\n\ -where pi is the Nyquist frequency@*\n\ -@var{up}: vector of 3 upper bounds for [stopband1, passband, stopband2]@*\n\ -@var{lo}: vector of 3 lower bounds for [stopband1, passband, stopband2]@*\n\ -@var{gridsize}: search grid size; larger values may improve accuracy,\n\ -but greatly increase calculation time.@*\n\ -Output:@*\n\ -A vector of @var{m}*2+1 FIR coefficients, or an empty value if the solver failed to converge.@*\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\ -Original Paper: I. W. Selesnick, M. Lang, and C. S. Burrus. A modified algorithm for\n\ -constrained least square design of multiband FIR filters without 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); - if (error_state) { - gripe_wrong_type_arg("cl2bp", args (0)); - return retval; - } - const double w1 = args(1).double_value(); - if (error_state) { - gripe_wrong_type_arg("cl2bp", args (1)); - return retval; - } - const double w2 = args(2).double_value(); - if (error_state) { - gripe_wrong_type_arg("cl2bp", args (2)); - return retval; - } - const ColumnVector up_vector(args(3).vector_value()); - if (error_state) { - gripe_wrong_type_arg("cl2bp", args (3)); - return retval; - } - const ColumnVector lo_vector(args(4).vector_value()); - if (error_state) { - gripe_wrong_type_arg("cl2bp", args (4)); - return retval; - } - if (up_vector.length() != 3 || lo_vector.length() != 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 = args(5).int_value(true); - if (error_state) { - gripe_wrong_type_arg("cl2bp", args (5)); - return retval; - } - 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(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); -*/
--- a/main/signal/src/cl2bp_lib.cc Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,603 +0,0 @@ -// 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; if not, see <http://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]); - - 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); - } - - 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; -}
--- a/main/signal/src/cl2bp_lib.h Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -// 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; if not, see <http://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& src) { } // 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
--- a/main/signal/src/medfilt1.cc Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,242 +0,0 @@ -/* - * Copyright 2000 Paul Kienzle <pkienzle@users.sf.net> - * This source code is freely redistributable and may be used for - * any purpose. This copyright notice must be maintained. - * Paul Kienzle is not responsible for the consequences of using - * this software. - * - * Mar 2000 - Kai Habel (kahacjde@linux.zrz.tu-berlin.de) - * Change: ColumnVector x=arg(i).vector_value(); - * to: ColumnVector x=ColumnVector(arg(i).vector_value()); - * Oct 2000 - Paul Kienzle (pkienzle@users.sf.net) - * rewrite to ignore NaNs rather than replacing them with zero - * extend to handle matrix arguments - */ - -#include <cmath> -#include <octave/oct.h> -#include <octave/lo-ieee.h> -#include <octave/pager.h> -using namespace std; - -// The median class holds a sorted data window. This window is -// intended to slide over the data, so when the window shifts -// by one position, the old value from the start of the window must -// be removed and the new value from the end of the window must -// be added. Since removals and additions generally occur in pairs, -// a hole is left in the sorted window when the value is removed so -// that on average, fewer values need to be shifted to close the -// hole and open a new one in the sorted position. -class Median { -private: - double *window; // window data - int max; // length of window used - int hole; // position of hole, or max if no hole - void close_hole() // close existing hole - { - // move hole to the end of the window - while (hole < max-1) { - window[hole] = window[hole+1]; - hole++; - } - // shorten window (if no hole, then hole==max) - if (hole == max-1) max--; - } - void print(); - -public: - Median(int n) - { - max=hole=0; - window = new double[n]; - } - ~Median(void) - { - delete [] window; - } - - void add(double v); // add a new value - void remove(double v); // remove an existing value - void clear() { max=hole=0; } // clear the window - double operator() (); // find the median in the window -} ; - -// Print the sorted window, and indicate any hole -void Median::print() -{ - octave_stdout << "[ "; - for (int i=0; i < max; i++) - { - if (i == hole) - octave_stdout << "x "; - else - octave_stdout << window[i] << " "; - } - octave_stdout << " ]"; -} - - -// Remove a value from the sorted window, leaving a hole. The caller -// must promise to only remove values that they have added. -void Median::remove(double v) -{ - // NaN's are not added or removed - if (lo_ieee_isnan(v)) return; - - // octave_stdout << "Remove " << v << " from "; print(); - - // only one hole allowed, so close pre-existing ones - close_hole(); - - // binary search to find the value to remove - int lo = 0, hi=max-1; - hole = hi/2; - while (lo <= hi) { - if (v > window[hole]) lo = hole+1; - else if (v < window[hole]) hi = hole-1; - else break; - hole = (lo+hi)/2; - } - - // Verify that it is the correct value to replace - // Note that we shouldn't need this code since we are always replacing - // a value that is already in the window, but for some reason - // v==window[hole] occasionally doens't work. - if (v != window[hole]) { - for (hole = 0; hole < max-1; hole++) - if (fabs(v-window[hole]) < fabs(v-window[hole+1])) break; - warning ("medfilt1: value %f not found---removing %f instead", - v, window[hole]); - print(); octave_stdout << endl; - } - - // octave_stdout << " gives "; print(); octave_stdout << endl; -} - -// Insert a new value in the sorted window, plugging any holes, or -// extending the window as necessary. The caller must promise not -// to add more values than median was created with, without -// removing some beforehand. -void Median::add(double v) -{ - // NaN's are not added or removed - if (lo_ieee_isnan(v)) return; - - // octave_stdout << "Add " << v << " to "; print(); - - // If no holes, extend the array - if (hole == max) max++; - - // shift the hole up to the beginning as far as it can go. - while (hole > 0 && window[hole-1] > v) { - window[hole] = window[hole-1]; - hole--; - } - - // or shift the hole down to the end as far as it can go. - while (hole < max-1 && window[hole+1] < v) { - window[hole] = window[hole+1]; - hole++; - } - - // plug in the replacement value - window[hole] = v; - - // close the hole - hole = max; - - // octave_stdout << " gives "; print(); octave_stdout << endl; -} - -// Compute the median value from the sorted window -// Return the central value if there is one or the average of the -// two central values. Return NaN if there are no values. -double Median::operator()() -{ - close_hole(); - - if (max % 2 == 1) - return window[(max-1)/2]; - else if (max == 0) - return lo_ieee_nan_value(); - else - return (window[max/2-1]+window[max/2])/2.0; -} - -DEFUN_DLD (medfilt1, args, , - "y = medfilt1(x [, n])\n\ -\n\ -Apply a median filter of length n to the signal x. A sliding window is\n\ -applied to the data, and for each step the median value in the window is\n\ -returned. If n is odd then the window for y(i) is x(i-(n-1)/2:i+(n-1)/2).\n\ -If n is even then the window is x(i-n/2:i+n/2-1) and the two values in the\n\ -center of the sorted window are averaged. If n is not given, then 3 is used.\n\ -NaNs are ignored, as are values beyond the ends, by taking the median of\n\ -the remaining values.") -{ - octave_value_list retval; - - int nargin = args.length(); - if (nargin < 1 || nargin > 3) - { - print_usage (); - return retval; - } - - if (args(0).is_complex_type()) - { - error("medfilt1 cannot process complex vectors"); - return retval; - } - - int n=3; // length of the filter (default 3) - if (nargin > 1) n = NINT(args(1).double_value()); - if (n < 1) - { - error ("medfilt1 filter length must be at least 1"); - return retval; - } - - // Create a window to hold the sorted median values - Median median(n); - int mid = n/2; // mid-point of the window - - Matrix signal(args(0).matrix_value()); - int nr = signal.rows(); // number of points to process - int nc = signal.columns(); // number of points to process - Matrix filter(nr,nc); // filtered signal to return - - if (nr == 1) // row vector - { - int start = -n, end = 0, pos=-(n-mid)+1; - while (pos < nc) - { - if (start >= 0) median.remove(signal(0,start)); - if (end < nc) median.add(signal(0,end)); - if (pos >= 0) filter(0,pos) = median(); - start++, end++, pos++; - } - } - else // column vector or matrix - { - for (int column=0; column < nc; column++) - { - median.clear(); - int start = -n, end = 0, pos=-(n-mid)+1; - while (pos < nr) - { - if (start >= 0) median.remove(signal(start,column)); - if (end < nr) median.add(signal(end,column)); - if (pos >= 0) filter(pos,column) = median(); - start++, end++, pos++; - } - } - } - - retval(0) = filter; - return retval; -} - -/* -%!assert(medfilt1([1, 2, 3, 4, 5], 3), [1.5, 2, 3, 4, 4.5]); -*/
--- a/main/signal/src/remez.cc Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,903 +0,0 @@ -// 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; if not, see <http://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 <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 - - -#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 */ - 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 coeffiecients - * 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 reponse 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(int 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, , - "b = remez(n, f, a [, w] [, ftype] [, griddensity])\n\ -Parks-McClellan optimal FIR filter design.\n\ -n gives the number of taps in the returned filter\n\ -f gives frequency at the band edges [ b1 e1 b2 e2 b3 e3 ...]\n\ -a gives amplitude at the band edges [ a(b1) a(e1) a(b2) a(e2) ...]\n\ -w gives weighting applied to each band\n\ -ftype is 'bandpass', 'hilbert' or 'differentiator'\n\ -griddensity determines how accurately the filter will be\n\ - constructed. The minimum value is 16, but higher numbers are\n\ - slower to compute.\n\ -\n\ -Frequency is in the range (0, 1), with 1 being the nyquist frequency") -{ - octave_value_list retval; - int i; - - int nargin = args.length(); - if (nargin < 3 || nargin > 6) { - print_usage (); - return retval; - } - - int numtaps = NINT (args(0).double_value()) + 1; // #coeff = filter order+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.length()/2; - OCTAVE_LOCAL_BUFFER(double, bands, numbands*2); - if (numbands < 1 || o_bands.length()%2 == 1) { - error("remez: must have an even number of band edges"); - return retval; - } - for (i=1; i < o_bands.length(); 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.length() != o_bands.length()) { - 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.length() != 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 = 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 = 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); - - */
--- a/main/signal/src/sosfilt.cc Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -// 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; if not, see <http://www.gnu.org/licenses/>. - -#include <octave/config.h> -#include <octave/defun-dld.h> -#include <octave/error.h> -#include <octave/gripes.h> -#include <octave/oct-obj.h> -#include <octave/pager.h> -#include <octave/quit.h> -#include <octave/variables.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}.@*\n\ -The second order section filter is described by the matrix @var{sos} with:@*\n\ -@multitable {col 1} {this is column two}\n\ -@item @tab [ @var{B1} @var{A1} ]@*\n\ -@item @var{sos} = @tab [ ... ],@*\n\ -@item @tab [ @var{BN} @var{AN} ]@*\n\ -@end multitable\n\ -where @code{@var{B1}=[b0 b1 b2]} and @code{@var{A1}=[1 a1 a2]} for section 1, etc.@*\n\ -b0 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 (error_state) - { - gripe_wrong_type_arg("sosfilt",args(0)); - return retval; - } - - if (sos.columns() != 6) - { - error("Second-order section matrix must be a non-empty Lx6 matrix"); - return retval; - } - - Matrix x( args(1).matrix_value() ); - - if (error_state) - { - gripe_wrong_type_arg("sosfilt",args(1)); - return retval; - } - - 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; -} -
--- a/main/signal/src/upfirdn.cc Mon Mar 18 17:17:18 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -// 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; if not, see <http://www.gnu.org/licenses/>. - -#include <octave/config.h> -#include <octave/defun-dld.h> -#include <octave/error.h> -#include <octave/gripes.h> -#include <octave/oct-obj.h> -#include <octave/pager.h> -#include <octave/quit.h> -#include <octave/variables.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.length (); - const double r = p/(static_cast<double> (q)); - - const octave_idx_type Ly = ceil (static_cast<double> ((rx-1)*p + Lh) / - static_cast<double> (q)); - - MT y (Ly, cx, 0.0); - - for (octave_idx_type c = 0; c < cx; c++) - { - octave_idx_type m = 0; - while (m < Ly) - { - const octave_idx_type n = floor (m/r); - const octave_idx_type lm = (m * q) % p; - octave_idx_type k = 0; - typename MT::element_type accum; - accum = 0.0; - do - { - octave_idx_type ix = n - k; - if (ix >= rx) - { - k ++; - continue; - } - - const octave_idx_type ih = k * p + lm; - if ((ih >= Lh) | (ix < 0)) - break; - - accum += h (ih) * x (ix, c); - k++; - } - while (1); - - y (m, c) = accum; - m ++; - } - - } - - 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 ()); - - if (error_state) - { - gripe_wrong_type_arg ("upfirdn", args (1)); - return retval; - } - - octave_idx_type p = args (2).idx_type_value (); - - if (error_state) - { - gripe_wrong_type_arg ("upfirdn", args (2)); - return retval; - } - - octave_idx_type q = args (3).idx_type_value (); - - if (error_state) - { - gripe_wrong_type_arg ("upfirdn", args (3)); - return retval; - } - - // Do the dispatching - if (args (0).is_real_matrix ()) - { - Matrix x = args (0).matrix_value (); - if (error_state) - { - gripe_wrong_type_arg ("upfirdn", args (0)); - return retval; - } - - Matrix y = upfirdn (x, h, p, q); - retval (0) = y; - } - else if (args (0).is_complex_matrix ()) - { - ComplexMatrix x = args (0).complex_matrix_value (); - if (error_state) - { - gripe_wrong_type_arg ("upfirdn", args (0)); - return retval; - } - - ComplexMatrix y = upfirdn (x, h, p, q); - retval (0) = y; - } - - return retval; -} -