diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3f4cdfe..2a9c878 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,15 +62,21 @@ if (DEFINED WIN32)
include_directories ( ${PROJECT_SOURCE_DIR}/external/fftw-3.3.4-dll32 ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release )
link_directories ( ${PROJECT_SOURCE_DIR}/external/fftw-3.3.4-dll32 ${PROJECT_SOURCE_DIR}/external/rtl-sdr-release/x32 )
set(FFTW_LIB fftw3-3)
+
include_directories ( ${PROJECT_SOURCE_DIR}/external/openal-soft-1.16.0-bin/include )
link_directories ( ${PROJECT_SOURCE_DIR}/external/openal-soft-1.16.0-bin/libs/Win32 )
SET (OPENAL_LIBRARY libOpenAL32.dll winmm)
+
+ link_directories ( ${PROJECT_SOURCE_DIR}/external/liquid-dsp/lib )
+ include_directories ( ${PROJECT_SOURCE_DIR}/external/liquid-dsp/include )
else (DEFINED WIN32)
set(RTLSDR_INCLUDE "/opt/local/include" CACHE FILEPATH "RTL-SDR Include Path")
set(RTLSDR_LIB "/opt/local/lib" CACHE FILEPATH "RTL-SDR Lib Path")
include_directories(${RTLSDR_INCLUDE})
link_directories(${RTLSDR_LIB})
+
set(FFTW_LIB fftw3)
+
find_package (OpenAL)
include_directories ( ${OPENAL_INCLUDE_DIR} )
endif (DEFINED WIN32)
@@ -104,7 +110,7 @@ SET (cubicsdr_headers
add_executable(CubicSDR ${cubicsdr_sources} ${cubicsdr_headers})
-target_link_libraries(CubicSDR rtlsdr ${FFTW_LIB} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${OPENAL_LIBRARY})
+target_link_libraries(CubicSDR rtlsdr liquid ${FFTW_LIB} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${OPENAL_LIBRARY})
# cubicvr2 glfw ${GLFW_LIBRARIES}
diff --git a/external/liquid-dsp/COPYING b/external/liquid-dsp/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/external/liquid-dsp/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/external/liquid-dsp/include/liquid.h b/external/liquid-dsp/include/liquid.h
new file mode 100644
index 0000000..933b7b3
--- /dev/null
+++ b/external/liquid-dsp/include/liquid.h
@@ -0,0 +1,5729 @@
+/*
+ * Copyright (c) 2007 - 2014 Joseph Gaeddert
+ *
+ * This file is part of liquid.
+ *
+ * liquid is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * liquid is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with liquid. If not, see .
+ */
+#ifndef __LIQUID_H__
+#define __LIQUID_H__
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4003 )
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+# define LIQUID_USE_COMPLEX_H 0
+#else
+# define LIQUID_USE_COMPLEX_H 1
+#endif // __cplusplus
+
+//
+// Make sure the version and version number macros weren't defined by
+// some prevoiusly included header file.
+//
+#ifdef LIQUID_VERSION
+# undef LIQUID_VERSION
+#endif
+#ifdef LIQUID_VERSION_NUMBER
+# undef LIQUID_VERSION_NUMBER
+#endif
+
+//
+// Compile-time version numbers
+//
+// LIQUID_VERSION = "X.Y.Z"
+// LIQUID_VERSION_NUMBER = (X*1000000 + Y*1000 + Z)
+//
+#define LIQUID_VERSION "1.2.0"
+#define LIQUID_VERSION_NUMBER 1002000
+
+//
+// Run-time library version numbers
+//
+extern const char liquid_version[];
+const char * liquid_libversion(void);
+int liquid_libversion_number(void);
+
+// run-time library validation
+#define LIQUID_VALIDATE_LIBVERSION \
+ if (LIQUID_VERSION_NUMBER != liquid_libversion_number()) { \
+ fprintf(stderr,"%s:%u: ", __FILE__,__LINE__); \
+ fprintf(stderr,"error: invalid liquid runtime library\n"); \
+ exit(1); \
+ } \
+
+#define LIQUID_CONCAT(prefix, name) prefix ## name
+#define LIQUID_VALIDATE_INPUT
+
+/*
+ * Compile-time complex data type definitions
+ *
+ * Default: use the C99 complex data type, otherwise
+ * define complex type compatible with the C++ complex standard,
+ * otherwise resort to defining binary compatible array.
+ */
+#if LIQUID_USE_COMPLEX_H==1
+# include
+# define LIQUID_DEFINE_COMPLEX(R,C) typedef R _Complex C
+#elif defined _GLIBCXX_COMPLEX || defined _LIBCPP_COMPLEX
+# define LIQUID_DEFINE_COMPLEX(R,C) typedef std::complex C
+#else
+# define LIQUID_DEFINE_COMPLEX(R,C) typedef struct {R real; R imag;} C;
+#endif
+//# define LIQUID_DEFINE_COMPLEX(R,C) typedef R C[2]
+
+LIQUID_DEFINE_COMPLEX(float, liquid_float_complex);
+LIQUID_DEFINE_COMPLEX(double, liquid_double_complex);
+
+//
+// MODULE : agc (automatic gain control)
+//
+
+#define AGC_MANGLE_CRCF(name) LIQUID_CONCAT(agc_crcf, name)
+#define AGC_MANGLE_RRRF(name) LIQUID_CONCAT(agc_rrrf, name)
+
+// large macro
+// AGC : name-mangling macro
+// T : primitive data type
+// TC : input/output data type
+#define LIQUID_AGC_DEFINE_API(AGC,T,TC) \
+typedef struct AGC(_s) * AGC(); \
+ \
+/* create automatic gain control object */ \
+AGC() AGC(_create)(void); \
+ \
+/* destroy object, freeing all internally-allocated memory */ \
+void AGC(_destroy)(AGC() _q); \
+ \
+/* print object properties to stdout */ \
+void AGC(_print)(AGC() _q); \
+ \
+/* reset object's internal state */ \
+void AGC(_reset)(AGC() _q); \
+ \
+/* execute automatic gain control on an single input sample */ \
+/* _q : automatic gain control object */ \
+/* _x : input sample */ \
+/* _y : output sample */ \
+void AGC(_execute)(AGC() _q, \
+ TC _x, \
+ TC * _y); \
+ \
+/* execute automatic gain control on block of samples */ \
+/* _q : automatic gain control object */ \
+/* _x : input data array, [size: _n x 1] */ \
+/* _n : number of input, output samples */ \
+/* _y : output data array, [szie: _n x 1] */ \
+void AGC(_execute_block)(AGC() _q, \
+ TC * _x, \
+ unsigned int _n, \
+ TC * _y); \
+ \
+/* lock/unlock gain control */ \
+void AGC(_lock)( AGC() _q); \
+void AGC(_unlock)(AGC() _q); \
+ \
+/* get/set loop filter bandwidth; attack/release time */ \
+float AGC(_get_bandwidth)(AGC() _q); \
+void AGC(_set_bandwidth)(AGC() _q, float _bt); \
+ \
+/* get/set signal level (linear) relative to unity energy */ \
+float AGC(_get_signal_level)(AGC() _q); \
+void AGC(_set_signal_level)(AGC() _q, float _signal_level); \
+ \
+/* get/set signal level (dB) relative to unity energy */ \
+float AGC(_get_rssi)(AGC() _q); \
+void AGC(_set_rssi)(AGC() _q, float _rssi); \
+ \
+/* get/set gain value (linear) relative to unity energy */ \
+float AGC(_get_gain)(AGC() _q); \
+void AGC(_set_gain)(AGC() _q, float _gain); \
+ \
+/* initialize internal gain on input array */ \
+/* _q : automatic gain control object */ \
+/* _x : input data array, [size: _n x 1] */ \
+/* _n : number of input, output samples */ \
+void AGC(_init)(AGC() _q, \
+ TC * _x, \
+ unsigned int _n); \
+
+// Define agc APIs
+LIQUID_AGC_DEFINE_API(AGC_MANGLE_CRCF, float, liquid_float_complex)
+LIQUID_AGC_DEFINE_API(AGC_MANGLE_RRRF, float, float)
+
+
+
+//
+// MODULE : audio
+//
+
+// CVSD: continuously variable slope delta
+typedef struct cvsd_s * cvsd;
+
+// create cvsd object
+// _num_bits : number of adjacent bits to observe (4 recommended)
+// _zeta : slope adjustment multiplier (1.5 recommended)
+// _alpha : pre-/post-emphasis filter coefficient (0.9 recommended)
+// NOTE: _alpha must be in [0,1]
+cvsd cvsd_create(unsigned int _num_bits,
+ float _zeta,
+ float _alpha);
+
+// destroy cvsd object
+void cvsd_destroy(cvsd _q);
+
+// print cvsd object parameters
+void cvsd_print(cvsd _q);
+
+// encode/decode single sample
+unsigned char cvsd_encode(cvsd _q, float _audio_sample);
+float cvsd_decode(cvsd _q, unsigned char _bit);
+
+// encode/decode 8 samples at a time
+void cvsd_encode8(cvsd _q, float * _audio, unsigned char * _data);
+void cvsd_decode8(cvsd _q, unsigned char _data, float * _audio);
+
+
+//
+// MODULE : buffer
+//
+
+// circular buffer
+#define CBUFFER_MANGLE_FLOAT(name) LIQUID_CONCAT(cbufferf, name)
+#define CBUFFER_MANGLE_CFLOAT(name) LIQUID_CONCAT(cbuffercf, name)
+
+// large macro
+// CBUFFER : name-mangling macro
+// T : data type
+#define LIQUID_CBUFFER_DEFINE_API(CBUFFER,T) \
+typedef struct CBUFFER(_s) * CBUFFER(); \
+ \
+/* create circular buffer object of a particular size */ \
+CBUFFER() CBUFFER(_create)(unsigned int _max_size); \
+ \
+/* create circular buffer object of a particular size and */ \
+/* specify the maximum number of elements that can be read */ \
+/* at any given time. */ \
+CBUFFER() CBUFFER(_create_max)(unsigned int _max_size, \
+ unsigned int _max_read); \
+ \
+/* destroy cbuffer object, freeing all internal memory */ \
+void CBUFFER(_destroy)(CBUFFER() _q); \
+ \
+/* print cbuffer object properties */ \
+void CBUFFER(_print)(CBUFFER() _q); \
+ \
+/* print cbuffer object properties and internal state */ \
+void CBUFFER(_debug_print)(CBUFFER() _q); \
+ \
+/* clear internal buffer */ \
+void CBUFFER(_clear)(CBUFFER() _q); \
+ \
+/* get the number of elements currently in the buffer */ \
+unsigned int CBUFFER(_size)(CBUFFER() _q); \
+ \
+/* get the maximum number of elements the buffer can hold */ \
+unsigned int CBUFFER(_max_size)(CBUFFER() _q); \
+ \
+/* get the maximum number of elements you may read at once */ \
+unsigned int CBUFFER(_max_read)(CBUFFER() _q); \
+ \
+/* get the number of available slots (max_size - size) */ \
+unsigned int CBUFFER(_space_available)(CBUFFER() _q); \
+ \
+/* is buffer full? */ \
+int CBUFFER(_is_full)(CBUFFER() _q); \
+ \
+/* write a single sample into the buffer */ \
+/* _q : circular buffer object */ \
+/* _v : input sample */ \
+void CBUFFER(_push)(CBUFFER() _q, \
+ T _v); \
+ \
+/* write samples to the buffer */ \
+/* _q : circular buffer object */ \
+/* _v : output array */ \
+/* _n : number of samples to write */ \
+void CBUFFER(_write)(CBUFFER() _q, \
+ T * _v, \
+ unsigned int _n); \
+ \
+/* remove and return a single element from the buffer */ \
+/* _q : circular buffer object */ \
+/* _v : pointer to sample output */ \
+void CBUFFER(_pop)(CBUFFER() _q, \
+ T * _v); \
+ \
+/* read buffer contents */ \
+/* _q : circular buffer object */ \
+/* _num_requested : number of elements requested */ \
+/* _v : output pointer */ \
+/* _nr : number of elements referenced by _v */ \
+void CBUFFER(_read)(CBUFFER() _q, \
+ unsigned int _num_requested, \
+ T ** _v, \
+ unsigned int * _num_read); \
+ \
+/* release _n samples from the buffer */ \
+void CBUFFER(_release)(CBUFFER() _q, \
+ unsigned int _n); \
+
+// Define buffer APIs
+LIQUID_CBUFFER_DEFINE_API(CBUFFER_MANGLE_FLOAT, float)
+LIQUID_CBUFFER_DEFINE_API(CBUFFER_MANGLE_CFLOAT, liquid_float_complex)
+
+
+
+// Windowing functions
+#define WINDOW_MANGLE_FLOAT(name) LIQUID_CONCAT(windowf, name)
+#define WINDOW_MANGLE_CFLOAT(name) LIQUID_CONCAT(windowcf, name)
+
+// large macro
+// WINDOW : name-mangling macro
+// T : data type
+#define LIQUID_WINDOW_DEFINE_API(WINDOW,T) \
+ \
+typedef struct WINDOW(_s) * WINDOW(); \
+ \
+/* create window buffer object of length _n */ \
+WINDOW() WINDOW(_create)(unsigned int _n); \
+ \
+/* recreate window buffer object with new length */ \
+/* _q : old window object */ \
+/* _n : new window length */ \
+WINDOW() WINDOW(_recreate)(WINDOW() _q, unsigned int _n); \
+ \
+/* destroy window object, freeing all internally memory */ \
+void WINDOW(_destroy)(WINDOW() _q); \
+ \
+/* print window object to stdout */ \
+void WINDOW(_print)(WINDOW() _q); \
+ \
+/* print window object to stdout (with extra information) */ \
+void WINDOW(_debug_print)(WINDOW() _q); \
+ \
+/* clear/reset window object (initialize to zeros) */ \
+void WINDOW(_clear)(WINDOW() _q); \
+ \
+/* read window buffer contents */ \
+/* _q : window object */ \
+/* _v : output pointer (set to internal array) */ \
+void WINDOW(_read)(WINDOW() _q, T ** _v); \
+ \
+/* index single element in buffer at a particular index */ \
+/* _q : window object */ \
+/* _i : index of element to read */ \
+/* _v : output value pointer */ \
+void WINDOW(_index)(WINDOW() _q, \
+ unsigned int _i, \
+ T * _v); \
+ \
+/* push single element onto window buffer */ \
+/* _q : window object */ \
+/* _v : single input element */ \
+void WINDOW(_push)(WINDOW() _q, \
+ T _v); \
+ \
+/* write array of elements onto window buffer */ \
+/* _q : window object */ \
+/* _v : input array of values to write */ \
+/* _n : number of input values to write */ \
+void WINDOW(_write)(WINDOW() _q, \
+ T * _v, \
+ unsigned int _n); \
+
+// Define window APIs
+LIQUID_WINDOW_DEFINE_API(WINDOW_MANGLE_FLOAT, float)
+LIQUID_WINDOW_DEFINE_API(WINDOW_MANGLE_CFLOAT, liquid_float_complex)
+//LIQUID_WINDOW_DEFINE_API(WINDOW_MANGLE_UINT, unsigned int)
+
+
+// wdelay functions : windowed-delay
+// Implements an efficient z^-k delay with minimal memory
+#define WDELAY_MANGLE_FLOAT(name) LIQUID_CONCAT(wdelayf, name)
+#define WDELAY_MANGLE_CFLOAT(name) LIQUID_CONCAT(wdelaycf, name)
+#define WDELAY_MANGLE_UINT(name) LIQUID_CONCAT(wdelayui, name)
+
+// large macro
+// WDELAY : name-mangling macro
+// T : data type
+#define LIQUID_WDELAY_DEFINE_API(WDELAY,T) \
+typedef struct WDELAY(_s) * WDELAY(); \
+ \
+/* create delay buffer object with '_delay' samples */ \
+WDELAY() WDELAY(_create)(unsigned int _delay); \
+ \
+/* re-create delay buffer object with '_delay' samples */ \
+/* _q : old delay buffer object */ \
+/* _delay : delay for new object */ \
+WDELAY() WDELAY(_recreate)(WDELAY() _q, \
+ unsigned int _delay); \
+ \
+/* destroy delay buffer object, freeing internal memory */ \
+void WDELAY(_destroy)(WDELAY() _q); \
+ \
+/* print delay buffer object's state to stdout */ \
+void WDELAY(_print)(WDELAY() _q); \
+ \
+/* clear/reset state of object */ \
+void WDELAY(_clear)(WDELAY() _q); \
+ \
+/* read delayed sample from delay buffer object */ \
+/* _q : delay buffer object */ \
+/* _v : value of delayed element */ \
+void WDELAY(_read)(WDELAY() _q, \
+ T * _v); \
+ \
+/* push new sample into delay buffer object */ \
+/* _q : delay buffer object */ \
+/* _v : new value to be added to buffer */ \
+void WDELAY(_push)(WDELAY() _q, \
+ T _v); \
+
+// Define wdelay APIs
+LIQUID_WDELAY_DEFINE_API(WDELAY_MANGLE_FLOAT, float)
+LIQUID_WDELAY_DEFINE_API(WDELAY_MANGLE_CFLOAT, liquid_float_complex)
+//LIQUID_WDELAY_DEFINE_API(WDELAY_MANGLE_UINT, unsigned int)
+
+
+
+//
+// MODULE : dotprod (vector dot product)
+//
+
+#define DOTPROD_MANGLE_RRRF(name) LIQUID_CONCAT(dotprod_rrrf,name)
+#define DOTPROD_MANGLE_CCCF(name) LIQUID_CONCAT(dotprod_cccf,name)
+#define DOTPROD_MANGLE_CRCF(name) LIQUID_CONCAT(dotprod_crcf,name)
+
+// large macro
+// DOTPROD : name-mangling macro
+// TO : output data type
+// TC : coefficients data type
+// TI : input data type
+#define LIQUID_DOTPROD_DEFINE_API(DOTPROD,TO,TC,TI) \
+ \
+/* run dot product without creating object [unrolled loop] */ \
+/* _v : coefficients array [size: _n x 1] */ \
+/* _x : input array [size: _n x 1] */ \
+/* _n : dotprod length, _n > 0 */ \
+/* _y : output sample pointer */ \
+void DOTPROD(_run)( TC *_v, TI *_x, unsigned int _n, TO *_y); \
+void DOTPROD(_run4)(TC *_v, TI *_x, unsigned int _n, TO *_y); \
+ \
+typedef struct DOTPROD(_s) * DOTPROD(); \
+ \
+/* create dot product object */ \
+/* _v : coefficients array [size: _n x 1] */ \
+/* _n : dotprod length, _n > 0 */ \
+DOTPROD() DOTPROD(_create)(TC * _v, \
+ unsigned int _n); \
+ \
+/* re-create dot product object */ \
+/* _q : old dotprod object */ \
+/* _v : coefficients array [size: _n x 1] */ \
+/* _n : dotprod length, _n > 0 */ \
+DOTPROD() DOTPROD(_recreate)(DOTPROD() _q, \
+ TC * _v, \
+ unsigned int _n); \
+ \
+/* destroy dotprod object, freeing all internal memory */ \
+void DOTPROD(_destroy)(DOTPROD() _q); \
+ \
+/* print dotprod object internals to standard output */ \
+void DOTPROD(_print)(DOTPROD() _q); \
+ \
+/* execute dot product */ \
+/* _q : dotprod object */ \
+/* _x : input array [size: _n x 1] */ \
+/* _y : output sample pointer */ \
+void DOTPROD(_execute)(DOTPROD() _q, \
+ TI * _x, \
+ TO * _y); \
+
+LIQUID_DOTPROD_DEFINE_API(DOTPROD_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_DOTPROD_DEFINE_API(DOTPROD_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+LIQUID_DOTPROD_DEFINE_API(DOTPROD_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+//
+// sum squared methods
+//
+
+float liquid_sumsqf(float * _v,
+ unsigned int _n);
+
+float liquid_sumsqcf(liquid_float_complex * _v,
+ unsigned int _n);
+
+
+//
+// MODULE : equalization
+//
+
+// least mean-squares (LMS)
+#define EQLMS_MANGLE_RRRF(name) LIQUID_CONCAT(eqlms_rrrf,name)
+#define EQLMS_MANGLE_CCCF(name) LIQUID_CONCAT(eqlms_cccf,name)
+
+// large macro
+// EQLMS : name-mangling macro
+// T : data type
+#define LIQUID_EQLMS_DEFINE_API(EQLMS,T) \
+typedef struct EQLMS(_s) * EQLMS(); \
+ \
+/* create LMS EQ initialized with external coefficients */ \
+/* _h : filter coefficients (NULL for {1,0,0...}) */ \
+/* _p : filter length */ \
+EQLMS() EQLMS(_create)(T * _h, \
+ unsigned int _p); \
+ \
+/* create LMS EQ initialized with square-root Nyquist */ \
+/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
+/* _k : samples/symbol */ \
+/* _m : filter delay (symbols) */ \
+/* _beta : rolloff factor (0 < beta <= 1) */ \
+/* _dt : fractional sample delay */ \
+EQLMS() EQLMS(_create_rnyquist)(int _type, \
+ unsigned int _k, \
+ unsigned int _m, \
+ float _beta, \
+ float _dt); \
+ \
+/* re-create EQ initialized with external coefficients */ \
+/* _q : equalizer object */ \
+/* _h : filter coefficients (NULL for {1,0,0...}) */ \
+/* _p : filter length */ \
+EQLMS() EQLMS(_recreate)(EQLMS() _q, \
+ T * _h, \
+ unsigned int _p); \
+ \
+/* destroy equalizer object, freeing all internal memory */ \
+void EQLMS(_destroy)(EQLMS() _q); \
+ \
+/* reset equalizer object, clearing internal state */ \
+void EQLMS(_reset)(EQLMS() _q); \
+ \
+/* print equalizer internal state */ \
+void EQLMS(_print)(EQLMS() _q); \
+ \
+/* get/set equalizer learning rate */ \
+float EQLMS(_get_bw)(EQLMS() _q); \
+void EQLMS(_set_bw)(EQLMS() _q, \
+ float _lambda); \
+ \
+/* push sample into equalizer internal buffer */ \
+void EQLMS(_push)(EQLMS() _q, \
+ T _x); \
+ \
+/* execute internal dot product and return result */ \
+/* _q : equalizer object */ \
+/* _y : output sample */ \
+void EQLMS(_execute)(EQLMS() _q, \
+ T * _y); \
+ \
+/* step through one cycle of equalizer training */ \
+/* _q : equalizer object */ \
+/* _d : desired output */ \
+/* _d_hat : actual output */ \
+void EQLMS(_step)(EQLMS() _q, \
+ T _d, \
+ T _d_hat); \
+ \
+/* get equalizer's internal coefficients */ \
+/* _q : equalizer object */ \
+/* _w : weights [size: _p x 1] */ \
+void EQLMS(_get_weights)(EQLMS() _q, \
+ T * _w); \
+ \
+/* train equalizer object on group of samples */ \
+/* _q : equalizer object */ \
+/* _w : input/output weights [size: _p x 1] */ \
+/* _x : received sample vector [size: _n x 1] */ \
+/* _d : desired output vector [size: _n x 1] */ \
+/* _n : input, output vector length */ \
+void EQLMS(_train)(EQLMS() _q, \
+ T * _w, \
+ T * _x, \
+ T * _d, \
+ unsigned int _n); \
+
+LIQUID_EQLMS_DEFINE_API(EQLMS_MANGLE_RRRF, float);
+LIQUID_EQLMS_DEFINE_API(EQLMS_MANGLE_CCCF, liquid_float_complex);
+
+
+// recursive least-squares (RLS)
+#define EQRLS_MANGLE_RRRF(name) LIQUID_CONCAT(eqrls_rrrf,name)
+#define EQRLS_MANGLE_CCCF(name) LIQUID_CONCAT(eqrls_cccf,name)
+
+// large macro
+// EQRLS : name-mangling macro
+// T : data type
+#define LIQUID_EQRLS_DEFINE_API(EQRLS,T) \
+typedef struct EQRLS(_s) * EQRLS(); \
+ \
+/* create RLS EQ initialized with external coefficients */ \
+/* _h : filter coefficients (NULL for {1,0,0...}) */ \
+/* _p : filter length */ \
+EQRLS() EQRLS(_create)(T * _h, \
+ unsigned int _p); \
+ \
+/* re-create RLS EQ initialized with external coefficients */ \
+/* _q : initial equalizer object */ \
+/* _h : filter coefficients (NULL for {1,0,0...}) */ \
+/* _p : filter length */ \
+EQRLS() EQRLS(_recreate)(EQRLS() _q, \
+ T * _h, \
+ unsigned int _p); \
+ \
+/* destroy equalizer object, freeing all internal memory */ \
+void EQRLS(_destroy)(EQRLS() _q); \
+ \
+/* print equalizer internal state */ \
+void EQRLS(_print)(EQRLS() _q); \
+ \
+/* reset equalizer object, clearing internal state */ \
+void EQRLS(_reset)(EQRLS() _q); \
+ \
+/* get/set equalizer learning rate */ \
+float EQRLS(_get_bw)(EQRLS() _q); \
+void EQRLS(_set_bw)(EQRLS() _q, \
+ float _mu); \
+ \
+/* push sample into equalizer internal buffer */ \
+void EQRLS(_push)(EQRLS() _q, T _x); \
+ \
+/* execute internal dot product and return result */ \
+/* _q : equalizer object */ \
+/* _y : output sample */ \
+void EQRLS(_execute)(EQRLS() _q, T * _y); \
+ \
+/* step through one cycle of equalizer training */ \
+/* _q : equalizer object */ \
+/* _d : desired output */ \
+/* _d_hat : actual output */ \
+void EQRLS(_step)(EQRLS() _q, T _d, T _d_hat); \
+ \
+/* retrieve internal filter coefficients */ \
+/* _q : equalizer object */ \
+/* _w : weights [size: _p x 1] */ \
+void EQRLS(_get_weights)(EQRLS() _q, \
+ T * _w); \
+ \
+/* train equalizer object on group of samples */ \
+/* _q : equalizer object */ \
+/* _w : input/output weights [size: _p x 1] */ \
+/* _x : received sample vector [size: _n x 1] */ \
+/* _d : desired output vector [size: _n x 1] */ \
+/* _n : input, output vector length */ \
+void EQRLS(_train)(EQRLS() _q, \
+ T * _w, \
+ T * _x, \
+ T * _d, \
+ unsigned int _n);
+
+LIQUID_EQRLS_DEFINE_API(EQRLS_MANGLE_RRRF, float);
+LIQUID_EQRLS_DEFINE_API(EQRLS_MANGLE_CCCF, liquid_float_complex);
+
+
+
+
+//
+// MODULE : fec (forward error-correction)
+//
+
+// soft bit values
+#define LIQUID_SOFTBIT_0 (0)
+#define LIQUID_SOFTBIT_1 (255)
+#define LIQUID_SOFTBIT_ERASURE (127)
+
+// available CRC schemes
+#define LIQUID_CRC_NUM_SCHEMES 7
+typedef enum {
+ LIQUID_CRC_UNKNOWN=0, // unknown/unavailable CRC scheme
+ LIQUID_CRC_NONE, // no error-detection
+ LIQUID_CRC_CHECKSUM, // 8-bit checksum
+ LIQUID_CRC_8, // 8-bit CRC
+ LIQUID_CRC_16, // 16-bit CRC
+ LIQUID_CRC_24, // 24-bit CRC
+ LIQUID_CRC_32 // 32-bit CRC
+} crc_scheme;
+
+// pretty names for crc schemes
+extern const char * crc_scheme_str[LIQUID_CRC_NUM_SCHEMES][2];
+
+// Print compact list of existing and available CRC schemes
+void liquid_print_crc_schemes();
+
+// returns crc_scheme based on input string
+crc_scheme liquid_getopt_str2crc(const char * _str);
+
+// get length of CRC (bytes)
+unsigned int crc_get_length(crc_scheme _scheme);
+
+// generate error-detection key
+//
+// _scheme : error-detection scheme
+// _msg : input data message, [size: _n x 1]
+// _n : input data message size
+unsigned int crc_generate_key(crc_scheme _scheme,
+ unsigned char * _msg,
+ unsigned int _n);
+
+// validate message using error-detection key
+//
+// _scheme : error-detection scheme
+// _msg : input data message, [size: _n x 1]
+// _n : input data message size
+// _key : error-detection key
+int crc_validate_message(crc_scheme _scheme,
+ unsigned char * _msg,
+ unsigned int _n,
+ unsigned int _key);
+
+
+// available FEC schemes
+#define LIQUID_FEC_NUM_SCHEMES 28
+typedef enum {
+ LIQUID_FEC_UNKNOWN=0, // unknown/unsupported scheme
+ LIQUID_FEC_NONE, // no error-correction
+ LIQUID_FEC_REP3, // simple repeat code, r1/3
+ LIQUID_FEC_REP5, // simple repeat code, r1/5
+ LIQUID_FEC_HAMMING74, // Hamming (7,4) block code, r1/2 (really 4/7)
+ LIQUID_FEC_HAMMING84, // Hamming (7,4) with extra parity bit, r1/2
+ LIQUID_FEC_HAMMING128, // Hamming (12,8) block code, r2/3
+
+ LIQUID_FEC_GOLAY2412, // Golay (24,12) block code, r1/2
+ LIQUID_FEC_SECDED2216, // SEC-DED (22,16) block code, r8/11
+ LIQUID_FEC_SECDED3932, // SEC-DED (39,32) block code
+ LIQUID_FEC_SECDED7264, // SEC-DED (72,64) block code, r8/9
+
+ // codecs not defined internally (see http://www.ka9q.net/code/fec/)
+ LIQUID_FEC_CONV_V27, // r1/2, K=7, dfree=10
+ LIQUID_FEC_CONV_V29, // r1/2, K=9, dfree=12
+ LIQUID_FEC_CONV_V39, // r1/3, K=9, dfree=18
+ LIQUID_FEC_CONV_V615, // r1/6, K=15, dfree<=57 (Heller 1968)
+
+ // punctured (perforated) codes
+ LIQUID_FEC_CONV_V27P23, // r2/3, K=7, dfree=6
+ LIQUID_FEC_CONV_V27P34, // r3/4, K=7, dfree=5
+ LIQUID_FEC_CONV_V27P45, // r4/5, K=7, dfree=4
+ LIQUID_FEC_CONV_V27P56, // r5/6, K=7, dfree=4
+ LIQUID_FEC_CONV_V27P67, // r6/7, K=7, dfree=3
+ LIQUID_FEC_CONV_V27P78, // r7/8, K=7, dfree=3
+
+ LIQUID_FEC_CONV_V29P23, // r2/3, K=9, dfree=7
+ LIQUID_FEC_CONV_V29P34, // r3/4, K=9, dfree=6
+ LIQUID_FEC_CONV_V29P45, // r4/5, K=9, dfree=5
+ LIQUID_FEC_CONV_V29P56, // r5/6, K=9, dfree=5
+ LIQUID_FEC_CONV_V29P67, // r6/7, K=9, dfree=4
+ LIQUID_FEC_CONV_V29P78, // r7/8, K=9, dfree=4
+
+ // Reed-Solomon codes
+ LIQUID_FEC_RS_M8 // m=8, n=255, k=223
+} fec_scheme;
+
+// pretty names for fec schemes
+extern const char * fec_scheme_str[LIQUID_FEC_NUM_SCHEMES][2];
+
+// Print compact list of existing and available FEC schemes
+void liquid_print_fec_schemes();
+
+// returns fec_scheme based on input string
+fec_scheme liquid_getopt_str2fec(const char * _str);
+
+// fec object (pointer to fec structure)
+typedef struct fec_s * fec;
+
+// return the encoded message length using a particular error-
+// correction scheme (object-independent method)
+// _scheme : forward error-correction scheme
+// _msg_len : raw, uncoded message length
+unsigned int fec_get_enc_msg_length(fec_scheme _scheme,
+ unsigned int _msg_len);
+
+// get the theoretical rate of a particular forward error-
+// correction scheme (object-independent method)
+float fec_get_rate(fec_scheme _scheme);
+
+// create a fec object of a particular scheme
+// _scheme : error-correction scheme
+// _opts : (ignored)
+fec fec_create(fec_scheme _scheme,
+ void *_opts);
+
+// recreate fec object
+// _q : old fec object
+// _scheme : new error-correction scheme
+// _opts : (ignored)
+fec fec_recreate(fec _q,
+ fec_scheme _scheme,
+ void *_opts);
+
+// destroy fec object
+void fec_destroy(fec _q);
+
+// print fec object internals
+void fec_print(fec _q);
+
+// encode a block of data using a fec scheme
+// _q : fec object
+// _dec_msg_len : decoded message length
+// _msg_dec : decoded message
+// _msg_enc : encoded message
+void fec_encode(fec _q,
+ unsigned int _dec_msg_len,
+ unsigned char * _msg_dec,
+ unsigned char * _msg_enc);
+
+// decode a block of data using a fec scheme
+// _q : fec object
+// _dec_msg_len : decoded message length
+// _msg_enc : encoded message
+// _msg_dec : decoded message
+void fec_decode(fec _q,
+ unsigned int _dec_msg_len,
+ unsigned char * _msg_enc,
+ unsigned char * _msg_dec);
+
+// decode a block of data using a fec scheme (soft decision)
+// _q : fec object
+// _dec_msg_len : decoded message length
+// _msg_enc : encoded message (soft bits)
+// _msg_dec : decoded message
+void fec_decode_soft(fec _q,
+ unsigned int _dec_msg_len,
+ unsigned char * _msg_enc,
+ unsigned char * _msg_dec);
+
+//
+// Packetizer
+//
+
+// computes the number of encoded bytes after packetizing
+//
+// _n : number of uncoded input bytes
+// _crc : error-detecting scheme
+// _fec0 : inner forward error-correction code
+// _fec1 : outer forward error-correction code
+unsigned int packetizer_compute_enc_msg_len(unsigned int _n,
+ int _crc,
+ int _fec0,
+ int _fec1);
+
+// computes the number of decoded bytes before packetizing
+//
+// _k : number of encoded bytes
+// _crc : error-detecting scheme
+// _fec0 : inner forward error-correction code
+// _fec1 : outer forward error-correction code
+unsigned int packetizer_compute_dec_msg_len(unsigned int _k,
+ int _crc,
+ int _fec0,
+ int _fec1);
+
+typedef struct packetizer_s * packetizer;
+
+// create packetizer object
+//
+// _n : number of uncoded input bytes
+// _crc : error-detecting scheme
+// _fec0 : inner forward error-correction code
+// _fec1 : outer forward error-correction code
+packetizer packetizer_create(unsigned int _dec_msg_len,
+ int _crc,
+ int _fec0,
+ int _fec1);
+
+// re-create packetizer object
+//
+// _p : initialz packetizer object
+// _n : number of uncoded input bytes
+// _crc : error-detecting scheme
+// _fec0 : inner forward error-correction code
+// _fec1 : outer forward error-correction code
+packetizer packetizer_recreate(packetizer _p,
+ unsigned int _dec_msg_len,
+ int _crc,
+ int _fec0,
+ int _fec1);
+
+// destroy packetizer object
+void packetizer_destroy(packetizer _p);
+
+// print packetizer object internals
+void packetizer_print(packetizer _p);
+
+unsigned int packetizer_get_dec_msg_len(packetizer _p);
+unsigned int packetizer_get_enc_msg_len(packetizer _p);
+
+
+// packetizer_encode()
+//
+// Execute the packetizer on an input message
+//
+// _p : packetizer object
+// _msg : input message (uncoded bytes)
+// _pkt : encoded output message
+void packetizer_encode(packetizer _p,
+ unsigned char * _msg,
+ unsigned char * _pkt);
+
+// packetizer_decode()
+//
+// Execute the packetizer to decode an input message, return validity
+// check of resulting data
+//
+// _p : packetizer object
+// _pkt : input message (coded bytes)
+// _msg : decoded output message
+int packetizer_decode(packetizer _p,
+ unsigned char * _pkt,
+ unsigned char * _msg);
+
+// Execute the packetizer to decode an input message, return validity
+// check of resulting data
+//
+// _p : packetizer object
+// _pkt : input message (coded soft bits)
+// _msg : decoded output message
+int packetizer_decode_soft(packetizer _p,
+ unsigned char * _pkt,
+ unsigned char * _msg);
+
+
+//
+// interleaver
+//
+typedef struct interleaver_s * interleaver;
+
+// create interleaver
+// _n : number of bytes
+interleaver interleaver_create(unsigned int _n);
+
+// destroy interleaver object
+void interleaver_destroy(interleaver _q);
+
+// print interleaver object internals
+void interleaver_print(interleaver _q);
+
+// set depth (number of internal iterations)
+// _q : interleaver object
+// _depth : depth
+void interleaver_set_depth(interleaver _q,
+ unsigned int _depth);
+
+// execute forward interleaver (encoder)
+// _q : interleaver object
+// _msg_dec : decoded (un-interleaved) message
+// _msg_enc : encoded (interleaved) message
+void interleaver_encode(interleaver _q,
+ unsigned char * _msg_dec,
+ unsigned char * _msg_enc);
+
+// execute forward interleaver (encoder) on soft bits
+// _q : interleaver object
+// _msg_dec : decoded (un-interleaved) message
+// _msg_enc : encoded (interleaved) message
+void interleaver_encode_soft(interleaver _q,
+ unsigned char * _msg_dec,
+ unsigned char * _msg_enc);
+
+// execute reverse interleaver (decoder)
+// _q : interleaver object
+// _msg_enc : encoded (interleaved) message
+// _msg_dec : decoded (un-interleaved) message
+void interleaver_decode(interleaver _q,
+ unsigned char * _msg_enc,
+ unsigned char * _msg_dec);
+
+// execute reverse interleaver (decoder) on soft bits
+// _q : interleaver object
+// _msg_enc : encoded (interleaved) message
+// _msg_dec : decoded (un-interleaved) message
+void interleaver_decode_soft(interleaver _q,
+ unsigned char * _msg_enc,
+ unsigned char * _msg_dec);
+
+
+
+//
+// MODULE : fft (fast Fourier transform)
+//
+
+// type of transform
+typedef enum {
+ LIQUID_FFT_UNKNOWN = 0, // unknown transform type
+
+ // regular complex one-dimensional transforms
+ LIQUID_FFT_FORWARD = +1, // complex one-dimensional FFT
+ LIQUID_FFT_BACKWARD = -1, // complex one-dimensional inverse FFT
+
+ // discrete cosine transforms
+ LIQUID_FFT_REDFT00 = 10, // real one-dimensional DCT-I
+ LIQUID_FFT_REDFT10 = 11, // real one-dimensional DCT-II
+ LIQUID_FFT_REDFT01 = 12, // real one-dimensional DCT-III
+ LIQUID_FFT_REDFT11 = 13, // real one-dimensional DCT-IV
+
+ // discrete sine transforms
+ LIQUID_FFT_RODFT00 = 20, // real one-dimensional DST-I
+ LIQUID_FFT_RODFT10 = 21, // real one-dimensional DST-II
+ LIQUID_FFT_RODFT01 = 22, // real one-dimensional DST-III
+ LIQUID_FFT_RODFT11 = 23, // real one-dimensional DST-IV
+
+ // modified discrete cosine transform
+ LIQUID_FFT_MDCT = 30, // MDCT
+ LIQUID_FFT_IMDCT = 31, // IMDCT
+} liquid_fft_type;
+
+#define LIQUID_FFT_MANGLE_FLOAT(name) LIQUID_CONCAT(fft,name)
+
+// Macro : FFT
+// FFT : name-mangling macro
+// T : primitive data type
+// TC : primitive data type (complex)
+#define LIQUID_FFT_DEFINE_API(FFT,T,TC) \
+ \
+typedef struct FFT(plan_s) * FFT(plan); \
+ \
+/* create regular complex one-dimensional transform */ \
+/* _n : transform size */ \
+/* _x : pointer to input array [size: _n x 1] */ \
+/* _y : pointer to output array [size: _n x 1] */ \
+/* _dir : direction (e.g. LIQUID_FFT_FORWARD) */ \
+/* _flags : options, optimization */ \
+FFT(plan) FFT(_create_plan)(unsigned int _n, \
+ TC * _x, \
+ TC * _y, \
+ int _dir, \
+ int _flags); \
+ \
+/* create real-to-real transform */ \
+/* _n : transform size */ \
+/* _x : pointer to input array [size: _n x 1] */ \
+/* _y : pointer to output array [size: _n x 1] */ \
+/* _type : transform type (e.g. LIQUID_FFT_REDFT00) */ \
+/* _flags : options, optimization */ \
+FFT(plan) FFT(_create_plan_r2r_1d)(unsigned int _n, \
+ T * _x, \
+ T * _y, \
+ int _type, \
+ int _flags); \
+ \
+/* destroy transform */ \
+void FFT(_destroy_plan)(FFT(plan) _p); \
+ \
+/* print transform plan and internal strategy */ \
+void FFT(_print_plan)(FFT(plan) _p); \
+ \
+/* run the transform */ \
+void FFT(_execute)(FFT(plan) _p); \
+ \
+/* object-independent methods */ \
+ \
+/* perform n-point FFT allocating plan internally */ \
+/* _nfft : fft size */ \
+/* _x : input array [size: _nfft x 1] */ \
+/* _y : output array [size: _nfft x 1] */ \
+/* _dir : fft direction: LIQUID_FFT_{FORWARD,BACKWARD} */ \
+/* _flags : fft flags */ \
+void FFT(_run)(unsigned int _n, \
+ TC * _x, \
+ TC * _y, \
+ int _dir, \
+ int _flags); \
+ \
+/* perform n-point real FFT allocating plan internally */ \
+/* _nfft : fft size */ \
+/* _x : input array [size: _nfft x 1] */ \
+/* _y : output array [size: _nfft x 1] */ \
+/* _type : fft type, e.g. LIQUID_FFT_REDFT10 */ \
+/* _flags : fft flags */ \
+void FFT(_r2r_1d_run)(unsigned int _n, \
+ T * _x, \
+ T * _y, \
+ int _type, \
+ int _flags); \
+ \
+/* perform _n-point fft shift */ \
+void FFT(_shift)(TC * _x, \
+ unsigned int _n); \
+
+
+LIQUID_FFT_DEFINE_API(LIQUID_FFT_MANGLE_FLOAT,float,liquid_float_complex)
+
+// antiquated fft methods
+// FFT(plan) FFT(_create_plan_mdct)(unsigned int _n,
+// T * _x,
+// T * _y,
+// int _kind,
+// int _flags);
+
+
+//
+// spectral periodogram
+//
+
+#define LIQUID_SPGRAM_MANGLE_CFLOAT(name) LIQUID_CONCAT(spgramcf,name)
+#define LIQUID_SPGRAM_MANGLE_FLOAT(name) LIQUID_CONCAT(spgramf, name)
+
+// Macro : SPGRAM
+// SPGRAM : name-mangling macro
+// T : primitive data type
+// TC : primitive data type (complex)
+// TI : primitive data type (input)
+#define LIQUID_SPGRAM_DEFINE_API(SPGRAM,T,TC,TI) \
+ \
+typedef struct SPGRAM(_s) * SPGRAM(); \
+ \
+/* create spgram object */ \
+/* _nfft : FFT size */ \
+/* _window : window [size: _window_len x 1] */ \
+/* _window_len : window length */ \
+SPGRAM() SPGRAM(_create)(unsigned int _nfft, \
+ float * _window, \
+ unsigned int _window_len); \
+ \
+/* create spgram object with Kaiser-Bessel window */ \
+/* _nfft : FFT size */ \
+/* _window_len : window length */ \
+/* _beta : Kaiser-Bessel parameter (_beta > 0) */ \
+SPGRAM() SPGRAM(_create_kaiser)(unsigned int _nfft, \
+ unsigned int _window_len, \
+ float _beta); \
+ \
+/* destroy spgram object */ \
+void SPGRAM(_destroy)(SPGRAM() _q); \
+ \
+/* resets the internal state of the spgram object */ \
+void SPGRAM(_reset)(SPGRAM() _q); \
+ \
+/* push samples into spgram object */ \
+/* _q : spgram object */ \
+/* _x : input buffer [size: _n x 1] */ \
+/* _n : input buffer length */ \
+void SPGRAM(_push)(SPGRAM() _q, \
+ TI * _x, \
+ unsigned int _n); \
+ \
+/* compute spectral periodogram output from current buffer */ \
+/* contents */ \
+/* _q : spgram object */ \
+/* _X : output complex spectrum [size: _nfft x 1] */ \
+void SPGRAM(_execute)(SPGRAM() _q, \
+ TC * _X); \
+ \
+/* accumulate power spectral density */ \
+/* _q : spgram object */ \
+/* _x : input buffer [size: _n x 1] */ \
+/* _n : input buffer length */ \
+void SPGRAM(_accumulate_psd)(SPGRAM() _q, \
+ TI * _x, \
+ unsigned int _n); \
+ \
+/* write accumulated psd */ \
+/* _q : spgram object */ \
+/* _x : input buffer [size: _n x 1] */ \
+/* _n : input buffer length [size: _nfft x 1] */ \
+void SPGRAM(_write_accumulation)(SPGRAM() _q, \
+ T * _x); \
+ \
+/* estimate spectrum on input signal */ \
+/* _q : spgram object */ \
+/* _x : input signal [size: _n x 1] */ \
+/* _n : input signal length */ \
+/* _psd : output spectrum, [size: _nfft x 1] */ \
+void SPGRAM(_estimate_psd)(SPGRAM() _q, \
+ TI * _x, \
+ unsigned int _n, \
+ T * _psd); \
+
+LIQUID_SPGRAM_DEFINE_API(LIQUID_SPGRAM_MANGLE_CFLOAT,
+ float,
+ liquid_float_complex,
+ liquid_float_complex)
+
+LIQUID_SPGRAM_DEFINE_API(LIQUID_SPGRAM_MANGLE_FLOAT,
+ float,
+ liquid_float_complex,
+ float)
+
+
+// ascii spectrogram
+typedef struct asgram_s * asgram;
+
+// create asgram object
+// _nfft : FFT size
+asgram asgram_create(unsigned int _nfft);
+void asgram_destroy(asgram _q);
+void asgram_reset(asgram _q);
+void asgram_set_scale(asgram _q, float _offset, float _scale);
+
+// push samples into asgram object
+// _q : asgram object
+// _x : input buffer [size: _n x 1]
+// _n : input buffer length
+void asgram_push(asgram _q,
+ liquid_float_complex * _x,
+ unsigned int _n);
+
+// execute asgram
+// _q : asgram object
+// _ascii : ASCII character output buffer [size: _nfft x 1]
+// _peakval : peak PSD value [dB]
+// _peakfreq : normalized frequency of peak PSD value
+void asgram_execute(asgram _q,
+ char * _ascii,
+ float * _peakval,
+ float * _peakfreq);
+
+//
+// MODULE : filter
+//
+
+//
+// firdes: finite impulse response filter design
+//
+
+// prototypes
+typedef enum {
+ LIQUID_FIRFILT_UNKNOWN=0, // unknown filter type
+
+ // Nyquist filter prototypes
+ LIQUID_FIRFILT_KAISER, // Nyquist Kaiser filter
+ LIQUID_FIRFILT_PM, // Parks-McClellan filter
+ LIQUID_FIRFILT_RCOS, // raised-cosine filter
+ LIQUID_FIRFILT_FEXP, // flipped exponential
+ LIQUID_FIRFILT_FSECH, // flipped hyperbolic secant
+ LIQUID_FIRFILT_FARCSECH, // flipped arc-hyperbolic secant
+
+ // root-Nyquist filter prototypes
+ LIQUID_FIRFILT_ARKAISER, // root-Nyquist Kaiser (approximate optimum)
+ LIQUID_FIRFILT_RKAISER, // root-Nyquist Kaiser (true optimum)
+ LIQUID_FIRFILT_RRC, // root raised-cosine
+ LIQUID_FIRFILT_hM3, // harris-Moerder-3 filter
+ LIQUID_FIRFILT_GMSKTX, // GMSK transmit filter
+ LIQUID_FIRFILT_GMSKRX, // GMSK receive filter
+ LIQUID_FIRFILT_RFEXP, // flipped exponential
+ LIQUID_FIRFILT_RFSECH, // flipped hyperbolic secant
+ LIQUID_FIRFILT_RFARCSECH, // flipped arc-hyperbolic secant
+} liquid_firfilt_type;
+
+// returns filter type based on input string
+int liquid_getopt_str2firfilt(const char * _str);
+
+// estimate required filter length given
+// _df : transition bandwidth (0 < _b < 0.5)
+// _As : stop-band attenuation [dB], _As > 0
+unsigned int estimate_req_filter_len(float _df,
+ float _As);
+
+// estimate filter stop-band attenuation given
+// _df : transition bandwidth (0 < _b < 0.5)
+// _N : filter length
+float estimate_req_filter_As(float _df,
+ unsigned int _N);
+
+// estimate filter transition bandwidth given
+// _As : stop-band attenuation [dB], _As > 0
+// _N : filter length
+float estimate_req_filter_df(float _As,
+ unsigned int _N);
+
+
+// returns the Kaiser window beta factor give the filter's target
+// stop-band attenuation (As) [Vaidyanathan:1993]
+// _As : target filter's stop-band attenuation [dB], _As > 0
+float kaiser_beta_As(float _As);
+
+
+// Design Nyquist filter
+// _type : filter type (e.g. LIQUID_FIRFILT_RCOS)
+// _k : samples/symbol
+// _m : symbol delay
+// _beta : excess bandwidth factor, _beta in [0,1]
+// _dt : fractional sample delay
+// _h : output coefficient buffer (length: 2*k*m+1)
+void liquid_firdes_nyquist(liquid_firfilt_type _type,
+ unsigned int _k,
+ unsigned int _m,
+ float _beta,
+ float _dt,
+ float * _h);
+
+
+// Design FIR filter using Parks-McClellan algorithm
+
+// band type specifier
+typedef enum {
+ LIQUID_FIRDESPM_BANDPASS=0, // regular band-pass filter
+ LIQUID_FIRDESPM_DIFFERENTIATOR, // differentiating filter
+ LIQUID_FIRDESPM_HILBERT // Hilbert transform
+} liquid_firdespm_btype;
+
+// weighting type specifier
+typedef enum {
+ LIQUID_FIRDESPM_FLATWEIGHT=0, // flat weighting
+ LIQUID_FIRDESPM_EXPWEIGHT, // exponential weighting
+ LIQUID_FIRDESPM_LINWEIGHT, // linear weighting
+} liquid_firdespm_wtype;
+
+// run filter design (full life cycle of object)
+// _h_len : length of filter (number of taps)
+// _num_bands : number of frequency bands
+// _bands : band edges, f in [0,0.5], [size: _num_bands x 2]
+// _des : desired response [size: _num_bands x 1]
+// _weights : response weighting [size: _num_bands x 1]
+// _wtype : weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1]
+// _btype : band type (e.g. LIQUID_FIRDESPM_BANDPASS)
+// _h : output coefficients array [size: _h_len x 1]
+void firdespm_run(unsigned int _h_len,
+ unsigned int _num_bands,
+ float * _bands,
+ float * _des,
+ float * _weights,
+ liquid_firdespm_wtype * _wtype,
+ liquid_firdespm_btype _btype,
+ float * _h);
+
+// structured object
+typedef struct firdespm_s * firdespm;
+
+// create firdespm object
+// _h_len : length of filter (number of taps)
+// _num_bands : number of frequency bands
+// _bands : band edges, f in [0,0.5], [size: _num_bands x 2]
+// _des : desired response [size: _num_bands x 1]
+// _weights : response weighting [size: _num_bands x 1]
+// _wtype : weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1]
+// _btype : band type (e.g. LIQUID_FIRDESPM_BANDPASS)
+firdespm firdespm_create(unsigned int _h_len,
+ unsigned int _num_bands,
+ float * _bands,
+ float * _des,
+ float * _weights,
+ liquid_firdespm_wtype * _wtype,
+ liquid_firdespm_btype _btype);
+
+// destroy firdespm object
+void firdespm_destroy(firdespm _q);
+
+// print firdespm object internals
+void firdespm_print(firdespm _q);
+
+// execute filter design, storing result in _h
+void firdespm_execute(firdespm _q, float * _h);
+
+
+// Design FIR using kaiser window
+// _n : filter length, _n > 0
+// _fc : cutoff frequency, 0 < _fc < 0.5
+// _As : stop-band attenuation [dB], _As > 0
+// _mu : fractional sample offset, -0.5 < _mu < 0.5
+// _h : output coefficient buffer, [size: _n x 1]
+void liquid_firdes_kaiser(unsigned int _n,
+ float _fc,
+ float _As,
+ float _mu,
+ float *_h);
+
+// Design FIR doppler filter
+// _n : filter length
+// _fd : normalized doppler frequency (0 < _fd < 0.5)
+// _K : Rice fading factor (K >= 0)
+// _theta : LoS component angle of arrival
+// _h : output coefficient buffer
+void liquid_firdes_doppler(unsigned int _n,
+ float _fd,
+ float _K,
+ float _theta,
+ float *_h);
+
+
+// Design Nyquist raised-cosine filter
+// _k : samples/symbol
+// _m : symbol delay
+// _beta : rolloff factor (0 < beta <= 1)
+// _dt : fractional sample delay
+// _h : output coefficient buffer (length: 2*k*m+1)
+void liquid_firdes_rcos(unsigned int _k,
+ unsigned int _m,
+ float _beta,
+ float _dt,
+ float * _h);
+
+// Design root-Nyquist filter
+// _type : filter type (e.g. LIQUID_FIRFILT_RRC)
+// _k : samples/symbol, _k > 1
+// _m : symbol delay, _m > 0
+// _beta : excess bandwidth factor, _beta in [0,1)
+// _dt : fractional sample delay, _dt in [-1,1]
+// _h : output coefficient buffer (length: 2*_k*_m+1)
+void liquid_firdes_rnyquist(liquid_firfilt_type _type,
+ unsigned int _k,
+ unsigned int _m,
+ float _beta,
+ float _dt,
+ float * _h);
+
+// Design root-Nyquist raised-cosine filter
+void liquid_firdes_rrcos(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+
+// Design root-Nyquist Kaiser filter
+void liquid_firdes_rkaiser(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+
+// Design (approximate) root-Nyquist Kaiser filter
+void liquid_firdes_arkaiser(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+
+// Design root-Nyquist harris-Moerder filter
+void liquid_firdes_hM3(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+
+// Design GMSK transmit and receive filters
+void liquid_firdes_gmsktx(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+void liquid_firdes_gmskrx(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+
+// Design flipped exponential Nyquist/root-Nyquist filters
+void liquid_firdes_fexp( unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+void liquid_firdes_rfexp(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+
+// Design flipped hyperbolic secand Nyquist/root-Nyquist filters
+void liquid_firdes_fsech( unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+void liquid_firdes_rfsech(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+
+// Design flipped arc-hyperbolic secand Nyquist/root-Nyquist filters
+void liquid_firdes_farcsech( unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+void liquid_firdes_rfarcsech(unsigned int _k, unsigned int _m, float _beta, float _dt, float * _h);
+
+// Compute group delay for an FIR filter
+// _h : filter coefficients array
+// _n : filter length
+// _fc : frequency at which delay is evaluated (-0.5 < _fc < 0.5)
+float fir_group_delay(float * _h,
+ unsigned int _n,
+ float _fc);
+
+// Compute group delay for an IIR filter
+// _b : filter numerator coefficients
+// _nb : filter numerator length
+// _a : filter denominator coefficients
+// _na : filter denominator length
+// _fc : frequency at which delay is evaluated (-0.5 < _fc < 0.5)
+float iir_group_delay(float * _b,
+ unsigned int _nb,
+ float * _a,
+ unsigned int _na,
+ float _fc);
+
+
+// liquid_filter_autocorr()
+//
+// Compute auto-correlation of filter at a specific lag.
+//
+// _h : filter coefficients [size: _h_len x 1]
+// _h_len : filter length
+// _lag : auto-correlation lag (samples)
+float liquid_filter_autocorr(float * _h,
+ unsigned int _h_len,
+ int _lag);
+
+// liquid_filter_crosscorr()
+//
+// Compute cross-correlation of two filters at a specific lag.
+//
+// _h : filter coefficients [size: _h_len]
+// _h_len : filter length
+// _g : filter coefficients [size: _g_len]
+// _g_len : filter length
+// _lag : cross-correlation lag (samples)
+float liquid_filter_crosscorr(float * _h,
+ unsigned int _h_len,
+ float * _g,
+ unsigned int _g_len,
+ int _lag);
+
+// liquid_filter_isi()
+//
+// Compute inter-symbol interference (ISI)--both RMS and
+// maximum--for the filter _h.
+//
+// _h : filter coefficients [size: 2*_k*_m+1 x 1]
+// _k : filter over-sampling rate (samples/symbol)
+// _m : filter delay (symbols)
+// _rms : output root mean-squared ISI
+// _max : maximum ISI
+void liquid_filter_isi(float * _h,
+ unsigned int _k,
+ unsigned int _m,
+ float * _rms,
+ float * _max);
+
+// Compute relative out-of-band energy
+//
+// _h : filter coefficients [size: _h_len x 1]
+// _h_len : filter length
+// _fc : analysis cut-off frequency
+// _nfft : fft size
+float liquid_filter_energy(float * _h,
+ unsigned int _h_len,
+ float _fc,
+ unsigned int _nfft);
+
+
+//
+// IIR filter design
+//
+
+// IIR filter design filter type
+typedef enum {
+ LIQUID_IIRDES_BUTTER=0,
+ LIQUID_IIRDES_CHEBY1,
+ LIQUID_IIRDES_CHEBY2,
+ LIQUID_IIRDES_ELLIP,
+ LIQUID_IIRDES_BESSEL
+} liquid_iirdes_filtertype;
+
+// IIR filter design band type
+typedef enum {
+ LIQUID_IIRDES_LOWPASS=0,
+ LIQUID_IIRDES_HIGHPASS,
+ LIQUID_IIRDES_BANDPASS,
+ LIQUID_IIRDES_BANDSTOP
+} liquid_iirdes_bandtype;
+
+// IIR filter design coefficients format
+typedef enum {
+ LIQUID_IIRDES_SOS=0,
+ LIQUID_IIRDES_TF
+} liquid_iirdes_format;
+
+// IIR filter design template
+// _ftype : filter type (e.g. LIQUID_IIRDES_BUTTER)
+// _btype : band type (e.g. LIQUID_IIRDES_BANDPASS)
+// _format : coefficients format (e.g. LIQUID_IIRDES_SOS)
+// _n : filter order
+// _fc : low-pass prototype cut-off frequency
+// _f0 : center frequency (band-pass, band-stop)
+// _Ap : pass-band ripple in dB
+// _As : stop-band ripple in dB
+// _B : numerator
+// _A : denominator
+void liquid_iirdes(liquid_iirdes_filtertype _ftype,
+ liquid_iirdes_bandtype _btype,
+ liquid_iirdes_format _format,
+ unsigned int _n,
+ float _fc,
+ float _f0,
+ float _Ap,
+ float _As,
+ float * _B,
+ float * _A);
+
+// compute analog zeros, poles, gain for specific filter types
+void butter_azpkf(unsigned int _n,
+ liquid_float_complex * _za,
+ liquid_float_complex * _pa,
+ liquid_float_complex * _ka);
+void cheby1_azpkf(unsigned int _n,
+ float _ep,
+ liquid_float_complex * _z,
+ liquid_float_complex * _p,
+ liquid_float_complex * _k);
+void cheby2_azpkf(unsigned int _n,
+ float _es,
+ liquid_float_complex * _z,
+ liquid_float_complex * _p,
+ liquid_float_complex * _k);
+void ellip_azpkf(unsigned int _n,
+ float _ep,
+ float _es,
+ liquid_float_complex * _z,
+ liquid_float_complex * _p,
+ liquid_float_complex * _k);
+void bessel_azpkf(unsigned int _n,
+ liquid_float_complex * _z,
+ liquid_float_complex * _p,
+ liquid_float_complex * _k);
+
+// compute frequency pre-warping factor
+float iirdes_freqprewarp(liquid_iirdes_bandtype _btype,
+ float _fc,
+ float _f0);
+
+// convert analog z/p/k form to discrete z/p/k form (bilinear z-transform)
+// _za : analog zeros [length: _nza]
+// _nza : number of analog zeros
+// _pa : analog poles [length: _npa]
+// _npa : number of analog poles
+// _m : frequency pre-warping factor
+// _zd : output digital zeros [length: _npa]
+// _pd : output digital poles [length: _npa]
+// _kd : output digital gain (should actually be real-valued)
+void bilinear_zpkf(liquid_float_complex * _za,
+ unsigned int _nza,
+ liquid_float_complex * _pa,
+ unsigned int _npa,
+ liquid_float_complex _ka,
+ float _m,
+ liquid_float_complex * _zd,
+ liquid_float_complex * _pd,
+ liquid_float_complex * _kd);
+
+// digital z/p/k low-pass to high-pass
+// _zd : digital zeros (low-pass prototype), [length: _n]
+// _pd : digital poles (low-pass prototype), [length: _n]
+// _n : low-pass filter order
+// _zdt : output digital zeros transformed [length: _n]
+// _pdt : output digital poles transformed [length: _n]
+void iirdes_dzpk_lp2hp(liquid_float_complex * _zd,
+ liquid_float_complex * _pd,
+ unsigned int _n,
+ liquid_float_complex * _zdt,
+ liquid_float_complex * _pdt);
+
+// digital z/p/k low-pass to band-pass
+// _zd : digital zeros (low-pass prototype), [length: _n]
+// _pd : digital poles (low-pass prototype), [length: _n]
+// _n : low-pass filter order
+// _f0 : center frequency
+// _zdt : output digital zeros transformed [length: 2*_n]
+// _pdt : output digital poles transformed [length: 2*_n]
+void iirdes_dzpk_lp2bp(liquid_float_complex * _zd,
+ liquid_float_complex * _pd,
+ unsigned int _n,
+ float _f0,
+ liquid_float_complex * _zdt,
+ liquid_float_complex * _pdt);
+
+// convert discrete z/p/k form to transfer function
+// _zd : digital zeros [length: _n]
+// _pd : digital poles [length: _n]
+// _n : filter order
+// _kd : digital gain
+// _b : output numerator [length: _n+1]
+// _a : output denominator [length: _n+1]
+void iirdes_dzpk2tff(liquid_float_complex * _zd,
+ liquid_float_complex * _pd,
+ unsigned int _n,
+ liquid_float_complex _kd,
+ float * _b,
+ float * _a);
+
+// convert discrete z/p/k form to second-order sections
+// _zd : digital zeros [length: _n]
+// _pd : digital poles [length: _n]
+// _n : filter order
+// _kd : digital gain
+// _B : output numerator [size: 3 x L+r]
+// _A : output denominator [size: 3 x L+r]
+// where r = _n%2, L = (_n-r)/2
+void iirdes_dzpk2sosf(liquid_float_complex * _zd,
+ liquid_float_complex * _pd,
+ unsigned int _n,
+ liquid_float_complex _kd,
+ float * _B,
+ float * _A);
+
+// additional IIR filter design templates
+
+// design 2nd-order IIR filter (active lag)
+// 1 + t2 * s
+// F(s) = ------------
+// 1 + t1 * s
+//
+// _w : filter bandwidth
+// _zeta : damping factor (1/sqrt(2) suggested)
+// _K : loop gain (1000 suggested)
+// _b : output feed-forward coefficients [size: 3 x 1]
+// _a : output feed-back coefficients [size: 3 x 1]
+void iirdes_pll_active_lag(float _w,
+ float _zeta,
+ float _K,
+ float * _b,
+ float * _a);
+
+// design 2nd-order IIR filter (active PI)
+// 1 + t2 * s
+// F(s) = ------------
+// t1 * s
+//
+// _w : filter bandwidth
+// _zeta : damping factor (1/sqrt(2) suggested)
+// _K : loop gain (1000 suggested)
+// _b : output feed-forward coefficients [size: 3 x 1]
+// _a : output feed-back coefficients [size: 3 x 1]
+void iirdes_pll_active_PI(float _w,
+ float _zeta,
+ float _K,
+ float * _b,
+ float * _a);
+
+// checks stability of iir filter
+// _b : feed-forward coefficients [size: _n x 1]
+// _a : feed-back coefficients [size: _n x 1]
+// _n : number of coefficients
+int iirdes_isstable(float * _b,
+ float * _a,
+ unsigned int _n);
+
+//
+// linear prediction
+//
+
+// compute the linear prediction coefficients for an input signal _x
+// _x : input signal [size: _n x 1]
+// _n : input signal length
+// _p : prediction filter order
+// _a : prediction filter [size: _p+1 x 1]
+// _e : prediction error variance [size: _p+1 x 1]
+void liquid_lpc(float * _x,
+ unsigned int _n,
+ unsigned int _p,
+ float * _a,
+ float * _g);
+
+// solve the Yule-Walker equations using Levinson-Durbin recursion
+// for _symmetric_ autocorrelation
+// _r : autocorrelation array [size: _p+1 x 1]
+// _p : filter order
+// _a : output coefficients [size: _p+1 x 1]
+// _e : error variance [size: _p+1 x 1]
+//
+// NOTES:
+// By definition _a[0] = 1.0
+void liquid_levinson(float * _r,
+ unsigned int _p,
+ float * _a,
+ float * _e);
+
+//
+// auto-correlator (delay cross-correlation)
+//
+
+#define AUTOCORR_MANGLE_CCCF(name) LIQUID_CONCAT(autocorr_cccf,name)
+#define AUTOCORR_MANGLE_RRRF(name) LIQUID_CONCAT(autocorr_rrrf,name)
+
+// Macro:
+// AUTOCORR : name-mangling macro
+// TO : output data type
+// TC : coefficients data type
+// TI : input data type
+#define LIQUID_AUTOCORR_DEFINE_API(AUTOCORR,TO,TC,TI) \
+ \
+typedef struct AUTOCORR(_s) * AUTOCORR(); \
+ \
+/* create auto-correlator object */ \
+/* _window_size : size of the correlator window */ \
+/* _delay : correlator delay [samples] */ \
+AUTOCORR() AUTOCORR(_create)(unsigned int _window_size, \
+ unsigned int _delay); \
+ \
+/* destroy auto-correlator object, freeing internal memory */ \
+void AUTOCORR(_destroy)(AUTOCORR() _q); \
+ \
+/* reset auto-correlator object's internals */ \
+void AUTOCORR(_reset)(AUTOCORR() _q); \
+ \
+/* print auto-correlator parameters to stdout */ \
+void AUTOCORR(_print)(AUTOCORR() _q); \
+ \
+/* push sample into auto-correlator object */ \
+void AUTOCORR(_push)(AUTOCORR() _q, \
+ TI _x); \
+ \
+/* compute single auto-correlation output */ \
+void AUTOCORR(_execute)(AUTOCORR() _q, \
+ TO * _rxx); \
+ \
+/* compute auto-correlation on block of samples; the input */ \
+/* and output arrays may have the same pointer */ \
+/* _q : auto-correlation object */ \
+/* _x : input array [size: _n x 1] */ \
+/* _n : number of input, output samples */ \
+/* _rxx : input array [size: _n x 1] */ \
+void AUTOCORR(_execute_block)(AUTOCORR() _q, \
+ TI * _x, \
+ unsigned int _n, \
+ TO * _rxx); \
+ \
+/* return sum of squares of buffered samples */ \
+float AUTOCORR(_get_energy)(AUTOCORR() _q); \
+
+LIQUID_AUTOCORR_DEFINE_API(AUTOCORR_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+LIQUID_AUTOCORR_DEFINE_API(AUTOCORR_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+
+//
+// Finite impulse response filter
+//
+
+#define FIRFILT_MANGLE_RRRF(name) LIQUID_CONCAT(firfilt_rrrf,name)
+#define FIRFILT_MANGLE_CRCF(name) LIQUID_CONCAT(firfilt_crcf,name)
+#define FIRFILT_MANGLE_CCCF(name) LIQUID_CONCAT(firfilt_cccf,name)
+
+// Macro:
+// FIRFILT : name-mangling macro
+// TO : output data type
+// TC : coefficients data type
+// TI : input data type
+#define LIQUID_FIRFILT_DEFINE_API(FIRFILT,TO,TC,TI) \
+typedef struct FIRFILT(_s) * FIRFILT(); \
+ \
+FIRFILT() FIRFILT(_create)(TC * _h, unsigned int _n); \
+ \
+/* create using Kaiser-Bessel windowed sinc method */ \
+/* _n : filter length, _n > 0 */ \
+/* _fc : filter cut-off frequency 0 < _fc < 0.5 */ \
+/* _As : filter stop-band attenuation [dB], _As > 0 */ \
+/* _mu : fractional sample offset, -0.5 < _mu < 0.5 */ \
+FIRFILT() FIRFILT(_create_kaiser)(unsigned int _n, \
+ float _fc, \
+ float _As, \
+ float _mu); \
+ \
+/* create from square-root Nyquist prototype */ \
+/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
+/* _k : nominal samples/symbol, _k > 1 */ \
+/* _m : filter delay [symbols], _m > 0 */ \
+/* _beta : rolloff factor, 0 < beta <= 1 */ \
+/* _mu : fractional sample offset,-0.5 < _mu < 0.5 */ \
+FIRFILT() FIRFILT(_create_rnyquist)(int _type, \
+ unsigned int _k, \
+ unsigned int _m, \
+ float _beta, \
+ float _mu); \
+ \
+/* re-create filter */ \
+/* _q : original filter object */ \
+/* _h : pointer to filter coefficients [size: _n x 1] */ \
+/* _n : filter length, _n > 0 */ \
+FIRFILT() FIRFILT(_recreate)(FIRFILT() _q, \
+ TC * _h, \
+ unsigned int _n); \
+ \
+/* destroy filter object and free all internal memory */ \
+void FIRFILT(_destroy)(FIRFILT() _q); \
+ \
+/* reset filter object's internal buffer */ \
+void FIRFILT(_reset)(FIRFILT() _q); \
+ \
+/* print filter object information */ \
+void FIRFILT(_print)(FIRFILT() _q); \
+ \
+/* set output scaling for filter */ \
+void FIRFILT(_set_scale)(FIRFILT() _q, \
+ TC _g); \
+ \
+/* push sample into filter object's internal buffer */ \
+/* _q : filter object */ \
+/* _x : single input sample */ \
+void FIRFILT(_push)(FIRFILT() _q, \
+ TI _x); \
+ \
+/* execute the filter on internal buffer and coefficients */ \
+/* _q : filter object */ \
+/* _y : pointer to single output sample */ \
+void FIRFILT(_execute)(FIRFILT() _q, \
+ TO * _y); \
+ \
+/* execute the filter on a block of input samples; the */ \
+/* input and output buffers may be the same */ \
+/* _q : filter object */ \
+/* _x : pointer to input array [size: _n x 1] */ \
+/* _n : number of input, output samples */ \
+/* _y : pointer to output array [size: _n x 1] */ \
+void FIRFILT(_execute_block)(FIRFILT() _q, \
+ TI * _x, \
+ unsigned int _n, \
+ TO * _y); \
+ \
+/* return length of filter object */ \
+unsigned int FIRFILT(_get_length)(FIRFILT() _q); \
+ \
+/* compute complex frequency response of filter object */ \
+/* _q : filter object */ \
+/* _fc : frequency to evaluate */ \
+/* _H : pointer to output complex frequency response */ \
+void FIRFILT(_freqresponse)(FIRFILT() _q, \
+ float _fc, \
+ liquid_float_complex * _H); \
+ \
+/* compute and return group delay of filter object */ \
+/* _q : filter object */ \
+/* _fc : frequency to evaluate */ \
+float FIRFILT(_groupdelay)(FIRFILT() _q, \
+ float _fc); \
+
+LIQUID_FIRFILT_DEFINE_API(FIRFILT_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_FIRFILT_DEFINE_API(FIRFILT_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_FIRFILT_DEFINE_API(FIRFILT_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+//
+// FIR Hilbert transform
+// 2:1 real-to-complex decimator
+// 1:2 complex-to-real interpolator
+//
+
+#define FIRHILB_MANGLE_FLOAT(name) LIQUID_CONCAT(firhilbf, name)
+//#define FIRHILB_MANGLE_DOUBLE(name) LIQUID_CONCAT(firhilb, name)
+
+// NOTES:
+// Although firhilb is a placeholder for both decimation and
+// interpolation, separate objects should be used for each task.
+#define LIQUID_FIRHILB_DEFINE_API(FIRHILB,T,TC) \
+typedef struct FIRHILB(_s) * FIRHILB(); \
+ \
+/* create finite impulse reponse Hilbert transform */ \
+/* _m : filter semi-length, delay is 2*m+1 */ \
+/* _As : filter stop-band attenuation [dB] */ \
+FIRHILB() FIRHILB(_create)(unsigned int _m, \
+ float _As); \
+ \
+/* destroy finite impulse reponse Hilbert transform */ \
+void FIRHILB(_destroy)(FIRHILB() _q); \
+ \
+/* print firhilb object internals to stdout */ \
+void FIRHILB(_print)(FIRHILB() _q); \
+ \
+/* reset firhilb object internal state */ \
+void FIRHILB(_reset)(FIRHILB() _q); \
+ \
+/* execute Hilbert transform (real to complex) */ \
+/* _q : Hilbert transform object */ \
+/* _x : real-valued input sample */ \
+/* _y : complex-valued output sample */ \
+void FIRHILB(_r2c_execute)(FIRHILB() _q, \
+ T _x, \
+ TC * _y); \
+ \
+/* execute Hilbert transform (complex to real) */ \
+/* _q : Hilbert transform object */ \
+/* _x : complex-valued input sample */ \
+/* _y : real-valued output sample */ \
+void FIRHILB(_c2r_execute)(FIRHILB() _q, \
+ TC _x, \
+ T * _y); \
+ \
+/* execute Hilbert transform decimator (real to complex) */ \
+/* _q : Hilbert transform object */ \
+/* _x : real-valued input array [size: 2 x 1] */ \
+/* _y : complex-valued output sample */ \
+void FIRHILB(_decim_execute)(FIRHILB() _q, \
+ T * _x, \
+ TC * _y); \
+ \
+/* execute Hilbert transform interpolator (real to complex) */ \
+/* _q : Hilbert transform object */ \
+/* _x : complex-valued input sample */ \
+/* _y : real-valued output array [size: 2 x 1] */ \
+void FIRHILB(_interp_execute)(FIRHILB() _q, \
+ TC _x, \
+ T * _y); \
+
+LIQUID_FIRHILB_DEFINE_API(FIRHILB_MANGLE_FLOAT, float, liquid_float_complex)
+//LIQUID_FIRHILB_DEFINE_API(FIRHILB_MANGLE_DOUBLE, double, liquid_double_complex)
+
+
+//
+// FFT-based finite impulse response filter
+//
+
+#define FFTFILT_MANGLE_RRRF(name) LIQUID_CONCAT(fftfilt_rrrf,name)
+#define FFTFILT_MANGLE_CRCF(name) LIQUID_CONCAT(fftfilt_crcf,name)
+#define FFTFILT_MANGLE_CCCF(name) LIQUID_CONCAT(fftfilt_cccf,name)
+
+// Macro:
+// FFTFILT : name-mangling macro
+// TO : output data type
+// TC : coefficients data type
+// TI : input data type
+#define LIQUID_FFTFILT_DEFINE_API(FFTFILT,TO,TC,TI) \
+typedef struct FFTFILT(_s) * FFTFILT(); \
+ \
+/* create FFT-based FIR filter using external coefficients */ \
+/* _h : filter coefficients [size: _h_len x 1] */ \
+/* _h_len : filter length, _h_len > 0 */ \
+/* _n : block size = nfft/2, at least _h_len-1 */ \
+FFTFILT() FFTFILT(_create)(TC * _h, \
+ unsigned int _h_len, \
+ unsigned int _n); \
+ \
+/* destroy filter object and free all internal memory */ \
+void FFTFILT(_destroy)(FFTFILT() _q); \
+ \
+/* reset filter object's internal buffer */ \
+void FFTFILT(_reset)(FFTFILT() _q); \
+ \
+/* print filter object information */ \
+void FFTFILT(_print)(FFTFILT() _q); \
+ \
+/* set output scaling for filter */ \
+void FFTFILT(_set_scale)(FFTFILT() _q, \
+ TC _g); \
+ \
+/* execute the filter on internal buffer and coefficients */ \
+/* _q : filter object */ \
+/* _x : pointer to input data array [size: _n x 1] */ \
+/* _y : pointer to output data array [size: _n x 1] */ \
+void FFTFILT(_execute)(FFTFILT() _q, \
+ TI * _x, \
+ TO * _y); \
+ \
+/* return length of filter object's internal coefficients */ \
+unsigned int FFTFILT(_get_length)(FFTFILT() _q); \
+
+LIQUID_FFTFILT_DEFINE_API(FFTFILT_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_FFTFILT_DEFINE_API(FFTFILT_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_FFTFILT_DEFINE_API(FFTFILT_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+
+//
+// Infinite impulse response filter
+//
+
+#define IIRFILT_MANGLE_RRRF(name) LIQUID_CONCAT(iirfilt_rrrf,name)
+#define IIRFILT_MANGLE_CRCF(name) LIQUID_CONCAT(iirfilt_crcf,name)
+#define IIRFILT_MANGLE_CCCF(name) LIQUID_CONCAT(iirfilt_cccf,name)
+
+// Macro:
+// IIRFILT : name-mangling macro
+// TO : output data type
+// TC : coefficients data type
+// TI : input data type
+#define LIQUID_IIRFILT_DEFINE_API(IIRFILT,TO,TC,TI) \
+ \
+typedef struct IIRFILT(_s) * IIRFILT(); \
+ \
+/* create infinite impulse reponse filter */ \
+/* _b : feed-forward coefficients [size: _nb x 1] */ \
+/* _nb : number of feed-forward coefficients */ \
+/* _a : feed-back coefficients [size: _na x 1] */ \
+/* _na : number of feed-back coefficients */ \
+IIRFILT() IIRFILT(_create)(TC * _b, \
+ unsigned int _nb, \
+ TC * _a, \
+ unsigned int _na); \
+ \
+/* create IIR filter using 2nd-order secitons */ \
+/* _B : feed-forward coefficients [size: _nsos x 3] */ \
+/* _A : feed-back coefficients [size: _nsos x 3] */ \
+IIRFILT() IIRFILT(_create_sos)(TC * _B, \
+ TC * _A, \
+ unsigned int _nsos); \
+ \
+/* create IIR filter from design template */ \
+/* _ftype : filter type (e.g. LIQUID_IIRDES_BUTTER) */ \
+/* _btype : band type (e.g. LIQUID_IIRDES_BANDPASS) */ \
+/* _format : coefficients format (e.g. LIQUID_IIRDES_SOS) */ \
+/* _n : filter order */ \
+/* _fc : low-pass prototype cut-off frequency */ \
+/* _f0 : center frequency (band-pass, band-stop) */ \
+/* _Ap : pass-band ripple in dB */ \
+/* _As : stop-band ripple in dB */ \
+IIRFILT() IIRFILT(_create_prototype)( \
+ liquid_iirdes_filtertype _ftype, \
+ liquid_iirdes_bandtype _btype, \
+ liquid_iirdes_format _format, \
+ unsigned int _order, \
+ float _fc, \
+ float _f0, \
+ float _Ap, \
+ float _As); \
+ \
+/* create 8th-order integrator filter */ \
+IIRFILT() IIRFILT(_create_integrator)(); \
+ \
+/* create 8th-order differentiator filter */ \
+IIRFILT() IIRFILT(_create_differentiator)(); \
+ \
+/* create simple DC-blocking filter */ \
+IIRFILT() IIRFILT(_create_dc_blocker)(float _alpha); \
+ \
+/* create phase-locked loop iirfilt object */ \
+/* _w : filter bandwidth */ \
+/* _zeta : damping factor (1/sqrt(2) suggested) */ \
+/* _K : loop gain (1000 suggested) */ \
+IIRFILT() IIRFILT(_create_pll)(float _w, \
+ float _zeta, \
+ float _K); \
+ \
+/* destroy iirfilt object, freeing all internal memory */ \
+void IIRFILT(_destroy)(IIRFILT() _q); \
+ \
+/* print iirfilt object properties to stdout */ \
+void IIRFILT(_print)(IIRFILT() _q); \
+ \
+/* clear/reset iirfilt object internals */ \
+void IIRFILT(_reset)(IIRFILT() _q); \
+ \
+/* compute filter output */ \
+/* _q : iirfilt object */ \
+/* _x : input sample */ \
+/* _y : output sample pointer */ \
+void IIRFILT(_execute)(IIRFILT() _q, \
+ TI _x, \
+ TO * _y); \
+ \
+/* execute the filter on a block of input samples; the */ \
+/* input and output buffers may be the same */ \
+/* _q : filter object */ \
+/* _x : pointer to input array [size: _n x 1] */ \
+/* _n : number of input, output samples */ \
+/* _y : pointer to output array [size: _n x 1] */ \
+void IIRFILT(_execute_block)(IIRFILT() _q, \
+ TI * _x, \
+ unsigned int _n, \
+ TO * _y); \
+ \
+/* return iirfilt object's filter length (order + 1) */ \
+unsigned int IIRFILT(_get_length)(IIRFILT() _q); \
+ \
+/* compute complex frequency response of filter object */ \
+/* _q : filter object */ \
+/* _fc : frequency to evaluate */ \
+/* _H : pointer to output complex frequency response */ \
+void IIRFILT(_freqresponse)(IIRFILT() _q, \
+ float _fc, \
+ liquid_float_complex * _H); \
+ \
+/* compute and return group delay of filter object */ \
+/* _q : filter object */ \
+/* _fc : frequency to evaluate */ \
+float IIRFILT(_groupdelay)(IIRFILT() _q, float _fc); \
+
+LIQUID_IIRFILT_DEFINE_API(IIRFILT_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_IIRFILT_DEFINE_API(IIRFILT_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_IIRFILT_DEFINE_API(IIRFILT_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+
+//
+// FIR Polyphase filter bank
+//
+#define FIRPFB_MANGLE_RRRF(name) LIQUID_CONCAT(firpfb_rrrf,name)
+#define FIRPFB_MANGLE_CRCF(name) LIQUID_CONCAT(firpfb_crcf,name)
+#define FIRPFB_MANGLE_CCCF(name) LIQUID_CONCAT(firpfb_cccf,name)
+
+// Macro:
+// FIRPFB : name-mangling macro
+// TO : output data type
+// TC : coefficients data type
+// TI : input data type
+#define LIQUID_FIRPFB_DEFINE_API(FIRPFB,TO,TC,TI) \
+ \
+typedef struct FIRPFB(_s) * FIRPFB(); \
+ \
+/* create firpfb from external coefficients */ \
+/* _M : number of filters in the bank */ \
+/* _h : coefficients [size: _M*_h_len x 1] */ \
+/* _h_len : filter delay (symbols) */ \
+FIRPFB() FIRPFB(_create)(unsigned int _M, \
+ TC * _h, \
+ unsigned int _h_len); \
+ \
+/* create firpfb from square-root Nyquist prototype */ \
+/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
+/* _npfb : number of filters in the bank */ \
+/* _k : nominal samples/symbol */ \
+/* _m : filter delay (symbols) */ \
+/* _beta : rolloff factor (0 < beta <= 1) */ \
+FIRPFB() FIRPFB(_create_rnyquist)(int _type, \
+ unsigned int _npfb, \
+ unsigned int _k, \
+ unsigned int _m, \
+ float _beta); \
+ \
+/* create from square-root derivative Nyquist prototype */ \
+/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
+/* _npfb : number of filters in the bank */ \
+/* _k : nominal samples/symbol */ \
+/* _m : filter delay (symbols) */ \
+/* _beta : rolloff factor (0 < beta <= 1) */ \
+FIRPFB() FIRPFB(_create_drnyquist)(int _type, \
+ unsigned int _npfb, \
+ unsigned int _k, \
+ unsigned int _m, \
+ float _beta); \
+ \
+/* re-create filterbank object */ \
+/* _q : original firpfb object */ \
+/* _M : number of filters in the bank */ \
+/* _h : coefficients [size: _M x _h_len] */ \
+/* _h_len : length of each filter */ \
+FIRPFB() FIRPFB(_recreate)(FIRPFB() _q, \
+ unsigned int _M, \
+ TC * _h, \
+ unsigned int _h_len); \
+ \
+/* destroy firpfb object, freeing all internal memory */ \
+void FIRPFB(_destroy)(FIRPFB() _q); \
+ \
+/* print firpfb object's parameters */ \
+void FIRPFB(_print)(FIRPFB() _q); \
+ \
+/* clear/reset firpfb object internal state */ \
+void FIRPFB(_reset)(FIRPFB() _q); \
+ \
+/* push sample into firpfb internal buffer */ \
+void FIRPFB(_push)(FIRPFB() _q, TI _x); \
+ \
+/* execute the filter on internal buffer and coefficients */ \
+/* _q : firpfb object */ \
+/* _i : index of filter to use */ \
+/* _y : pointer to output sample */ \
+void FIRPFB(_execute)(FIRPFB() _q, \
+ unsigned int _i, \
+ TO * _y); \
+
+LIQUID_FIRPFB_DEFINE_API(FIRPFB_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_FIRPFB_DEFINE_API(FIRPFB_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_FIRPFB_DEFINE_API(FIRPFB_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+//
+// Interpolators
+//
+
+// firinterp : finite impulse response interpolator
+#define FIRINTERP_MANGLE_RRRF(name) LIQUID_CONCAT(firinterp_rrrf,name)
+#define FIRINTERP_MANGLE_CRCF(name) LIQUID_CONCAT(firinterp_crcf,name)
+#define FIRINTERP_MANGLE_CCCF(name) LIQUID_CONCAT(firinterp_cccf,name)
+
+#define LIQUID_FIRINTERP_DEFINE_API(FIRINTERP,TO,TC,TI) \
+ \
+typedef struct FIRINTERP(_s) * FIRINTERP(); \
+ \
+/* create interpolator from external coefficients */ \
+/* _M : interpolation factor */ \
+/* _h : filter coefficients [size: _h_len x 1] */ \
+/* _h_len : filter length */ \
+FIRINTERP() FIRINTERP(_create)(unsigned int _M, \
+ TC * _h, \
+ unsigned int _h_len); \
+ \
+/* create interpolator from prototype */ \
+/* _M : interpolation factor */ \
+/* _m : filter delay (symbols) */ \
+/* _As : stop-band attenuation [dB] */ \
+FIRINTERP() FIRINTERP(_create_prototype)(unsigned int _M, \
+ unsigned int _m, \
+ float _As); \
+ \
+/* create Nyquist interpolator */ \
+/* _type : filter type (e.g. LIQUID_FIRFILT_RCOS) */ \
+/* _k : samples/symbol, _k > 1 */ \
+/* _m : filter delay (symbols), _m > 0 */ \
+/* _beta : excess bandwidth factor, _beta < 1 */ \
+/* _dt : fractional sample delay, _dt in (-1, 1) */ \
+FIRINTERP() FIRINTERP(_create_nyquist)(int _type, \
+ unsigned int _k, \
+ unsigned int _m, \
+ float _beta, \
+ float _dt); \
+ \
+/* create square-root Nyquist interpolator */ \
+/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
+/* _k : samples/symbol, _k > 1 */ \
+/* _m : filter delay (symbols), _m > 0 */ \
+/* _beta : excess bandwidth factor, _beta < 1 */ \
+/* _dt : fractional sample delay, _dt in (-1, 1) */ \
+FIRINTERP() FIRINTERP(_create_rnyquist)(int _type, \
+ unsigned int _k, \
+ unsigned int _m, \
+ float _beta, \
+ float _dt); \
+ \
+/* destroy firinterp object, freeing all internal memory */ \
+void FIRINTERP(_destroy)(FIRINTERP() _q); \
+ \
+/* print firinterp object's internal properties to stdout */ \
+void FIRINTERP(_print)(FIRINTERP() _q); \
+ \
+/* reset internal state */ \
+void FIRINTERP(_reset)(FIRINTERP() _q); \
+ \
+/* execute interpolation on single input sample */ \
+/* _q : firinterp object */ \
+/* _x : input sample */ \
+/* _y : output sample array [size: _M x 1] */ \
+void FIRINTERP(_execute)(FIRINTERP() _q, \
+ TI _x, \
+ TO * _y); \
+ \
+/* execute interpolation on block of input samples */ \
+/* _q : firinterp object */ \
+/* _x : input array [size: _n x 1] */ \
+/* _n : size of input array */ \
+/* _y : output sample array [size: _M*_n x 1] */ \
+void FIRINTERP(_execute_block)(FIRINTERP() _q, \
+ TI * _x, \
+ unsigned int _n, \
+ TO * _y); \
+
+LIQUID_FIRINTERP_DEFINE_API(FIRINTERP_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_FIRINTERP_DEFINE_API(FIRINTERP_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_FIRINTERP_DEFINE_API(FIRINTERP_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+// iirinterp : infinite impulse response interpolator
+#define IIRINTERP_MANGLE_RRRF(name) LIQUID_CONCAT(iirinterp_rrrf,name)
+#define IIRINTERP_MANGLE_CRCF(name) LIQUID_CONCAT(iirinterp_crcf,name)
+#define IIRINTERP_MANGLE_CCCF(name) LIQUID_CONCAT(iirinterp_cccf,name)
+
+#define LIQUID_IIRINTERP_DEFINE_API(IIRINTERP,TO,TC,TI) \
+typedef struct IIRINTERP(_s) * IIRINTERP(); \
+ \
+/* create interpolator from external coefficients */ \
+/* _M : interpolation factor */ \
+/* _b : feed-back coefficients [size: _nb x 1] */ \
+/* _nb : feed-back coefficients length */ \
+/* _a : feed-forward coefficients [size: _na x 1] */ \
+/* _na : feed-forward coefficients length */ \
+IIRINTERP() IIRINTERP(_create)(unsigned int _M, \
+ TC * _b, \
+ unsigned int _nb, \
+ TC * _a, \
+ unsigned int _na); \
+ \
+/* create interpolator from prototype */ \
+/* _M : interpolation factor */ \
+IIRINTERP() IIRINTERP(_create_prototype)( \
+ unsigned int _M, \
+ liquid_iirdes_filtertype _ftype, \
+ liquid_iirdes_bandtype _btype, \
+ liquid_iirdes_format _format, \
+ unsigned int _order, \
+ float _fc, \
+ float _f0, \
+ float _Ap, \
+ float _As); \
+ \
+/* destroy interpolator object and free internal memory */ \
+void IIRINTERP(_destroy)(IIRINTERP() _q); \
+ \
+/* print interpolator object internals */ \
+void IIRINTERP(_print)(IIRINTERP() _q); \
+ \
+/* reset interpolator object */ \
+void IIRINTERP(_reset)(IIRINTERP() _q); \
+ \
+/* execute interpolation on single input sample */ \
+/* _q : iirinterp object */ \
+/* _x : input sample */ \
+/* _y : output sample array [size: _M x 1] */ \
+void IIRINTERP(_execute)(IIRINTERP() _q, \
+ TI _x, \
+ TO * _y); \
+ \
+/* execute interpolation on block of input samples */ \
+/* _q : iirinterp object */ \
+/* _x : input array [size: _n x 1] */ \
+/* _n : size of input array */ \
+/* _y : output sample array [size: _M*_n x 1] */ \
+void IIRINTERP(_execute_block)(IIRINTERP() _q, \
+ TI * _x, \
+ unsigned int _n, \
+ TO * _y); \
+ \
+/* get system group delay at frequency _fc */ \
+float IIRINTERP(_groupdelay)(IIRINTERP() _q, float _fc); \
+
+LIQUID_IIRINTERP_DEFINE_API(IIRINTERP_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_IIRINTERP_DEFINE_API(IIRINTERP_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_IIRINTERP_DEFINE_API(IIRINTERP_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+//
+// Decimators
+//
+
+// firdecim : finite impulse response decimator
+#define FIRDECIM_MANGLE_RRRF(name) LIQUID_CONCAT(firdecim_rrrf,name)
+#define FIRDECIM_MANGLE_CRCF(name) LIQUID_CONCAT(firdecim_crcf,name)
+#define FIRDECIM_MANGLE_CCCF(name) LIQUID_CONCAT(firdecim_cccf,name)
+
+#define LIQUID_FIRDECIM_DEFINE_API(FIRDECIM,TO,TC,TI) \
+typedef struct FIRDECIM(_s) * FIRDECIM(); \
+ \
+/* create decimator from external coefficients */ \
+/* _M : decimation factor */ \
+/* _h : filter coefficients [size: _h_len x 1] */ \
+/* _h_len : filter coefficients length */ \
+FIRDECIM() FIRDECIM(_create)(unsigned int _M, \
+ TC * _h, \
+ unsigned int _h_len); \
+ \
+/* create decimator from prototype */ \
+/* _M : decimation factor */ \
+/* _m : filter delay (symbols) */ \
+/* _As : stop-band attenuation [dB] */ \
+FIRDECIM() FIRDECIM(_create_prototype)(unsigned int _M, \
+ unsigned int _m, \
+ float _As); \
+ \
+/* create square-root Nyquist decimator */ \
+/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
+/* _M : samples/symbol (decimation factor) */ \
+/* _m : filter delay (symbols) */ \
+/* _beta : rolloff factor (0 < beta <= 1) */ \
+/* _dt : fractional sample delay */ \
+FIRDECIM() FIRDECIM(_create_rnyquist)(int _type, \
+ unsigned int _M, \
+ unsigned int _m, \
+ float _beta, \
+ float _dt); \
+ \
+/* destroy decimator object */ \
+void FIRDECIM(_destroy)(FIRDECIM() _q); \
+ \
+/* print decimator object propreties to stdout */ \
+void FIRDECIM(_print)(FIRDECIM() _q); \
+ \
+/* reset decimator object internal state */ \
+void FIRDECIM(_clear)(FIRDECIM() _q); \
+ \
+/* execute decimator on _M input samples */ \
+/* _q : decimator object */ \
+/* _x : input samples [size: _M x 1] */ \
+/* _y : output sample pointer */ \
+void FIRDECIM(_execute)(FIRDECIM() _q, \
+ TI * _x, \
+ TO * _y); \
+ \
+/* execute decimator on block of _n*_M input samples */ \
+/* _q : decimator object */ \
+/* _x : input array [size: _n*_M x 1] */ \
+/* _n : number of _output_ samples */ \
+/* _y : output array [_sze: _n x 1] */ \
+void FIRDECIM(_execute_block)(FIRDECIM() _q, \
+ TI * _x, \
+ unsigned int _n, \
+ TO * _y); \
+
+LIQUID_FIRDECIM_DEFINE_API(FIRDECIM_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_FIRDECIM_DEFINE_API(FIRDECIM_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_FIRDECIM_DEFINE_API(FIRDECIM_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+
+// iirdecim : infinite impulse response decimator
+#define IIRDECIM_MANGLE_RRRF(name) LIQUID_CONCAT(iirdecim_rrrf,name)
+#define IIRDECIM_MANGLE_CRCF(name) LIQUID_CONCAT(iirdecim_crcf,name)
+#define IIRDECIM_MANGLE_CCCF(name) LIQUID_CONCAT(iirdecim_cccf,name)
+
+#define LIQUID_IIRDECIM_DEFINE_API(IIRDECIM,TO,TC,TI) \
+typedef struct IIRDECIM(_s) * IIRDECIM(); \
+ \
+/* create decimator from external coefficients */ \
+/* _M : decimation factor */ \
+/* _b : feed-back coefficients [size: _nb x 1] */ \
+/* _nb : feed-back coefficients length */ \
+/* _a : feed-forward coefficients [size: _na x 1] */ \
+/* _na : feed-forward coefficients length */ \
+IIRDECIM() IIRDECIM(_create)(unsigned int _M, \
+ TC * _b, \
+ unsigned int _nb, \
+ TC * _a, \
+ unsigned int _na); \
+ \
+/* create decimator from prototype */ \
+/* _M : decimation factor */ \
+IIRDECIM() IIRDECIM(_create_prototype)( \
+ unsigned int _M, \
+ liquid_iirdes_filtertype _ftype, \
+ liquid_iirdes_bandtype _btype, \
+ liquid_iirdes_format _format, \
+ unsigned int _order, \
+ float _fc, \
+ float _f0, \
+ float _Ap, \
+ float _As); \
+ \
+/* destroy decimator object and free internal memory */ \
+void IIRDECIM(_destroy)(IIRDECIM() _q); \
+ \
+/* print decimator object internals */ \
+void IIRDECIM(_print)(IIRDECIM() _q); \
+ \
+/* reset decimator object */ \
+void IIRDECIM(_reset)(IIRDECIM() _q); \
+ \
+/* execute decimator on _M input samples */ \
+/* _q : decimator object */ \
+/* _x : input samples [size: _M x 1] */ \
+/* _y : output sample pointer */ \
+void IIRDECIM(_execute)(IIRDECIM() _q, \
+ TI * _x, \
+ TO * _y); \
+ \
+/* execute decimator on block of _n*_M input samples */ \
+/* _q : decimator object */ \
+/* _x : input array [size: _n*_M x 1] */ \
+/* _n : number of _output_ samples */ \
+/* _y : output array [_sze: _n x 1] */ \
+void IIRDECIM(_execute_block)(IIRDECIM() _q, \
+ TI * _x, \
+ unsigned int _n, \
+ TO * _y); \
+ \
+/* get system group delay at frequency _fc */ \
+float IIRDECIM(_groupdelay)(IIRDECIM() _q, float _fc); \
+
+LIQUID_IIRDECIM_DEFINE_API(IIRDECIM_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_IIRDECIM_DEFINE_API(IIRDECIM_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_IIRDECIM_DEFINE_API(IIRDECIM_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+
+
+//
+// Half-band resampler
+//
+#define RESAMP2_MANGLE_RRRF(name) LIQUID_CONCAT(resamp2_rrrf,name)
+#define RESAMP2_MANGLE_CRCF(name) LIQUID_CONCAT(resamp2_crcf,name)
+#define RESAMP2_MANGLE_CCCF(name) LIQUID_CONCAT(resamp2_cccf,name)
+
+#define LIQUID_RESAMP2_DEFINE_API(RESAMP2,TO,TC,TI) \
+typedef struct RESAMP2(_s) * RESAMP2(); \
+ \
+/* create half-band resampler */ \
+/* _m : filter semi-length (h_len = 4*m+1) */ \
+/* _f0 : filter center frequency */ \
+/* _As : stop-band attenuation [dB] */ \
+RESAMP2() RESAMP2(_create)(unsigned int _m, \
+ float _f0, \
+ float _As); \
+ \
+/* re-create half-band resampler with new properties */ \
+/* _q : original half-band resampler object */ \
+/* _m : filter semi-length (h_len = 4*m+1) */ \
+/* _f0 : filter center frequency */ \
+/* _As : stop-band attenuation [dB] */ \
+RESAMP2() RESAMP2(_recreate)(RESAMP2() _q, \
+ unsigned int _m, \
+ float _f0, \
+ float _As); \
+ \
+/* destroy half-band resampler */ \
+void RESAMP2(_destroy)(RESAMP2() _q); \
+ \
+/* print resamp2 object's internals */ \
+void RESAMP2(_print)(RESAMP2() _q); \
+ \
+/* reset internal buffer */ \
+void RESAMP2(_clear)(RESAMP2() _q); \
+ \
+/* get resampler filter delay (semi-length m) */ \
+unsigned int RESAMP2(_get_delay)(RESAMP2() _q); \
+ \
+/* execute resamp2 as half-band filter */ \
+/* _q : resamp2 object */ \
+/* _x : input sample */ \
+/* _y0 : output sample pointer (low frequency) */ \
+/* _y1 : output sample pointer (high frequency) */ \
+void RESAMP2(_filter_execute)(RESAMP2() _q, \
+ TI _x, \
+ TO * _y0, \
+ TO * _y1); \
+ \
+/* execute resamp2 as half-band analysis filterbank */ \
+/* _q : resamp2 object */ \
+/* _x : input array [size: 2 x 1] */ \
+/* _y : output array [size: 2 x 1] */ \
+void RESAMP2(_analyzer_execute)(RESAMP2() _q, \
+ TI * _x, \
+ TO * _y); \
+ \
+/* execute resamp2 as half-band synthesis filterbank */ \
+/* _q : resamp2 object */ \
+/* _x : input array [size: 2 x 1] */ \
+/* _y : output array [size: 2 x 1] */ \
+void RESAMP2(_synthesizer_execute)(RESAMP2() _q, \
+ TI * _x, \
+ TO * _y); \
+ \
+/* execute resamp2 as half-band decimator */ \
+/* _q : resamp2 object */ \
+/* _x : input array [size: 2 x 1] */ \
+/* _y : output sample pointer */ \
+void RESAMP2(_decim_execute)(RESAMP2() _q, \
+ TI * _x, \
+ TO * _y); \
+ \
+/* execute resamp2 as half-band interpolator */ \
+/* _q : resamp2 object */ \
+/* _x : input sample */ \
+/* _y : output array [size: 2 x 1] */ \
+void RESAMP2(_interp_execute)(RESAMP2() _q, \
+ TI _x, \
+ TO * _y); \
+
+LIQUID_RESAMP2_DEFINE_API(RESAMP2_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_RESAMP2_DEFINE_API(RESAMP2_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_RESAMP2_DEFINE_API(RESAMP2_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+
+//
+// Arbitrary resampler
+//
+#define RESAMP_MANGLE_RRRF(name) LIQUID_CONCAT(resamp_rrrf,name)
+#define RESAMP_MANGLE_CRCF(name) LIQUID_CONCAT(resamp_crcf,name)
+#define RESAMP_MANGLE_CCCF(name) LIQUID_CONCAT(resamp_cccf,name)
+
+#define LIQUID_RESAMP_DEFINE_API(RESAMP,TO,TC,TI) \
+typedef struct RESAMP(_s) * RESAMP(); \
+ \
+/* create arbitrary resampler object */ \
+/* _rate : arbitrary resampling rate */ \
+/* _m : filter semi-length (delay) */ \
+/* _fc : filter cutoff frequency, 0 < _fc < 0.5 */ \
+/* _As : filter stop-band attenuation [dB] */ \
+/* _npfb : number of filters in the bank */ \
+RESAMP() RESAMP(_create)(float _rate, \
+ unsigned int _m, \
+ float _fc, \
+ float _As, \
+ unsigned int _npfb); \
+ \
+/* destroy arbitrary resampler object */ \
+void RESAMP(_destroy)(RESAMP() _q); \
+ \
+/* print resamp object internals to stdout */ \
+void RESAMP(_print)(RESAMP() _q); \
+ \
+/* reset resamp object internals */ \
+void RESAMP(_reset)(RESAMP() _q); \
+ \
+/* get resampler delay (output samples) */ \
+unsigned int RESAMP(_get_delay)(RESAMP() _q); \
+ \
+/* set rate of arbitrary resampler */ \
+void RESAMP(_setrate)(RESAMP() _q, float _rate); \
+ \
+/* execute arbitrary resampler */ \
+/* _q : resamp object */ \
+/* _x : single input sample */ \
+/* _y : output sample array (pointer) */ \
+/* _num_written : number of samples written to _y */ \
+void RESAMP(_execute)(RESAMP() _q, \
+ TI _x, \
+ TO * _y, \
+ unsigned int * _num_written); \
+ \
+/* execute arbitrary resampler on a block of samples */ \
+/* _q : resamp object */ \
+/* _x : input buffer [size: _nx x 1] */ \
+/* _nx : input buffer */ \
+/* _y : output sample array (pointer) */ \
+/* _ny : number of samples written to _y */ \
+void RESAMP(_execute_block)(RESAMP() _q, \
+ TI * _x, \
+ unsigned int _nx, \
+ TO * _y, \
+ unsigned int * _ny); \
+
+LIQUID_RESAMP_DEFINE_API(RESAMP_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_RESAMP_DEFINE_API(RESAMP_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_RESAMP_DEFINE_API(RESAMP_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+
+//
+// Multi-stage half-band resampler
+//
+
+// resampling type (interpolator/decimator)
+typedef enum {
+ LIQUID_RESAMP_INTERP=0, // interpolator
+ LIQUID_RESAMP_DECIM, // decimator
+} liquid_resamp_type;
+
+#define MSRESAMP2_MANGLE_RRRF(name) LIQUID_CONCAT(msresamp2_rrrf,name)
+#define MSRESAMP2_MANGLE_CRCF(name) LIQUID_CONCAT(msresamp2_crcf,name)
+#define MSRESAMP2_MANGLE_CCCF(name) LIQUID_CONCAT(msresamp2_cccf,name)
+
+#define LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2,TO,TC,TI) \
+typedef struct MSRESAMP2(_s) * MSRESAMP2(); \
+ \
+/* create multi-stage half-band resampler */ \
+/* _type : resampler type (e.g. LIQUID_RESAMP_DECIM) */ \
+/* _num_stages : number of resampling stages */ \
+/* _fc : filter cut-off frequency 0 < _fc < 0.5 */ \
+/* _f0 : filter center frequency */ \
+/* _As : stop-band attenuation [dB] */ \
+MSRESAMP2() MSRESAMP2(_create)(int _type, \
+ unsigned int _num_stages, \
+ float _fc, \
+ float _f0, \
+ float _As); \
+ \
+/* destroy multi-stage half-bandresampler */ \
+void MSRESAMP2(_destroy)(MSRESAMP2() _q); \
+ \
+/* print msresamp object internals to stdout */ \
+void MSRESAMP2(_print)(MSRESAMP2() _q); \
+ \
+/* reset msresamp object internal state */ \
+void MSRESAMP2(_reset)(MSRESAMP2() _q); \
+ \
+/* get group delay (number of output samples) */ \
+float MSRESAMP2(_get_delay)(MSRESAMP2() _q); \
+ \
+/* execute multi-stage resampler, M = 2^num_stages */ \
+/* LIQUID_RESAMP_INTERP: input: 1, output: M */ \
+/* LIQUID_RESAMP_DECIM: input: M, output: 1 */ \
+/* _q : msresamp object */ \
+/* _x : input sample array */ \
+/* _y : output sample array */ \
+void MSRESAMP2(_execute)(MSRESAMP2() _q, \
+ TI * _x, \
+ TO * _y); \
+
+LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+
+//
+// Multi-stage arbitrary resampler
+//
+#define MSRESAMP_MANGLE_RRRF(name) LIQUID_CONCAT(msresamp_rrrf,name)
+#define MSRESAMP_MANGLE_CRCF(name) LIQUID_CONCAT(msresamp_crcf,name)
+#define MSRESAMP_MANGLE_CCCF(name) LIQUID_CONCAT(msresamp_cccf,name)
+
+#define LIQUID_MSRESAMP_DEFINE_API(MSRESAMP,TO,TC,TI) \
+typedef struct MSRESAMP(_s) * MSRESAMP(); \
+ \
+/* create multi-stage arbitrary resampler */ \
+/* _r : resampling rate [output/input] */ \
+/* _As : stop-band attenuation [dB] */ \
+MSRESAMP() MSRESAMP(_create)(float _r, \
+ float _As); \
+ \
+/* destroy multi-stage arbitrary resampler */ \
+void MSRESAMP(_destroy)(MSRESAMP() _q); \
+ \
+/* print msresamp object internals to stdout */ \
+void MSRESAMP(_print)(MSRESAMP() _q); \
+ \
+/* reset msresamp object internal state */ \
+void MSRESAMP(_reset)(MSRESAMP() _q); \
+ \
+/* get filter delay (output samples) */ \
+float MSRESAMP(_get_delay)(MSRESAMP() _q); \
+ \
+/* execute multi-stage resampler */ \
+/* _q : msresamp object */ \
+/* _x : input sample array [size: _nx x 1] */ \
+/* _nx : input sample array size */ \
+/* _y : output sample array [size: variable] */ \
+/* _ny : number of samples written to _y */ \
+void MSRESAMP(_execute)(MSRESAMP() _q, \
+ TI * _x, \
+ unsigned int _nx, \
+ TO * _y, \
+ unsigned int * _ny); \
+
+LIQUID_MSRESAMP_DEFINE_API(MSRESAMP_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_MSRESAMP_DEFINE_API(MSRESAMP_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_MSRESAMP_DEFINE_API(MSRESAMP_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+
+//
+// Symbol timing recovery (symbol synchronizer)
+//
+#define SYMSYNC_MANGLE_RRRF(name) LIQUID_CONCAT(symsync_rrrf,name)
+#define SYMSYNC_MANGLE_CRCF(name) LIQUID_CONCAT(symsync_crcf,name)
+
+#define LIQUID_SYMSYNC_DEFINE_API(SYMSYNC,TO,TC,TI) \
+ \
+typedef struct SYMSYNC(_s) * SYMSYNC(); \
+ \
+/* create synchronizer object from external coefficients */ \
+/* _k : samples per symbol */ \
+/* _M : number of filters in the bank */ \
+/* _h : matched filter coefficients [size: */ \
+/* _h_len : length of matched filter */ \
+SYMSYNC() SYMSYNC(_create)(unsigned int _k, \
+ unsigned int _M, \
+ TC * _h, \
+ unsigned int _h_len); \
+ \
+/* create square-root Nyquist symbol synchronizer */ \
+/* _type : filter type (e.g. LIQUID_FIRFILT_RRC) */ \
+/* _k : samples/symbol */ \
+/* _m : symbol delay */ \
+/* _beta : rolloff factor, beta in (0,1] */ \
+/* _M : number of filters in the bank */ \
+SYMSYNC() SYMSYNC(_create_rnyquist)(int _type, \
+ unsigned int _k, \
+ unsigned int _m, \
+ float _beta, \
+ unsigned int _M); \
+ \
+/* create symsync using Kaiser filter interpolator; useful */ \
+/* when the input signal has matched filter applied already */ \
+/* _k : input samples/symbol */ \
+/* _m : symbol delay */ \
+/* _beta : rolloff factor, beta in (0,1] */ \
+/* _M : number of filters in the bank */ \
+SYMSYNC() SYMSYNC(_create_kaiser)(unsigned int _k, \
+ unsigned int _m, \
+ float _beta, \
+ unsigned int _M); \
+ \
+/* destroy symsync object, freeing all internal memory */ \
+void SYMSYNC(_destroy)(SYMSYNC() _q); \
+ \
+/* print symsync object's parameters */ \
+void SYMSYNC(_print)(SYMSYNC() _q); \
+ \
+/* reset symsync internal state */ \
+void SYMSYNC(_reset)(SYMSYNC() _q); \
+ \
+/* lock/unlock loop control */ \
+void SYMSYNC(_lock)( SYMSYNC() _q); \
+void SYMSYNC(_unlock)(SYMSYNC() _q); \
+ \
+/* set synchronizer output rate (samples/symbol) */ \
+/* _q : synchronizer object */ \
+/* _k_out : output samples/symbol */ \
+void SYMSYNC(_set_output_rate)(SYMSYNC() _q, \
+ unsigned int _k_out); \
+ \
+/* set loop-filter bandwidth */ \
+/* _q : synchronizer object */ \
+/* _bt : loop bandwidth */ \
+void SYMSYNC(_set_lf_bw)(SYMSYNC() _q, \
+ float _bt); \
+ \
+/* return instantaneous fractional timing offset estimate */ \
+float SYMSYNC(_get_tau)(SYMSYNC() _q); \
+ \
+/* execute synchronizer on input data array */ \
+/* _q : synchronizer object */ \
+/* _x : input data array */ \
+/* _nx : number of input samples */ \
+/* _y : output data array */ \
+/* _ny : number of samples written to output buffer */ \
+void SYMSYNC(_execute)(SYMSYNC() _q, \
+ TI * _x, \
+ unsigned int _nx, \
+ TO * _y, \
+ unsigned int * _ny); \
+
+LIQUID_SYMSYNC_DEFINE_API(SYMSYNC_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_SYMSYNC_DEFINE_API(SYMSYNC_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+
+//
+// Finite impulse response Farrow filter
+//
+
+#define FIRFARROW_MANGLE_RRRF(name) LIQUID_CONCAT(firfarrow_rrrf,name)
+#define FIRFARROW_MANGLE_CRCF(name) LIQUID_CONCAT(firfarrow_crcf,name)
+//#define FIRFARROW_MANGLE_CCCF(name) LIQUID_CONCAT(firfarrow_cccf,name)
+
+// Macro:
+// FIRFARROW : name-mangling macro
+// TO : output data type
+// TC : coefficients data type
+// TI : input data type
+#define LIQUID_FIRFARROW_DEFINE_API(FIRFARROW,TO,TC,TI) \
+ \
+typedef struct FIRFARROW(_s) * FIRFARROW(); \
+ \
+/* create firfarrow object */ \
+/* _h_len : filter length */ \
+/* _p : polynomial order */ \
+/* _fc : filter cutoff frequency */ \
+/* _As : stopband attenuation [dB] */ \
+FIRFARROW() FIRFARROW(_create)(unsigned int _h_len, \
+ unsigned int _p, \
+ float _fc, \
+ float _As); \
+ \
+/* destroy firfarrow object, freeing all internal memory */ \
+void FIRFARROW(_destroy)(FIRFARROW() _q); \
+ \
+/* print firfarrow object's internal properties */ \
+void FIRFARROW(_print)(FIRFARROW() _q); \
+ \
+/* reset firfarrow object's internal state */ \
+void FIRFARROW(_reset)(FIRFARROW() _q); \
+ \
+/* push sample into firfarrow object */ \
+/* _q : firfarrow object */ \
+/* _x : input sample */ \
+void FIRFARROW(_push)(FIRFARROW() _q, \
+ TI _x); \
+ \
+/* set fractional delay of firfarrow object */ \
+/* _q : firfarrow object */ \
+/* _mu : fractional sample delay */ \
+void FIRFARROW(_set_delay)(FIRFARROW() _q, \
+ float _mu); \
+ \
+/* execute firfarrow internal dot product */ \
+/* _q : firfarrow object */ \
+/* _y : output sample pointer */ \
+void FIRFARROW(_execute)(FIRFARROW() _q, \
+ TO * _y); \
+ \
+/* compute firfarrow filter on block of samples; the input */ \
+/* and output arrays may have the same pointer */ \
+/* _q : firfarrow object */ \
+/* _x : input array [size: _n x 1] */ \
+/* _n : input, output array size */ \
+/* _y : output array [size: _n x 1] */ \
+void FIRFARROW(_execute_block)(FIRFARROW() _q, \
+ TI * _x, \
+ unsigned int _n, \
+ TO * _y); \
+ \
+/* get length of firfarrow object (number of filter taps) */ \
+unsigned int FIRFARROW(_get_length)(FIRFARROW() _q); \
+ \
+/* get coefficients of firfarrow object */ \
+/* _q : firfarrow object */ \
+/* _h : output coefficients pointer */ \
+void FIRFARROW(_get_coefficients)(FIRFARROW() _q, \
+ float * _h); \
+ \
+/* compute complex frequency response */ \
+/* _q : filter object */ \
+/* _fc : frequency */ \
+/* _H : output frequency response */ \
+void FIRFARROW(_freqresponse)(FIRFARROW() _q, \
+ float _fc, \
+ liquid_float_complex * _H); \
+ \
+/* compute group delay [samples] */ \
+/* _q : filter object */ \
+/* _fc : frequency */ \
+float FIRFARROW(_groupdelay)(FIRFARROW() _q, \
+ float _fc); \
+
+LIQUID_FIRFARROW_DEFINE_API(FIRFARROW_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_FIRFARROW_DEFINE_API(FIRFARROW_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+
+
+//
+// MODULE : framing
+//
+
+// framesyncstats : generic frame synchronizer statistic structure
+
+typedef struct {
+ // signal quality
+ float evm; // error vector magnitude [dB]
+ float rssi; // received signal strength indicator [dB]
+ float cfo; // carrier frequency offset (f/Fs)
+
+ // demodulated frame symbols
+ liquid_float_complex * framesyms; // pointer to array [size: framesyms x 1]
+ unsigned int num_framesyms; // length of framesyms
+
+ // modulation/coding scheme etc.
+ unsigned int mod_scheme; // modulation scheme
+ unsigned int mod_bps; // modulation depth (bits/symbol)
+ unsigned int check; // data validity check (crc, checksum)
+ unsigned int fec0; // forward error-correction (inner)
+ unsigned int fec1; // forward error-correction (outer)
+} framesyncstats_s;
+
+// external framesyncstats default object
+extern framesyncstats_s framesyncstats_default;
+
+// initialize framesyncstats object on default
+void framesyncstats_init_default(framesyncstats_s * _stats);
+
+// print framesyncstats object
+void framesyncstats_print(framesyncstats_s * _stats);
+
+// Generic frame synchronizer callback function type
+// _header : header data [size: 8 bytes]
+// _header_valid : is header valid? (0:no, 1:yes)
+// _payload : payload data [size: _payload_len]
+// _payload_len : length of payload (bytes)
+// _payload_valid : is payload valid? (0:no, 1:yes)
+// _stats : frame statistics object
+// _userdata : pointer to userdata
+typedef int (*framesync_callback)(unsigned char * _header,
+ int _header_valid,
+ unsigned char * _payload,
+ unsigned int _payload_len,
+ int _payload_valid,
+ framesyncstats_s _stats,
+ void * _userdata);
+
+// framesync csma callback functions invoked when signal levels is high or low
+// _userdata : user-defined data pointer
+typedef void (*framesync_csma_callback)(void * _userdata);
+
+
+//
+// Basic frame generator (64 bytes data payload)
+//
+
+// frame length in samples
+#define LIQUID_FRAME64_LEN (1340)
+
+typedef struct framegen64_s * framegen64;
+
+// create frame generator
+framegen64 framegen64_create();
+
+// destroy frame generator
+void framegen64_destroy(framegen64 _q);
+
+// print frame generator internal properties
+void framegen64_print(framegen64 _q);
+
+// generate frame
+// _q : frame generator object
+// _header : 8-byte header data
+// _payload : 64-byte payload data
+// _frame : output frame samples [size: LIQUID_FRAME64_LEN x 1]
+void framegen64_execute(framegen64 _q,
+ unsigned char * _header,
+ unsigned char * _payload,
+ liquid_float_complex * _frame);
+
+typedef struct framesync64_s * framesync64;
+
+// create framesync64 object
+// _callback : callback function
+// _userdata : user data pointer passed to callback function
+framesync64 framesync64_create(framesync_callback _callback,
+ void * _userdata);
+
+// destroy frame synchronizer
+void framesync64_destroy(framesync64 _q);
+
+// print frame synchronizer internal properties
+void framesync64_print(framesync64 _q);
+
+// reset frame synchronizer internal state
+void framesync64_reset(framesync64 _q);
+
+// push samples through frame synchronizer
+// _q : frame synchronizer object
+// _x : input samples [size: _n x 1]
+// _n : number of input samples
+void framesync64_execute(framesync64 _q,
+ liquid_float_complex * _x,
+ unsigned int _n);
+
+// enable/disable debugging
+void framesync64_debug_enable(framesync64 _q);
+void framesync64_debug_disable(framesync64 _q);
+void framesync64_debug_print(framesync64 _q, const char * _filename);
+
+#if 0
+// advanced modes
+void framesync64_set_csma_callbacks(framesync64 _q,
+ framesync_csma_callback _csma_lock,
+ framesync_csma_callback _csma_unlock,
+ void * _csma_userdata);
+#endif
+
+//
+// Flexible frame : adjustable payload, mod scheme, etc., but bring
+// your own error correction, redundancy check
+//
+
+// frame generator
+typedef struct {
+ unsigned int check; // data validity check
+ unsigned int fec0; // forward error-correction scheme (inner)
+ unsigned int fec1; // forward error-correction scheme (outer)
+ unsigned int mod_scheme; // modulation scheme
+} flexframegenprops_s;
+
+void flexframegenprops_init_default(flexframegenprops_s * _fgprops);
+
+typedef struct flexframegen_s * flexframegen;
+
+// create flexframegen object
+// _props : frame properties (modulation scheme, etc.)
+flexframegen flexframegen_create(flexframegenprops_s * _props);
+
+// destroy flexframegen object
+void flexframegen_destroy(flexframegen _q);
+
+// print flexframegen object internals
+void flexframegen_print(flexframegen _q);
+
+// reset flexframegen object internals
+void flexframegen_reset(flexframegen _q);
+
+// is frame assembled?
+int flexframegen_is_assembled(flexframegen _q);
+
+// get frame properties
+void flexframegen_getprops(flexframegen _q, flexframegenprops_s * _props);
+
+// set frame properties
+void flexframegen_setprops(flexframegen _q, flexframegenprops_s * _props);
+
+// get length of assembled frame (samples)
+unsigned int flexframegen_getframelen(flexframegen _q);
+
+// assemble a frame from an array of data
+// _q : frame generator object
+// _header : frame header
+// _payload : payload data [size: _payload_len x 1]
+// _payload_len : payload data length
+void flexframegen_assemble(flexframegen _q,
+ unsigned char * _header,
+ unsigned char * _payload,
+ unsigned int _payload_len);
+
+// write samples of assembled frame, two samples at a time, returning
+// '1' when frame is complete, '0' otherwise
+// _q : frame generator object
+// _buffer : output buffer [size: 2 x 1]
+int flexframegen_write_samples(flexframegen _q,
+ liquid_float_complex * _buffer);
+
+// frame synchronizer
+
+typedef struct flexframesync_s * flexframesync;
+
+// create flexframesync object
+// _callback : callback function
+// _userdata : user data pointer passed to callback function
+flexframesync flexframesync_create(framesync_callback _callback,
+ void * _userdata);
+
+// destroy frame synchronizer
+void flexframesync_destroy(flexframesync _q);
+
+// print frame synchronizer internal properties
+void flexframesync_print(flexframesync _q);
+
+// reset frame synchronizer internal state
+void flexframesync_reset(flexframesync _q);
+
+// push samples through frame synchronizer
+// _q : frame synchronizer object
+// _x : input samples [size: _n x 1]
+// _n : number of input samples
+void flexframesync_execute(flexframesync _q,
+ liquid_float_complex * _x,
+ unsigned int _n);
+
+// enable/disable debugging
+void flexframesync_debug_enable(flexframesync _q);
+void flexframesync_debug_disable(flexframesync _q);
+void flexframesync_debug_print(flexframesync _q,
+ const char * _filename);
+#if 0
+// advanced modes
+void flexframesync_set_csma_callbacks(flexframesync _fs,
+ framesync_csma_callback _csma_lock,
+ framesync_csma_callback _csma_unlock,
+ void * _csma_userdata);
+#endif
+
+
+//
+// bpacket : binary packet suitable for data streaming
+//
+
+//
+// bpacket generator/encoder
+//
+typedef struct bpacketgen_s * bpacketgen;
+
+// create bpacketgen object
+// _m : p/n sequence length (ignored)
+// _dec_msg_len : decoded message length (original uncoded data)
+// _crc : data validity check (e.g. cyclic redundancy check)
+// _fec0 : inner forward error-correction code scheme
+// _fec1 : outer forward error-correction code scheme
+bpacketgen bpacketgen_create(unsigned int _m,
+ unsigned int _dec_msg_len,
+ int _crc,
+ int _fec0,
+ int _fec1);
+
+// re-create bpacketgen object from old object
+// _q : old bpacketgen object
+// _m : p/n sequence length (ignored)
+// _dec_msg_len : decoded message length (original uncoded data)
+// _crc : data validity check (e.g. cyclic redundancy check)
+// _fec0 : inner forward error-correction code scheme
+// _fec1 : outer forward error-correction code scheme
+bpacketgen bpacketgen_recreate(bpacketgen _q,
+ unsigned int _m,
+ unsigned int _dec_msg_len,
+ int _crc,
+ int _fec0,
+ int _fec1);
+
+// destroy bpacketgen object, freeing all internally-allocated memory
+void bpacketgen_destroy(bpacketgen _q);
+
+// print bpacketgen internals
+void bpacketgen_print(bpacketgen _q);
+
+// return length of full packet
+unsigned int bpacketgen_get_packet_len(bpacketgen _q);
+
+// encode packet
+void bpacketgen_encode(bpacketgen _q,
+ unsigned char * _msg_dec,
+ unsigned char * _packet);
+
+//
+// bpacket synchronizer/decoder
+//
+typedef struct bpacketsync_s * bpacketsync;
+typedef int (*bpacketsync_callback)(unsigned char * _payload,
+ int _payload_valid,
+ unsigned int _payload_len,
+ framesyncstats_s _stats,
+ void * _userdata);
+bpacketsync bpacketsync_create(unsigned int _m,
+ bpacketsync_callback _callback,
+ void * _userdata);
+void bpacketsync_destroy(bpacketsync _q);
+void bpacketsync_print(bpacketsync _q);
+void bpacketsync_reset(bpacketsync _q);
+
+// run synchronizer on array of input bytes
+// _q : bpacketsync object
+// _bytes : input data array [size: _n x 1]
+// _n : input array size
+void bpacketsync_execute(bpacketsync _q,
+ unsigned char * _bytes,
+ unsigned int _n);
+
+// run synchronizer on input byte
+// _q : bpacketsync object
+// _byte : input byte
+void bpacketsync_execute_byte(bpacketsync _q,
+ unsigned char _byte);
+
+// run synchronizer on input symbol
+// _q : bpacketsync object
+// _sym : input symbol with _bps significant bits
+// _bps : number of bits in input symbol
+void bpacketsync_execute_sym(bpacketsync _q,
+ unsigned char _sym,
+ unsigned int _bps);
+
+// execute one bit at a time
+void bpacketsync_execute_bit(bpacketsync _q,
+ unsigned char _bit);
+
+//
+// GMSK frame generator
+//
+
+typedef struct gmskframegen_s * gmskframegen;
+
+// create GMSK frame generator
+gmskframegen gmskframegen_create();
+void gmskframegen_destroy(gmskframegen _fg);
+void gmskframegen_print(gmskframegen _fg);
+void gmskframegen_reset(gmskframegen _fg);
+void gmskframegen_assemble(gmskframegen _fg,
+ unsigned char * _header,
+ unsigned char * _payload,
+ unsigned int _payload_len,
+ crc_scheme _check,
+ fec_scheme _fec0,
+ fec_scheme _fec1);
+unsigned int gmskframegen_getframelen(gmskframegen _q);
+int gmskframegen_write_samples(gmskframegen _fg,
+ liquid_float_complex * _y);
+
+
+//
+// GMSK frame synchronizer
+//
+
+typedef struct gmskframesync_s * gmskframesync;
+
+// create GMSK frame synchronizer
+// _callback : callback function
+// _userdata : user data pointer passed to callback function
+gmskframesync gmskframesync_create(framesync_callback _callback,
+ void * _userdata);
+void gmskframesync_destroy(gmskframesync _q);
+void gmskframesync_print(gmskframesync _q);
+void gmskframesync_reset(gmskframesync _q);
+void gmskframesync_execute(gmskframesync _q,
+ liquid_float_complex * _x,
+ unsigned int _n);
+
+// debugging
+void gmskframesync_debug_enable(gmskframesync _q);
+void gmskframesync_debug_disable(gmskframesync _q);
+void gmskframesync_debug_print(gmskframesync _q, const char * _filename);
+
+
+//
+// OFDM flexframe generator
+//
+
+// ofdm frame generator properties
+typedef struct {
+ unsigned int check; // data validity check
+ unsigned int fec0; // forward error-correction scheme (inner)
+ unsigned int fec1; // forward error-correction scheme (outer)
+ unsigned int mod_scheme; // modulation scheme
+ //unsigned int block_size; // framing block size
+} ofdmflexframegenprops_s;
+void ofdmflexframegenprops_init_default(ofdmflexframegenprops_s * _props);
+
+typedef struct ofdmflexframegen_s * ofdmflexframegen;
+
+// create OFDM flexible framing generator object
+// _M : number of subcarriers, >10 typical
+// _cp_len : cyclic prefix length
+// _taper_len : taper length (OFDM symbol overlap)
+// _p : subcarrier allocation (null, pilot, data), [size: _M x 1]
+// _fgprops : frame properties (modulation scheme, etc.)
+ofdmflexframegen ofdmflexframegen_create(unsigned int _M,
+ unsigned int _cp_len,
+ unsigned int _taper_len,
+ unsigned char * _p,
+ ofdmflexframegenprops_s * _fgprops);
+
+// destroy ofdmflexframegen object
+void ofdmflexframegen_destroy(ofdmflexframegen _q);
+
+// print parameters, properties, etc.
+void ofdmflexframegen_print(ofdmflexframegen _q);
+
+// reset ofdmflexframegen object internals
+void ofdmflexframegen_reset(ofdmflexframegen _q);
+
+// is frame assembled?
+int ofdmflexframegen_is_assembled(ofdmflexframegen _q);
+
+// get properties
+void ofdmflexframegen_getprops(ofdmflexframegen _q,
+ ofdmflexframegenprops_s * _props);
+
+// set properties
+void ofdmflexframegen_setprops(ofdmflexframegen _q,
+ ofdmflexframegenprops_s * _props);
+
+// get length of frame (symbols)
+// _q : OFDM frame generator object
+unsigned int ofdmflexframegen_getframelen(ofdmflexframegen _q);
+
+// assemble a frame from an array of data
+// _q : OFDM frame generator object
+// _header : frame header [8 bytes]
+// _payload : payload data [size: _payload_len x 1]
+// _payload_len : payload data length
+void ofdmflexframegen_assemble(ofdmflexframegen _q,
+ unsigned char * _header,
+ unsigned char * _payload,
+ unsigned int _payload_len);
+
+// write symbols of assembled frame
+// _q : OFDM frame generator object
+// _buffer : output buffer [size: M+cp_len x 1]
+int ofdmflexframegen_writesymbol(ofdmflexframegen _q,
+ liquid_float_complex * _buffer);
+
+//
+// OFDM flex frame synchronizer
+//
+
+typedef struct ofdmflexframesync_s * ofdmflexframesync;
+
+// create OFDM flexible framing synchronizer object
+// _M : number of subcarriers
+// _cp_len : cyclic prefix length
+// _taper_len : taper length (OFDM symbol overlap)
+// _p : subcarrier allocation (null, pilot, data), [size: _M x 1]
+// _callback : user-defined callback function
+// _userdata : user-defined data pointer
+ofdmflexframesync ofdmflexframesync_create(unsigned int _M,
+ unsigned int _cp_len,
+ unsigned int _taper_len,
+ unsigned char * _p,
+ framesync_callback _callback,
+ void * _userdata);
+
+void ofdmflexframesync_destroy(ofdmflexframesync _q);
+void ofdmflexframesync_print(ofdmflexframesync _q);
+void ofdmflexframesync_reset(ofdmflexframesync _q);
+void ofdmflexframesync_execute(ofdmflexframesync _q,
+ liquid_float_complex * _x,
+ unsigned int _n);
+
+// query the received signal strength indication
+float ofdmflexframesync_get_rssi(ofdmflexframesync _q);
+
+// query the received carrier offset estimate
+float ofdmflexframesync_get_cfo(ofdmflexframesync _q);
+
+// enable/disable debugging
+void ofdmflexframesync_debug_enable(ofdmflexframesync _q);
+void ofdmflexframesync_debug_disable(ofdmflexframesync _q);
+void ofdmflexframesync_debug_print(ofdmflexframesync _q,
+ const char * _filename);
+
+
+
+//
+// Binary P/N synchronizer
+//
+#define BSYNC_MANGLE_RRRF(name) LIQUID_CONCAT(bsync_rrrf,name)
+#define BSYNC_MANGLE_CRCF(name) LIQUID_CONCAT(bsync_crcf,name)
+#define BSYNC_MANGLE_CCCF(name) LIQUID_CONCAT(bsync_cccf,name)
+
+// Macro:
+// BSYNC : name-mangling macro
+// TO : output data type
+// TC : coefficients data type
+// TI : input data type
+#define LIQUID_BSYNC_DEFINE_API(BSYNC,TO,TC,TI) \
+typedef struct BSYNC(_s) * BSYNC(); \
+ \
+BSYNC() BSYNC(_create)(unsigned int _n, TC * _v); \
+ \
+/* create binary synchronizer from m-sequence */ \
+/* _g : m-sequence generator polynomial */ \
+/* _k : samples/symbol (over-sampling factor) */ \
+BSYNC() BSYNC(_create_msequence)(unsigned int _g, \
+ unsigned int _k); \
+void BSYNC(_destroy)(BSYNC() _fs); \
+void BSYNC(_print)(BSYNC() _fs); \
+void BSYNC(_correlate)(BSYNC() _fs, TI _sym, TO * _y);
+
+LIQUID_BSYNC_DEFINE_API(BSYNC_MANGLE_RRRF,
+ float,
+ float,
+ float)
+
+LIQUID_BSYNC_DEFINE_API(BSYNC_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_BSYNC_DEFINE_API(BSYNC_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+
+//
+// Pre-demodulation synchronizers (binary and otherwise)
+//
+#define PRESYNC_MANGLE_CCCF(name) LIQUID_CONCAT( presync_cccf,name)
+#define BPRESYNC_MANGLE_CCCF(name) LIQUID_CONCAT(bpresync_cccf,name)
+
+// Macro:
+// PRESYNC : name-mangling macro
+// TO : output data type
+// TC : coefficients data type
+// TI : input data type
+#define LIQUID_PRESYNC_DEFINE_API(PRESYNC,TO,TC,TI) \
+typedef struct PRESYNC(_s) * PRESYNC(); \
+ \
+/* create pre-demod synchronizer */ \
+/* _v : baseband sequence */ \
+/* _n : baseband sequence length */ \
+/* _dphi_max : maximum absolute frequency deviation */ \
+/* _m : number of correlators */ \
+PRESYNC() PRESYNC(_create)(TC * _v, \
+ unsigned int _n, \
+ float _dphi_max, \
+ unsigned int _m); \
+ \
+/* destroy pre-demod synchronizer */ \
+void PRESYNC(_destroy)(PRESYNC() _q); \
+ \
+/* print pre-demod synchronizer internal state */ \
+void PRESYNC(_print)(PRESYNC() _q); \
+ \
+/* reset pre-demod synchronizer internal state */ \
+void PRESYNC(_reset)(PRESYNC() _q); \
+ \
+/* push input sample into pre-demod synchronizer */ \
+/* _q : pre-demod synchronizer object */ \
+/* _x : input sample */ \
+void PRESYNC(_push)(PRESYNC() _q, \
+ TI _x); \
+ \
+/* correlate input sequence */ \
+/* _q : pre-demod synchronizer object */ \
+/* _rxy : output cross correlation */ \
+/* _dphi_hat : output frequency offset estiamte */ \
+void PRESYNC(_correlate)(PRESYNC() _q, \
+ TO * _rxy, \
+ float * _dphi_hat); \
+
+// non-binary pre-demodulation synchronizer
+LIQUID_PRESYNC_DEFINE_API(PRESYNC_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+// binary pre-demodulation synchronizer
+LIQUID_PRESYNC_DEFINE_API(BPRESYNC_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+//
+// Pre-demodulation detector
+//
+
+typedef struct detector_cccf_s * detector_cccf;
+
+// create pre-demod detector
+// _s : sequence
+// _n : sequence length
+// _threshold : detection threshold (default: 0.7)
+// _dphi_max : maximum carrier offset
+detector_cccf detector_cccf_create(liquid_float_complex * _s,
+ unsigned int _n,
+ float _threshold,
+ float _dphi_max);
+
+// destroy pre-demo detector object
+void detector_cccf_destroy(detector_cccf _q);
+
+// print pre-demod detector internal state
+void detector_cccf_print(detector_cccf _q);
+
+// reset pre-demod detector internal state
+void detector_cccf_reset(detector_cccf _q);
+
+// Run sample through pre-demod detector's correlator.
+// Returns '1' if signal was detected, '0' otherwise
+// _q : pre-demod detector
+// _x : input sample
+// _tau_hat : fractional sample offset estimate (set when detected)
+// _dphi_hat : carrier frequency offset estimate (set when detected)
+// _gamma_hat : channel gain estimate (set when detected)
+int detector_cccf_correlate(detector_cccf _q,
+ liquid_float_complex _x,
+ float * _tau_hat,
+ float * _dphi_hat,
+ float * _gamma_hat);
+
+
+//
+// MODULE : math
+//
+
+// ln( Gamma(z) )
+float liquid_lngammaf(float _z);
+
+// Gamma(z)
+float liquid_gammaf(float _z);
+
+// ln( gamma(z,alpha) ) : lower incomplete gamma function
+float liquid_lnlowergammaf(float _z, float _alpha);
+
+// ln( Gamma(z,alpha) ) : upper incomplete gamma function
+float liquid_lnuppergammaf(float _z, float _alpha);
+
+// gamma(z,alpha) : lower incomplete gamma function
+float liquid_lowergammaf(float _z, float _alpha);
+
+// Gamma(z,alpha) : upper incomplete gamma function
+float liquid_uppergammaf(float _z, float _alpha);
+
+// n!
+float liquid_factorialf(unsigned int _n);
+
+
+
+// ln(I_v(z)) : log Modified Bessel function of the first kind
+float liquid_lnbesselif(float _nu, float _z);
+
+// I_v(z) : Modified Bessel function of the first kind
+float liquid_besselif(float _nu, float _z);
+
+// I_0(z) : Modified Bessel function of the first kind (order zero)
+float liquid_besseli0f(float _z);
+
+// J_v(z) : Bessel function of the first kind
+float liquid_besseljf(float _nu, float _z);
+
+// J_0(z) : Bessel function of the first kind (order zero)
+float liquid_besselj0f(float _z);
+
+
+// Q function
+float liquid_Qf(float _z);
+
+// Marcum Q-function
+float liquid_MarcumQf(int _M,
+ float _alpha,
+ float _beta);
+
+// Marcum Q-function (M=1)
+float liquid_MarcumQ1f(float _alpha,
+ float _beta);
+
+// sin(pi x) / (pi x)
+float sincf(float _x);
+
+// next power of 2 : y = ceil(log2(_x))
+unsigned int liquid_nextpow2(unsigned int _x);
+
+// (n choose k) = n! / ( k! (n-k)! )
+float liquid_nchoosek(unsigned int _n, unsigned int _k);
+
+//
+// Windowing functions
+//
+
+// Kaiser-Bessel derived window (single sample)
+// _n : index (0 <= _n < _N)
+// _N : length of filter (must be even)
+// _beta : Kaiser window parameter (_beta > 0)
+float liquid_kbd(unsigned int _n, unsigned int _N, float _beta);
+
+// Kaiser-Bessel derived window (full window)
+// _n : length of filter (must be even)
+// _beta : Kaiser window parameter (_beta > 0)
+// _w : resulting window
+void liquid_kbd_window(unsigned int _n, float _beta, float * _w);
+
+// Kaiser window
+// _n : window index
+// _N : full window length
+// _beta : Kaiser-Bessel window shape parameter
+// _dt : fractional sample offset
+float kaiser(unsigned int _n,
+ unsigned int _N,
+ float _beta,
+ float _dt);
+
+// Hamming window
+// _n : window index
+// _N : full window length
+float hamming(unsigned int _n, unsigned int _N);
+
+// Hann window
+// _n : window index
+// _N : full window length
+float hann(unsigned int _n, unsigned int _N);
+
+// Blackman-harris window
+// _n : window index
+// _N : full window length
+float blackmanharris(unsigned int _n, unsigned int _N);
+
+
+// polynomials
+
+
+#define POLY_MANGLE_DOUBLE(name) LIQUID_CONCAT(poly, name)
+#define POLY_MANGLE_FLOAT(name) LIQUID_CONCAT(polyf, name)
+
+#define POLY_MANGLE_CDOUBLE(name) LIQUID_CONCAT(polyc, name)
+#define POLY_MANGLE_CFLOAT(name) LIQUID_CONCAT(polycf, name)
+
+// large macro
+// POLY : name-mangling macro
+// T : data type
+// TC : data type (complex)
+#define LIQUID_POLY_DEFINE_API(POLY,T,TC) \
+/* evaluate polynomial _p (order _k-1) at value _x */ \
+T POLY(_val)(T * _p, unsigned int _k, T _x); \
+ \
+/* least-squares polynomial fit (order _k-1) */ \
+void POLY(_fit)(T * _x, \
+ T * _y, \
+ unsigned int _n, \
+ T * _p, \
+ unsigned int _k); \
+ \
+/* Lagrange polynomial exact fit (order _n-1) */ \
+void POLY(_fit_lagrange)(T * _x, \
+ T * _y, \
+ unsigned int _n, \
+ T * _p); \
+ \
+/* Lagrange polynomial interpolation */ \
+T POLY(_interp_lagrange)(T * _x, \
+ T * _y, \
+ unsigned int _n, \
+ T _x0); \
+ \
+/* Lagrange polynomial fit (barycentric form) */ \
+void POLY(_fit_lagrange_barycentric)(T * _x, \
+ unsigned int _n, \
+ T * _w); \
+ \
+/* Lagrange polynomial interpolation (barycentric form) */ \
+T POLY(_val_lagrange_barycentric)(T * _x, \
+ T * _y, \
+ T * _w, \
+ T _x0, \
+ unsigned int _n); \
+ \
+/* expands the polynomial: \
+ * P_n(x) = (1+x)^n \
+ * as \
+ * P_n(x) = p[0] + p[1]*x + p[2]*x^2 + ... + p[n]x^n \
+ * NOTE: _p has order n=m+k (array is length n+1) \
+ */ \
+void POLY(_expandbinomial)(unsigned int _n, \
+ T * _p); \
+ \
+/* expands the polynomial: \
+ * P_n(x) = (1+x)^m * (1-x)^k \
+ * as \
+ * P_n(x) = p[0] + p[1]*x + p[2]*x^2 + ... + p[n]x^n \
+ * NOTE: _p has order n=m+k (array is length n+1) \
+ */ \
+void POLY(_expandbinomial_pm)(unsigned int _m, \
+ unsigned int _k, \
+ T * _p); \
+ \
+/* expands the polynomial: \
+ * P_n(x) = (x-r[0]) * (x-r[1]) * ... * (x-r[n-1]) \
+ * as \
+ * P_n(x) = c[0] + c[1]*x + ... + c[n]*x^n \
+ * where r[0],r[1],...,r[n-1] are the roots of P_n(x) \
+ * NOTE: _c has order _n (array is length _n+1) \
+ */ \
+void POLY(_expandroots)(T * _a, \
+ unsigned int _n, \
+ T * _c); \
+ \
+/* expands the polynomial: \
+ * P_n(x) = \
+ * (x*b[0]-a[0]) * (x*b[1]-a[1]) * ... * (x*b[n-1]-a[n-1]) \
+ * as \
+ * P_n(x) = c[0] + c[1]*x + ... + c[n]*x^n \
+ * NOTE: _c has order _n (array is length _n+1) \
+ */ \
+void POLY(_expandroots2)(T * _a, \
+ T * _b, \
+ unsigned int _n, \
+ T * _c); \
+ \
+/* find roots of the polynomial (complex) */ \
+/* _poly : poly array, ascending powers [size: _k x 1] */ \
+/* _k : poly length (poly order = _k - 1) */ \
+/* _roots : resulting complex roots [size: _k-1 x 1] */ \
+void POLY(_findroots)(T * _poly, \
+ unsigned int _n, \
+ TC * _roots); \
+ \
+/* find the complex roots of the polynomial using the */ \
+/* Durand-Kerner method */ \
+void POLY(_findroots_durandkerner)(T * _poly, \
+ unsigned int _k, \
+ TC * _roots); \
+ \
+/* find the complex roots of the polynomial using */ \
+/* Bairstow's method */ \
+void POLY(_findroots_bairstow)(T * _poly, \
+ unsigned int _k, \
+ TC * _roots); \
+ \
+/* expands the multiplication of two polynomials */ \
+void POLY(_mul)(T * _a, \
+ unsigned int _order_a, \
+ T * _b, \
+ unsigned int _order_b, \
+ T * _c); \
+
+LIQUID_POLY_DEFINE_API(POLY_MANGLE_DOUBLE,
+ double,
+ liquid_double_complex)
+
+LIQUID_POLY_DEFINE_API(POLY_MANGLE_FLOAT,
+ float,
+ liquid_float_complex)
+
+LIQUID_POLY_DEFINE_API(POLY_MANGLE_CDOUBLE,
+ liquid_double_complex,
+ liquid_double_complex)
+
+LIQUID_POLY_DEFINE_API(POLY_MANGLE_CFLOAT,
+ liquid_float_complex,
+ liquid_float_complex)
+
+#if 0
+// expands the polynomial: (1+x)^n
+void poly_binomial_expand(unsigned int _n, int * _c);
+
+// expands the polynomial: (1+x)^k * (1-x)^(n-k)
+void poly_binomial_expand_pm(unsigned int _n,
+ unsigned int _k,
+ int * _c);
+#endif
+
+//
+// modular arithmetic, etc.
+//
+
+// maximum number of factors
+#define LIQUID_MAX_FACTORS (40)
+
+// is number prime?
+int liquid_is_prime(unsigned int _n);
+
+// compute number's prime factors
+// _n : number to factor
+// _factors : pre-allocated array of factors [size: LIQUID_MAX_FACTORS x 1]
+// _num_factors: number of factors found, sorted ascending
+void liquid_factor(unsigned int _n,
+ unsigned int * _factors,
+ unsigned int * _num_factors);
+
+// compute number's unique prime factors
+// _n : number to factor
+// _factors : pre-allocated array of factors [size: LIQUID_MAX_FACTORS x 1]
+// _num_factors: number of unique factors found, sorted ascending
+void liquid_unique_factor(unsigned int _n,
+ unsigned int * _factors,
+ unsigned int * _num_factors);
+
+// compute c = base^exp (mod n)
+unsigned int liquid_modpow(unsigned int _base,
+ unsigned int _exp,
+ unsigned int _n);
+
+// find smallest primitive root of _n
+unsigned int liquid_primitive_root(unsigned int _n);
+
+// find smallest primitive root of _n, assuming _n is prime
+unsigned int liquid_primitive_root_prime(unsigned int _n);
+
+// Euler's totient function
+unsigned int liquid_totient(unsigned int _n);
+
+
+//
+// MODULE : matrix
+//
+
+#define MATRIX_MANGLE_DOUBLE(name) LIQUID_CONCAT(matrix, name)
+#define MATRIX_MANGLE_FLOAT(name) LIQUID_CONCAT(matrixf, name)
+
+#define MATRIX_MANGLE_CDOUBLE(name) LIQUID_CONCAT(matrixc, name)
+#define MATRIX_MANGLE_CFLOAT(name) LIQUID_CONCAT(matrixcf, name)
+
+// large macro
+// MATRIX : name-mangling macro
+// T : data type
+#define LIQUID_MATRIX_DEFINE_API(MATRIX,T) \
+void MATRIX(_print)(T * _x, \
+ unsigned int _rx, \
+ unsigned int _cx); \
+void MATRIX(_add)(T * _x, \
+ T * _y, \
+ T * _z, \
+ unsigned int _r, \
+ unsigned int _c); \
+void MATRIX(_sub)(T * _x, \
+ T * _y, \
+ T * _z, \
+ unsigned int _r, \
+ unsigned int _c); \
+void MATRIX(_pmul)(T * _x, \
+ T * _y, \
+ T * _z, \
+ unsigned int _r, \
+ unsigned int _c); \
+void MATRIX(_pdiv)(T * _x, \
+ T * _y, \
+ T * _z, \
+ unsigned int _r, \
+ unsigned int _c); \
+void MATRIX(_mul)(T * _x, unsigned int _rx, unsigned int _cx, \
+ T * _y, unsigned int _ry, unsigned int _cy, \
+ T * _z, unsigned int _rz, unsigned int _cz); \
+void MATRIX(_div)(T * _x, T * _y, T * _z, unsigned int _n); \
+T MATRIX(_det)(T * _x, unsigned int _r, unsigned int _c); \
+void MATRIX(_trans)(T * _x, unsigned int _rx, unsigned int _cx);\
+void MATRIX(_hermitian)(T * _x, \
+ unsigned int _rx, \
+ unsigned int _cx); \
+ \
+/* compute x*x' on [m x n] matrix, result: [m x m] */ \
+void MATRIX(_mul_transpose)(T * _x, \
+ unsigned int _m, \
+ unsigned int _n, \
+ T * _xxT); \
+/* compute x'*x on [m x n] matrix, result: [n x n] */ \
+void MATRIX(_transpose_mul)(T * _x, \
+ unsigned int _m, \
+ unsigned int _n, \
+ T * _xTx); \
+/* compute x*x.' on [m x n] matrix, result: [m x m] */ \
+void MATRIX(_mul_hermitian)(T * _x, \
+ unsigned int _m, \
+ unsigned int _n, \
+ T * _xxH); \
+/* compute x.'*x on [m x n] matrix, result: [n x n] */ \
+void MATRIX(_hermitian_mul)(T * _x, \
+ unsigned int _m, \
+ unsigned int _n, \
+ T * _xHx); \
+ \
+void MATRIX(_aug)(T * _x, unsigned int _rx, unsigned int _cx, \
+ T * _y, unsigned int _ry, unsigned int _cy, \
+ T * _z, unsigned int _rz, unsigned int _cz); \
+void MATRIX(_inv)(T * _x, \
+ unsigned int _rx, \
+ unsigned int _cx); \
+void MATRIX(_eye)(T * _x, \
+ unsigned int _n); \
+void MATRIX(_ones)(T * _x, \
+ unsigned int _r, \
+ unsigned int _c); \
+void MATRIX(_zeros)(T * _x, \
+ unsigned int _r, \
+ unsigned int _c); \
+void MATRIX(_gjelim)(T * _x, \
+ unsigned int _rx, \
+ unsigned int _cx); \
+void MATRIX(_pivot)(T * _x, \
+ unsigned int _rx, \
+ unsigned int _cx, \
+ unsigned int _r, \
+ unsigned int _c); \
+void MATRIX(_swaprows)(T * _x, \
+ unsigned int _rx, \
+ unsigned int _cx, \
+ unsigned int _r1, \
+ unsigned int _r2); \
+void MATRIX(_linsolve)(T * _A, \
+ unsigned int _r, \
+ T * _b, \
+ T * _x, \
+ void * _opts); \
+void MATRIX(_cgsolve)(T * _A, \
+ unsigned int _r, \
+ T * _b, \
+ T * _x, \
+ void * _opts); \
+void MATRIX(_ludecomp_crout)(T * _x, \
+ unsigned int _rx, \
+ unsigned int _cx, \
+ T * _L, \
+ T * _U, \
+ T * _P); \
+void MATRIX(_ludecomp_doolittle)(T * _x, \
+ unsigned int _rx, \
+ unsigned int _cx, \
+ T * _L, \
+ T * _U, \
+ T * _P); \
+void MATRIX(_gramschmidt)(T * _A, \
+ unsigned int _rx, \
+ unsigned int _cx, \
+ T * _U); \
+void MATRIX(_qrdecomp_gramschmidt)(T * _x, \
+ unsigned int _rx, \
+ unsigned int _cx, \
+ T * _Q, \
+ T * _R); \
+void MATRIX(_chol)(T * _A, \
+ unsigned int _n, \
+ T * _L); \
+
+#define matrix_access(X,R,C,r,c) ((X)[(r)*(C)+(c)])
+
+#define matrixc_access(X,R,C,r,c) matrix_access(X,R,C,r,c)
+#define matrixf_access(X,R,C,r,c) matrix_access(X,R,C,r,c)
+#define matrixcf_access(X,R,C,r,c) matrix_access(X,R,C,r,c)
+
+LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_FLOAT, float)
+LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_DOUBLE, double)
+
+LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_CFLOAT, liquid_float_complex)
+LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_CDOUBLE, liquid_double_complex)
+
+
+#define SMATRIX_MANGLE_BOOL(name) LIQUID_CONCAT(smatrixb, name)
+#define SMATRIX_MANGLE_FLOAT(name) LIQUID_CONCAT(smatrixf, name)
+#define SMATRIX_MANGLE_INT(name) LIQUID_CONCAT(smatrixi, name)
+
+// sparse 'alist' matrix type (similar to MacKay, Davey Lafferty convention)
+// large macro
+// SMATRIX : name-mangling macro
+// T : primitive data type
+#define LIQUID_SMATRIX_DEFINE_API(SMATRIX,T) \
+typedef struct SMATRIX(_s) * SMATRIX(); \
+ \
+/* create _M x _N matrix, initialized with zeros */ \
+SMATRIX() SMATRIX(_create)(unsigned int _M, \
+ unsigned int _N); \
+ \
+/* create _M x _N matrix, initialized on array */ \
+SMATRIX() SMATRIX(_create_array)(T * _x, \
+ unsigned int _m, \
+ unsigned int _n); \
+ \
+/* destroy object */ \
+void SMATRIX(_destroy)(SMATRIX() _q); \
+ \
+/* print compact form */ \
+void SMATRIX(_print)(SMATRIX() _q); \
+ \
+/* print expanded form */ \
+void SMATRIX(_print_expanded)(SMATRIX() _q); \
+ \
+/* query properties methods */ \
+void SMATRIX(_size)(SMATRIX() _q, \
+ unsigned int * _m, \
+ unsigned int * _n); \
+ \
+/* zero all elements */ \
+void SMATRIX(_clear)(SMATRIX() _q); /* zero and keep memory */ \
+void SMATRIX(_reset)(SMATRIX() _q); /* zero and clear memory */ \
+ \
+/* determine if value has been set (allocated memory) */ \
+int SMATRIX(_isset)(SMATRIX() _q, \
+ unsigned int _m, \
+ unsigned int _n); \
+ \
+/* inserts/deletes element at index (memory allocation) */ \
+void SMATRIX(_insert)(SMATRIX() _q, \
+ unsigned int _m, \
+ unsigned int _n, \
+ T _v); \
+void SMATRIX(_delete)(SMATRIX() _q, \
+ unsigned int _m, \
+ unsigned int _n); \
+ \
+/* sets/gets the value (with memory allocation if needed) */ \
+void SMATRIX(_set)(SMATRIX() _q, \
+ unsigned int _m, \
+ unsigned int _n, \
+ T _v); \
+T SMATRIX(_get)(SMATRIX() _q, \
+ unsigned int _m, \
+ unsigned int _n); \
+ \
+/* initialize to identity matrix */ \
+void SMATRIX(_eye)(SMATRIX() _q); \
+ \
+/* multiply two sparse binary matrices */ \
+void SMATRIX(_mul)(SMATRIX() _x, \
+ SMATRIX() _y, \
+ SMATRIX() _z); \
+ \
+/* multiply sparse matrix by vector */ \
+/* _q : sparse matrix */ \
+/* _x : input vector [size: _N x 1] */ \
+/* _y : output vector [size: _M x 1] */ \
+void SMATRIX(_vmul)(SMATRIX() _q, \
+ T * _x, \
+ T * _y); \
+
+LIQUID_SMATRIX_DEFINE_API(SMATRIX_MANGLE_BOOL, unsigned char)
+LIQUID_SMATRIX_DEFINE_API(SMATRIX_MANGLE_FLOAT, float)
+LIQUID_SMATRIX_DEFINE_API(SMATRIX_MANGLE_INT, short int)
+
+//
+// smatrix cross methods
+//
+
+// multiply sparse binary matrix by floating-point matrix
+// _q : sparse matrix [size: A->M x A->N]
+// _x : input vector [size: mx x nx ]
+// _y : output vector [size: my x ny ]
+void smatrixb_mulf(smatrixb _A,
+ float * _x,
+ unsigned int _mx,
+ unsigned int _nx,
+ float * _y,
+ unsigned int _my,
+ unsigned int _ny);
+
+// multiply sparse binary matrix by floating-point vector
+// _q : sparse matrix
+// _x : input vector [size: _N x 1]
+// _y : output vector [size: _M x 1]
+void smatrixb_vmulf(smatrixb _q,
+ float * _x,
+ float * _y);
+
+
+//
+// MODULE : modem (modulator/demodulator)
+//
+
+// Maximum number of allowed bits per symbol
+#define MAX_MOD_BITS_PER_SYMBOL 8
+
+// Modulation schemes available
+#define LIQUID_MODEM_NUM_SCHEMES (52)
+
+typedef enum {
+ LIQUID_MODEM_UNKNOWN=0, // Unknown modulation scheme
+
+ // Phase-shift keying (PSK)
+ LIQUID_MODEM_PSK2, LIQUID_MODEM_PSK4,
+ LIQUID_MODEM_PSK8, LIQUID_MODEM_PSK16,
+ LIQUID_MODEM_PSK32, LIQUID_MODEM_PSK64,
+ LIQUID_MODEM_PSK128, LIQUID_MODEM_PSK256,
+
+ // Differential phase-shift keying (DPSK)
+ LIQUID_MODEM_DPSK2, LIQUID_MODEM_DPSK4,
+ LIQUID_MODEM_DPSK8, LIQUID_MODEM_DPSK16,
+ LIQUID_MODEM_DPSK32, LIQUID_MODEM_DPSK64,
+ LIQUID_MODEM_DPSK128, LIQUID_MODEM_DPSK256,
+
+ // amplitude-shift keying
+ LIQUID_MODEM_ASK2, LIQUID_MODEM_ASK4,
+ LIQUID_MODEM_ASK8, LIQUID_MODEM_ASK16,
+ LIQUID_MODEM_ASK32, LIQUID_MODEM_ASK64,
+ LIQUID_MODEM_ASK128, LIQUID_MODEM_ASK256,
+
+ // rectangular quadrature amplitude-shift keying (QAM)
+ LIQUID_MODEM_QAM4,
+ LIQUID_MODEM_QAM8, LIQUID_MODEM_QAM16,
+ LIQUID_MODEM_QAM32, LIQUID_MODEM_QAM64,
+ LIQUID_MODEM_QAM128, LIQUID_MODEM_QAM256,
+
+ // amplitude phase-shift keying (APSK)
+ LIQUID_MODEM_APSK4,
+ LIQUID_MODEM_APSK8, LIQUID_MODEM_APSK16,
+ LIQUID_MODEM_APSK32, LIQUID_MODEM_APSK64,
+ LIQUID_MODEM_APSK128, LIQUID_MODEM_APSK256,
+
+ // specific modem types
+ LIQUID_MODEM_BPSK, // Specific: binary PSK
+ LIQUID_MODEM_QPSK, // specific: quaternary PSK
+ LIQUID_MODEM_OOK, // Specific: on/off keying
+ LIQUID_MODEM_SQAM32, // 'square' 32-QAM
+ LIQUID_MODEM_SQAM128, // 'square' 128-QAM
+ LIQUID_MODEM_V29, // V.29 star constellation
+ LIQUID_MODEM_ARB16OPT, // optimal 16-QAM
+ LIQUID_MODEM_ARB32OPT, // optimal 32-QAM
+ LIQUID_MODEM_ARB64OPT, // optimal 64-QAM
+ LIQUID_MODEM_ARB128OPT, // optimal 128-QAM
+ LIQUID_MODEM_ARB256OPT, // optimal 256-QAM
+ LIQUID_MODEM_ARB64VT, // Virginia Tech logo
+
+ // arbitrary modem type
+ LIQUID_MODEM_ARB // arbitrary QAM
+} modulation_scheme;
+
+// structure for holding full modulation type descriptor
+struct modulation_type_s {
+ const char * name; // short name (e.g. 'bpsk')
+ const char * fullname; // full name (e.g. 'binary phase-shift keying')
+ modulation_scheme scheme; // modulation scheme (e.g. LIQUID_MODEM_BPSK)
+ unsigned int bps; // modulation depth (e.g. 1)
+};
+
+// full modulation type descriptor
+extern const struct modulation_type_s modulation_types[LIQUID_MODEM_NUM_SCHEMES];
+
+// Print compact list of existing and available modulation schemes
+void liquid_print_modulation_schemes();
+
+// returns modulation_scheme based on input string
+modulation_scheme liquid_getopt_str2mod(const char * _str);
+
+// query basic modulation types
+int liquid_modem_is_psk(modulation_scheme _ms);
+int liquid_modem_is_dpsk(modulation_scheme _ms);
+int liquid_modem_is_ask(modulation_scheme _ms);
+int liquid_modem_is_qam(modulation_scheme _ms);
+int liquid_modem_is_apsk(modulation_scheme _ms);
+
+// useful functions
+
+// counts the number of different bits between two symbols
+unsigned int count_bit_errors(unsigned int _s1, unsigned int _s2);
+
+// counts the number of different bits between two arrays of symbols
+// _msg0 : original message [size: _n x 1]
+// _msg1 : copy of original message [size: _n x 1]
+// _n : message size
+unsigned int count_bit_errors_array(unsigned char * _msg0,
+ unsigned char * _msg1,
+ unsigned int _n);
+
+// converts binary-coded decimal (BCD) to gray, ensuring successive values
+// differ by exactly one bit
+unsigned int gray_encode(unsigned int symbol_in);
+
+// converts a gray-encoded symbol to binary-coded decimal (BCD)
+unsigned int gray_decode(unsigned int symbol_in);
+
+// pack soft bits into symbol
+// _soft_bits : soft input bits [size: _bps x 1]
+// _bps : bits per symbol
+// _sym_out : output symbol, value in [0,2^_bps)
+void liquid_pack_soft_bits(unsigned char * _soft_bits,
+ unsigned int _bps,
+ unsigned int * _sym_out);
+
+// unpack soft bits into symbol
+// _sym_in : input symbol, value in [0,2^_bps)
+// _bps : bits per symbol
+// _soft_bits : soft output bits [size: _bps x 1]
+void liquid_unpack_soft_bits(unsigned int _sym_in,
+ unsigned int _bps,
+ unsigned char * _soft_bits);
+
+
+//
+// Linear modem
+//
+
+#define LIQUID_MODEM_MANGLE_FLOAT(name) LIQUID_CONCAT(modem,name)
+
+// Macro : MODEM
+// MODEM : name-mangling macro
+// T : primitive data type
+// TC : primitive data type (complex)
+#define LIQUID_MODEM_DEFINE_API(MODEM,T,TC) \
+ \
+/* define struct pointer */ \
+typedef struct MODEM(_s) * MODEM(); \
+ \
+/* create digital modem object, allocating memory as necessary */ \
+MODEM() MODEM(_create)(modulation_scheme _scheme); \
+ \
+/* create arbitrary digital modem object */ \
+MODEM() MODEM(_create_arbitrary)(TC * _table, unsigned int _M); \
+ \
+/* recreate modulation scheme, re-allocating memory as necessary */ \
+MODEM() MODEM(_recreate)(MODEM() _q, \
+ modulation_scheme _scheme); \
+ \
+void MODEM(_destroy)(MODEM() _q); \
+void MODEM(_print)( MODEM() _q); \
+void MODEM(_reset)( MODEM() _q); \
+ \
+/* generate random symbol */ \
+unsigned int MODEM(_gen_rand_sym)(MODEM() _q); \
+ \
+/* Accessor functions */ \
+unsigned int MODEM(_get_bps)(MODEM() _q); \
+ \
+/* generic modulate function; simply queries modem scheme */ \
+/* and calls appropriate subroutine */ \
+/* _q : modem object */ \
+/* _s : input symbol */ \
+/* _x : output sample */ \
+void MODEM(_modulate)(MODEM() _q, \
+ unsigned int _s, \
+ TC *_y); \
+ \
+/* generic hard-decision demodulation function */ \
+/* _q : modem object */ \
+/* _x : input sample */ \
+/* _s : output symbol */ \
+void MODEM(_demodulate)(MODEM() _q, \
+ TC _x, \
+ unsigned int * _s); \
+ \
+/* generic soft-decision demodulation function */ \
+/* _q : modem object */ \
+/* _x : input sample */ \
+/* _s : output hard symbol */ \
+/* _soft_bits : output soft bits */ \
+void MODEM(_demodulate_soft)(MODEM() _q, \
+ TC _x, \
+ unsigned int * _s, \
+ unsigned char * _soft_bits); \
+ \
+/* get demodulator's estimated transmit sample */ \
+void MODEM(_get_demodulator_sample)(MODEM() _q, \
+ TC * _x_hat); \
+ \
+/* get demodulator phase error */ \
+float MODEM(_get_demodulator_phase_error)(MODEM() _q); \
+ \
+/* get demodulator error vector magnitude */ \
+float MODEM(_get_demodulator_evm)(MODEM() _q); \
+
+// define modem APIs
+LIQUID_MODEM_DEFINE_API(LIQUID_MODEM_MANGLE_FLOAT,float,liquid_float_complex)
+
+
+//
+// continuous-phase modulation
+//
+
+// gmskmod : GMSK modulator
+typedef struct gmskmod_s * gmskmod;
+
+// create gmskmod object
+// _k : samples/symbol
+// _m : filter delay (symbols)
+// _BT : excess bandwidth factor
+gmskmod gmskmod_create(unsigned int _k,
+ unsigned int _m,
+ float _BT);
+void gmskmod_destroy(gmskmod _q);
+void gmskmod_print(gmskmod _q);
+void gmskmod_reset(gmskmod _q);
+void gmskmod_modulate(gmskmod _q,
+ unsigned int _sym,
+ liquid_float_complex * _y);
+
+
+// gmskdem : GMSK demodulator
+typedef struct gmskdem_s * gmskdem;
+
+// create gmskdem object
+// _k : samples/symbol
+// _m : filter delay (symbols)
+// _BT : excess bandwidth factor
+gmskdem gmskdem_create(unsigned int _k,
+ unsigned int _m,
+ float _BT);
+void gmskdem_destroy(gmskdem _q);
+void gmskdem_print(gmskdem _q);
+void gmskdem_reset(gmskdem _q);
+void gmskdem_set_eq_bw(gmskdem _q, float _bw);
+void gmskdem_demodulate(gmskdem _q,
+ liquid_float_complex * _y,
+ unsigned int * _sym);
+
+//
+// Analog frequency modulator
+//
+#define LIQUID_FREQMOD_MANGLE_FLOAT(name) LIQUID_CONCAT(freqmod,name)
+
+// Macro : FREQMOD (analog frequency modulator)
+// FREQMOD : name-mangling macro
+// T : primitive data type
+// TC : primitive data type (complex)
+#define LIQUID_FREQMOD_DEFINE_API(FREQMOD,T,TC) \
+ \
+/* define struct pointer */ \
+typedef struct FREQMOD(_s) * FREQMOD(); \
+ \
+/* create freqmod object (frequency modulator) */ \
+/* _kf : modulation factor */ \
+FREQMOD() FREQMOD(_create)(float _kf); \
+ \
+/* destroy freqmod object */ \
+void FREQMOD(_destroy)(FREQMOD() _q); \
+ \
+/* print freqmod object internals */ \
+void FREQMOD(_print)(FREQMOD() _q); \
+ \
+/* reset state */ \
+void FREQMOD(_reset)(FREQMOD() _q); \
+ \
+/* modulate single sample */ \
+/* _q : frequency modulator object */ \
+/* _m : message signal m(t) */ \
+/* _s : complex baseband signal s(t) */ \
+void FREQMOD(_modulate)(FREQMOD() _q, \
+ T _m, \
+ TC * _s); \
+ \
+/* modulate block of samples */ \
+/* _q : frequency modulator object */ \
+/* _m : message signal m(t), [size: _n x 1] */ \
+/* _n : number of input, output samples */ \
+/* _s : complex baseband signal s(t) [size: _n x 1] */ \
+void FREQMOD(_modulate_block)(FREQMOD() _q, \
+ T * _m, \
+ unsigned int _n, \
+ TC * _s); \
+
+// define freqmod APIs
+LIQUID_FREQMOD_DEFINE_API(LIQUID_FREQMOD_MANGLE_FLOAT,float,liquid_float_complex)
+
+
+
+//
+// Analog frequency demodulator
+//
+
+#define LIQUID_FREQDEM_MANGLE_FLOAT(name) LIQUID_CONCAT(freqdem,name)
+
+// Macro : FREQDEM (analog frequency modulator)
+// FREQDEM : name-mangling macro
+// T : primitive data type
+// TC : primitive data type (complex)
+#define LIQUID_FREQDEM_DEFINE_API(FREQDEM,T,TC) \
+ \
+/* define struct pointer */ \
+typedef struct FREQDEM(_s) * FREQDEM(); \
+ \
+/* create freqdem object (frequency modulator) */ \
+/* _kf : modulation factor */ \
+FREQDEM() FREQDEM(_create)(float _kf); \
+ \
+/* destroy freqdem object */ \
+void FREQDEM(_destroy)(FREQDEM() _q); \
+ \
+/* print freqdem object internals */ \
+void FREQDEM(_print)(FREQDEM() _q); \
+ \
+/* reset state */ \
+void FREQDEM(_reset)(FREQDEM() _q); \
+ \
+/* demodulate sample */ \
+/* _q : frequency modulator object */ \
+/* _r : received signal r(t) */ \
+/* _m : output message signal m(t) */ \
+void FREQDEM(_demodulate)(FREQDEM() _q, \
+ TC _r, \
+ T * _m); \
+ \
+/* demodulate block of samples */ \
+/* _q : frequency demodulator object */ \
+/* _r : received signal r(t) [size: _n x 1] */ \
+/* _n : number of input, output samples */ \
+/* _m : message signal m(t), [size: _n x 1] */ \
+void FREQDEM(_demodulate_block)(FREQDEM() _q, \
+ TC * _r, \
+ unsigned int _n, \
+ T * _m); \
+
+// define freqdem APIs
+LIQUID_FREQDEM_DEFINE_API(LIQUID_FREQDEM_MANGLE_FLOAT,float,liquid_float_complex)
+
+
+
+// amplitude modulation types
+typedef enum {
+ LIQUID_AMPMODEM_DSB=0, // double side-band
+ LIQUID_AMPMODEM_USB, // single side-band (upper)
+ LIQUID_AMPMODEM_LSB // single side-band (lower)
+} liquid_ampmodem_type;
+
+typedef struct ampmodem_s * ampmodem;
+
+// create ampmodem object
+// _m : modulation index
+// _fc : carrier frequency, range: [-0.5,0.5]
+// _type : AM type (e.g. LIQUID_AMPMODEM_DSB)
+// _suppressed_carrier : carrier suppression flag
+ampmodem ampmodem_create(float _m,
+ float _fc,
+ liquid_ampmodem_type _type,
+ int _suppressed_carrier);
+
+// destroy ampmodem object
+void ampmodem_destroy(ampmodem _fm);
+
+// print ampmodem object internals
+void ampmodem_print(ampmodem _fm);
+
+// reset ampmodem object state
+void ampmodem_reset(ampmodem _fm);
+
+// modulate sample
+void ampmodem_modulate(ampmodem _fm,
+ float _x,
+ liquid_float_complex *_y);
+
+// demodulate sample
+void ampmodem_demodulate(ampmodem _fm,
+ liquid_float_complex _y,
+ float *_x);
+
+
+//
+// MODULE : multichannel
+//
+
+
+#define FIRPFBCH_NYQUIST 0
+#define FIRPFBCH_ROOTNYQUIST 1
+
+#define LIQUID_ANALYZER 0
+#define LIQUID_SYNTHESIZER 1
+
+
+//
+// Finite impulse response polyphase filterbank channelizer
+//
+
+#define FIRPFBCH_MANGLE_CRCF(name) LIQUID_CONCAT(firpfbch_crcf,name)
+#define FIRPFBCH_MANGLE_CCCF(name) LIQUID_CONCAT(firpfbch_cccf,name)
+
+// Macro:
+// FIRPFBCH : name-mangling macro
+// TO : output data type
+// TC : coefficients data type
+// TI : input data type
+#define LIQUID_FIRPFBCH_DEFINE_API(FIRPFBCH,TO,TC,TI) \
+typedef struct FIRPFBCH(_s) * FIRPFBCH(); \
+ \
+/* create finite impulse response polyphase filter-bank */ \
+/* channelizer object from external coefficients */ \
+/* _type : channelizer type, e.g. LIQUID_ANALYZER */ \
+/* _M : number of channels */ \
+/* _p : number of coefficients for each channel */ \
+/* _h : coefficients [size: _M*_p x 1] */ \
+FIRPFBCH() FIRPFBCH(_create)(int _type, \
+ unsigned int _M, \
+ unsigned int _p, \
+ TC * _h); \
+ \
+/* create FIR polyphase filterbank channelizer object with */ \
+/* prototype filter based on windowed Kaiser design */ \
+/* _type : type (LIQUID_ANALYZER | LIQUID_SYNTHESIZER) */ \
+/* _M : number of channels */ \
+/* _m : filter delay (symbols) */ \
+/* _As : stop-band attentuation [dB] */ \
+FIRPFBCH() FIRPFBCH(_create_kaiser)(int _type, \
+ unsigned int _M, \
+ unsigned int _m, \
+ float _As); \
+ \
+/* create FIR polyphase filterbank channelizer object with */ \
+/* prototype root-Nyquist filter */ \
+/* _type : type (LIQUID_ANALYZER | LIQUID_SYNTHESIZER) */ \
+/* _M : number of channels */ \
+/* _m : filter delay (symbols) */ \
+/* _beta : filter excess bandwidth factor, in [0,1] */ \
+/* _ftype : filter prototype (rrcos, rkaiser, etc.) */ \
+FIRPFBCH() FIRPFBCH(_create_rnyquist)(int _type, \
+ unsigned int _M, \
+ unsigned int _m, \
+ float _beta, \
+ int _ftype); \
+ \
+/* destroy firpfbch object */ \
+void FIRPFBCH(_destroy)(FIRPFBCH() _q); \
+ \
+/* clear/reset firpfbch internal state */ \
+void FIRPFBCH(_reset)(FIRPFBCH() _q); \
+ \
+/* print firpfbch internal parameters to stdout */ \
+void FIRPFBCH(_print)(FIRPFBCH() _q); \
+ \
+/* execute filterbank as synthesizer on block of samples */ \
+/* _q : filterbank channelizer object */ \
+/* _x : channelized input, [size: num_channels x 1] */ \
+/* _y : output time series, [size: num_channels x 1] */ \
+void FIRPFBCH(_synthesizer_execute)(FIRPFBCH() _q, \
+ TI * _x, \
+ TO * _y); \
+ \
+/* execute filterbank as analyzer on block of samples */ \
+/* _q : filterbank channelizer object */ \
+/* _x : input time series, [size: num_channels x 1] */ \
+/* _y : channelized output, [size: num_channels x 1] */ \
+void FIRPFBCH(_analyzer_execute)(FIRPFBCH() _q, \
+ TI * _x, \
+ TO * _y); \
+
+
+LIQUID_FIRPFBCH_DEFINE_API(FIRPFBCH_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+LIQUID_FIRPFBCH_DEFINE_API(FIRPFBCH_MANGLE_CCCF,
+ liquid_float_complex,
+ liquid_float_complex,
+ liquid_float_complex)
+
+
+//
+// Finite impulse response polyphase filterbank channelizer
+// with output rate 2 Fs / M
+//
+
+#define FIRPFBCH2_MANGLE_CRCF(name) LIQUID_CONCAT(firpfbch2_crcf,name)
+
+// Macro:
+// FIRPFBCH2 : name-mangling macro
+// TO : output data type
+// TC : coefficients data type
+// TI : input data type
+#define LIQUID_FIRPFBCH2_DEFINE_API(FIRPFBCH2,TO,TC,TI) \
+typedef struct FIRPFBCH2(_s) * FIRPFBCH2(); \
+ \
+/* create firpfbch2 object */ \
+/* _type : channelizer type (e.g. LIQUID_ANALYZER) */ \
+/* _M : number of channels (must be even) */ \
+/* _m : prototype filter semi-lenth, length=2*M*m */ \
+/* _h : prototype filter coefficient array */ \
+FIRPFBCH2() FIRPFBCH2(_create)(int _type, \
+ unsigned int _M, \
+ unsigned int _m, \
+ TC * _h); \
+ \
+/* create firpfbch2 object using Kaiser window prototype */ \
+/* _type : channelizer type (e.g. LIQUID_ANALYZER) */ \
+/* _M : number of channels (must be even) */ \
+/* _m : prototype filter semi-lenth, length=2*M*m+1 */ \
+/* _As : filter stop-band attenuation [dB] */ \
+FIRPFBCH2() FIRPFBCH2(_create_kaiser)(int _type, \
+ unsigned int _M, \
+ unsigned int _m, \
+ float _As); \
+ \
+/* destroy firpfbch2 object, freeing internal memory */ \
+void FIRPFBCH2(_destroy)(FIRPFBCH2() _q); \
+ \
+/* reset firpfbch2 object internals */ \
+void FIRPFBCH2(_reset)(FIRPFBCH2() _q); \
+ \
+/* print firpfbch2 object internals */ \
+void FIRPFBCH2(_print)(FIRPFBCH2() _q); \
+ \
+/* execute filterbank channelizer */ \
+/* LIQUID_ANALYZER: input: M/2, output: M */ \
+/* LIQUID_SYNTHESIZER: input: M, output: M/2 */ \
+/* _x : channelizer input */ \
+/* _y : channelizer output */ \
+void FIRPFBCH2(_execute)(FIRPFBCH2() _q, \
+ TI * _x, \
+ TO * _y); \
+
+
+LIQUID_FIRPFBCH2_DEFINE_API(FIRPFBCH2_MANGLE_CRCF,
+ liquid_float_complex,
+ float,
+ liquid_float_complex)
+
+
+
+#define OFDMFRAME_SCTYPE_NULL 0
+#define OFDMFRAME_SCTYPE_PILOT 1
+#define OFDMFRAME_SCTYPE_DATA 2
+
+// initialize default subcarrier allocation
+// _M : number of subcarriers
+// _p : output subcarrier allocation array, [size: _M x 1]
+void ofdmframe_init_default_sctype(unsigned int _M,
+ unsigned char * _p);
+
+// validate subcarrier type (count number of null, pilot, and data
+// subcarriers in the allocation)
+// _p : subcarrier allocation array, [size: _M x 1]
+// _M : number of subcarriers
+// _M_null : output number of null subcarriers
+// _M_pilot : output number of pilot subcarriers
+// _M_data : output number of data subcarriers
+void ofdmframe_validate_sctype(unsigned char * _p,
+ unsigned int _M,
+ unsigned int * _M_null,
+ unsigned int * _M_pilot,
+ unsigned int * _M_data);
+
+// print subcarrier allocation to screen
+// _p : output subcarrier allocation array, [size: _M x 1]
+// _M : number of subcarriers
+void ofdmframe_print_sctype(unsigned char * _p,
+ unsigned int _M);
+
+
+//
+// OFDM frame (symbol) generator
+//
+typedef struct ofdmframegen_s * ofdmframegen;
+
+// create OFDM framing generator object
+// _M : number of subcarriers, >10 typical
+// _cp_len : cyclic prefix length
+// _taper_len : taper length (OFDM symbol overlap)
+// _p : subcarrier allocation (null, pilot, data), [size: _M x 1]
+ofdmframegen ofdmframegen_create(unsigned int _M,
+ unsigned int _cp_len,
+ unsigned int _taper_len,
+ unsigned char * _p);
+
+void ofdmframegen_destroy(ofdmframegen _q);
+
+void ofdmframegen_print(ofdmframegen _q);
+
+void ofdmframegen_reset(ofdmframegen _q);
+
+// write first S0 symbol
+void ofdmframegen_write_S0a(ofdmframegen _q,
+ liquid_float_complex *_y);
+
+// write second S0 symbol
+void ofdmframegen_write_S0b(ofdmframegen _q,
+ liquid_float_complex *_y);
+
+// write S1 symbol
+void ofdmframegen_write_S1(ofdmframegen _q,
+ liquid_float_complex *_y);
+
+// write data symbol
+void ofdmframegen_writesymbol(ofdmframegen _q,
+ liquid_float_complex * _x,
+ liquid_float_complex *_y);
+
+// write tail
+void ofdmframegen_writetail(ofdmframegen _q,
+ liquid_float_complex * _x);
+
+//
+// OFDM frame (symbol) synchronizer
+//
+typedef int (*ofdmframesync_callback)(liquid_float_complex * _y,
+ unsigned char * _p,
+ unsigned int _M,
+ void * _userdata);
+typedef struct ofdmframesync_s * ofdmframesync;
+
+// create OFDM framing synchronizer object
+// _M : number of subcarriers, >10 typical
+// _cp_len : cyclic prefix length
+// _taper_len : taper length (OFDM symbol overlap)
+// _p : subcarrier allocation (null, pilot, data), [size: _M x 1]
+// _callback : user-defined callback function
+// _userdata : user-defined data pointer
+ofdmframesync ofdmframesync_create(unsigned int _M,
+ unsigned int _cp_len,
+ unsigned int _taper_len,
+ unsigned char * _p,
+ ofdmframesync_callback _callback,
+ void * _userdata);
+void ofdmframesync_destroy(ofdmframesync _q);
+void ofdmframesync_print(ofdmframesync _q);
+void ofdmframesync_reset(ofdmframesync _q);
+void ofdmframesync_execute(ofdmframesync _q,
+ liquid_float_complex * _x,
+ unsigned int _n);
+
+// query methods
+float ofdmframesync_get_rssi(ofdmframesync _q); // received signal strength indication
+float ofdmframesync_get_cfo(ofdmframesync _q); // carrier offset estimate
+
+// debugging
+void ofdmframesync_debug_enable(ofdmframesync _q);
+void ofdmframesync_debug_disable(ofdmframesync _q);
+void ofdmframesync_debug_print(ofdmframesync _q, const char * _filename);
+
+
+//
+// MODULE : nco (numerically-controlled oscillator)
+//
+
+// oscillator type
+// LIQUID_NCO : numerically-controlled oscillator (fast)
+// LIQUID_VCO : "voltage"-controlled oscillator (precise)
+typedef enum {
+ LIQUID_NCO=0,
+ LIQUID_VCO
+} liquid_ncotype;
+
+#define NCO_MANGLE_FLOAT(name) LIQUID_CONCAT(nco_crcf, name)
+
+// large macro
+// NCO : name-mangling macro
+// T : primitive data type
+// TC : input/output data type
+#define LIQUID_NCO_DEFINE_API(NCO,T,TC) \
+typedef struct NCO(_s) * NCO(); \
+ \
+NCO() NCO(_create)(liquid_ncotype _type); \
+void NCO(_destroy)(NCO() _q); \
+void NCO(_print)(NCO() _q); \
+ \
+/* set phase/frequency to zero, reset pll filter */ \
+void NCO(_reset)(NCO() _q); \
+ \
+/* get/set/adjust internal frequency/phase */ \
+T NCO(_get_frequency)( NCO() _q); \
+void NCO(_set_frequency)( NCO() _q, T _f); \
+void NCO(_adjust_frequency)(NCO() _q, T _df); \
+T NCO(_get_phase)( NCO() _q); \
+void NCO(_set_phase)( NCO() _q, T _phi); \
+void NCO(_adjust_phase)( NCO() _q, T _dphi); \
+ \
+/* increment phase by internal phase step (frequency) */ \
+void NCO(_step)(NCO() _q); \
+ \
+/* compute trigonometric functions */ \
+T NCO(_sin)(NCO() _q); \
+T NCO(_cos)(NCO() _q); \
+void NCO(_sincos)(NCO() _q, T* _s, T* _c); \
+void NCO(_cexpf)(NCO() _q, TC * _y); \
+ \
+/* pll : phase-locked loop */ \
+void NCO(_pll_set_bandwidth)(NCO() _q, T _b); \
+void NCO(_pll_step)(NCO() _q, T _dphi); \
+ \
+/* Rotate input sample up by NCO angle (no stepping) */ \
+void NCO(_mix_up)(NCO() _q, TC _x, TC *_y); \
+ \
+/* Rotate input sample down by NCO angle (no stepping) */ \
+void NCO(_mix_down)(NCO() _q, TC _x, TC *_y); \
+ \
+/* Rotate input vector up by NCO angle (stepping) */ \
+/* _q : nco object */ \
+/* _x : input vector [size: _N x 1] */ \
+/* _y : output vector [size: _N x 1] */ \
+/* _N : vector size */ \
+void NCO(_mix_block_up)(NCO() _q, \
+ TC *_x, \
+ TC *_y, \
+ unsigned int _N); \
+ \
+/* Rotate input vector down by NCO angle (stepping) */ \
+/* _q : nco object */ \
+/* _x : input vector [size: _N x 1] */ \
+/* _y : output vector [size: _N x 1] */ \
+/* _N : vector size */ \
+void NCO(_mix_block_down)(NCO() _q, \
+ TC *_x, \
+ TC *_y, \
+ unsigned int _N); \
+
+// Define nco APIs
+LIQUID_NCO_DEFINE_API(NCO_MANGLE_FLOAT, float, liquid_float_complex)
+
+
+// nco utilities
+
+// unwrap phase of array (basic)
+void liquid_unwrap_phase(float * _theta, unsigned int _n);
+
+// unwrap phase of array (advanced)
+void liquid_unwrap_phase2(float * _theta, unsigned int _n);
+
+
+
+//
+// MODULE : optimization
+//
+
+// utility function pointer definition
+typedef float (*utility_function)(void * _userdata,
+ float * _v,
+ unsigned int _n);
+
+// n-dimensional Rosenbrock utility function (minimum at _v = {1,1,1...}
+// _userdata : user-defined data structure (convenience)
+// _v : input vector [size: _n x 1]
+// _n : input vector size
+float liquid_rosenbrock(void * _userdata,
+ float * _v,
+ unsigned int _n);
+
+// n-dimensional inverse Gauss utility function (minimum at _v = {0,0,0...}
+// _userdata : user-defined data structure (convenience)
+// _v : input vector [size: _n x 1]
+// _n : input vector size
+float liquid_invgauss(void * _userdata,
+ float * _v,
+ unsigned int _n);
+
+// n-dimensional multimodal utility function (minimum at _v = {0,0,0...}
+// _userdata : user-defined data structure (convenience)
+// _v : input vector [size: _n x 1]
+// _n : input vector size
+float liquid_multimodal(void * _userdata,
+ float * _v,
+ unsigned int _n);
+
+// n-dimensional spiral utility function (minimum at _v = {0,0,0...}
+// _userdata : user-defined data structure (convenience)
+// _v : input vector [size: _n x 1]
+// _n : input vector size
+float liquid_spiral(void * _userdata,
+ float * _v,
+ unsigned int _n);
+
+
+//
+// Gradient search
+//
+
+#define LIQUID_OPTIM_MINIMIZE (0)
+#define LIQUID_OPTIM_MAXIMIZE (1)
+
+typedef struct gradsearch_s * gradsearch;
+
+// Create a gradient search object
+// _userdata : user data object pointer
+// _v : array of parameters to optimize
+// _num_parameters : array length (number of parameters to optimize)
+// _u : utility function pointer
+// _direction : search direction (e.g. LIQUID_OPTIM_MAXIMIZE)
+gradsearch gradsearch_create(void * _userdata,
+ float * _v,
+ unsigned int _num_parameters,
+ utility_function _utility,
+ int _direction);
+
+// Destroy a gradsearch object
+void gradsearch_destroy(gradsearch _q);
+
+// Prints current status of search
+void gradsearch_print(gradsearch _q);
+
+// Iterate once
+float gradsearch_step(gradsearch _q);
+
+// Execute the search
+float gradsearch_execute(gradsearch _q,
+ unsigned int _max_iterations,
+ float _target_utility);
+
+
+// quasi-Newton search
+typedef struct qnsearch_s * qnsearch;
+
+// Create a simple qnsearch object; parameters are specified internally
+// _userdata : userdata
+// _v : array of parameters to optimize
+// _num_parameters : array length
+// _get_utility : utility function pointer
+// _direction : search direction (e.g. LIQUID_OPTIM_MAXIMIZE)
+qnsearch qnsearch_create(void * _userdata,
+ float * _v,
+ unsigned int _num_parameters,
+ utility_function _u,
+ int _direction);
+
+// Destroy a qnsearch object
+void qnsearch_destroy(qnsearch _g);
+
+// Prints current status of search
+void qnsearch_print(qnsearch _g);
+
+// Resets internal state
+void qnsearch_reset(qnsearch _g);
+
+// Iterate once
+void qnsearch_step(qnsearch _g);
+
+// Execute the search
+float qnsearch_execute(qnsearch _g,
+ unsigned int _max_iterations,
+ float _target_utility);
+
+//
+// chromosome (for genetic algorithm search)
+//
+typedef struct chromosome_s * chromosome;
+
+// create a chromosome object, variable bits/trait
+chromosome chromosome_create(unsigned int * _bits_per_trait,
+ unsigned int _num_traits);
+
+// create a chromosome object, all traits same resolution
+chromosome chromosome_create_basic(unsigned int _num_traits,
+ unsigned int _bits_per_trait);
+
+// create a chromosome object, cloning a parent
+chromosome chromosome_create_clone(chromosome _parent);
+
+// copy existing chromosomes' internal traits (all other internal
+// parameters must be equal)
+void chromosome_copy(chromosome _parent, chromosome _child);
+
+// Destroy a chromosome object
+void chromosome_destroy(chromosome _c);
+
+// get number of traits in chromosome
+unsigned int chromosome_get_num_traits(chromosome _c);
+
+// Print chromosome values to screen (binary representation)
+void chromosome_print(chromosome _c);
+
+// Print chromosome values to screen (floating-point representation)
+void chromosome_printf(chromosome _c);
+
+// clear chromosome (set traits to zero)
+void chromosome_clear(chromosome _c);
+
+// initialize chromosome on integer values
+void chromosome_init(chromosome _c,
+ unsigned int * _v);
+
+// initialize chromosome on floating-point values
+void chromosome_initf(chromosome _c,
+ float * _v);
+
+// Mutates chromosome _c at _index
+void chromosome_mutate(chromosome _c, unsigned int _index);
+
+// Resulting chromosome _c is a crossover of parents _p1 and _p2 at _threshold
+void chromosome_crossover(chromosome _p1,
+ chromosome _p2,
+ chromosome _c,
+ unsigned int _threshold);
+
+// Initializes chromosome to random value
+void chromosome_init_random(chromosome _c);
+
+// Returns integer representation of chromosome
+unsigned int chromosome_value(chromosome _c,
+ unsigned int _index);
+
+// Returns floating-point representation of chromosome
+float chromosome_valuef(chromosome _c,
+ unsigned int _index);
+
+//
+// genetic algorithm search
+//
+typedef struct gasearch_s * gasearch;
+
+typedef float (*gasearch_utility)(void * _userdata, chromosome _c);
+
+// Create a simple gasearch object; parameters are specified internally
+// _utility : chromosome fitness utility function
+// _userdata : user data, void pointer passed to _get_utility() callback
+// _parent : initial population parent chromosome, governs precision, etc.
+// _minmax : search direction
+gasearch gasearch_create(gasearch_utility _u,
+ void * _userdata,
+ chromosome _parent,
+ int _minmax);
+
+// Create a gasearch object, specifying search parameters
+// _utility : chromosome fitness utility function
+// _userdata : user data, void pointer passed to _get_utility() callback
+// _parent : initial population parent chromosome, governs precision, etc.
+// _minmax : search direction
+// _population_size : number of chromosomes in population
+// _mutation_rate : probability of mutating chromosomes
+gasearch gasearch_create_advanced(gasearch_utility _utility,
+ void * _userdata,
+ chromosome _parent,
+ int _minmax,
+ unsigned int _population_size,
+ float _mutation_rate);
+
+
+// Destroy a gasearch object
+void gasearch_destroy(gasearch _q);
+
+// print search parameter internals
+void gasearch_print(gasearch _q);
+
+// set mutation rate
+void gasearch_set_mutation_rate(gasearch _q,
+ float _mutation_rate);
+
+// set population/selection size
+// _q : ga search object
+// _population_size : new population size (number of chromosomes)
+// _selection_size : selection size (number of parents for new generation)
+void gasearch_set_population_size(gasearch _q,
+ unsigned int _population_size,
+ unsigned int _selection_size);
+
+// Execute the search
+// _q : ga search object
+// _max_iterations : maximum number of iterations to run before bailing
+// _target_utility : target utility
+float gasearch_run(gasearch _q,
+ unsigned int _max_iterations,
+ float _target_utility);
+
+// iterate over one evolution of the search algorithm
+void gasearch_evolve(gasearch _q);
+
+// get optimal chromosome
+// _q : ga search object
+// _c : output optimal chromosome
+// _utility_opt : fitness of _c
+void gasearch_getopt(gasearch _q,
+ chromosome _c,
+ float * _utility_opt);
+
+//
+// MODULE : quantization
+//
+
+float compress_mulaw(float _x, float _mu);
+float expand_mulaw(float _x, float _mu);
+
+void compress_cf_mulaw(liquid_float_complex _x, float _mu, liquid_float_complex * _y);
+void expand_cf_mulaw(liquid_float_complex _y, float _mu, liquid_float_complex * _x);
+
+//float compress_alaw(float _x, float _a);
+//float expand_alaw(float _x, float _a);
+
+// inline quantizer: 'analog' signal in [-1, 1]
+unsigned int quantize_adc(float _x, unsigned int _num_bits);
+float quantize_dac(unsigned int _s, unsigned int _num_bits);
+
+// structured quantizer
+
+typedef enum {
+ LIQUID_COMPANDER_NONE=0,
+ LIQUID_COMPANDER_LINEAR,
+ LIQUID_COMPANDER_MULAW,
+ LIQUID_COMPANDER_ALAW
+} liquid_compander_type;
+
+#define QUANTIZER_MANGLE_FLOAT(name) LIQUID_CONCAT(quantizerf, name)
+#define QUANTIZER_MANGLE_CFLOAT(name) LIQUID_CONCAT(quantizercf, name)
+
+// large macro
+// QUANTIZER : name-mangling macro
+// T : data type
+#define LIQUID_QUANTIZER_DEFINE_API(QUANTIZER,T) \
+typedef struct QUANTIZER(_s) * QUANTIZER(); \
+QUANTIZER() QUANTIZER(_create)(liquid_compander_type _ctype, \
+ float _range, \
+ unsigned int _num_bits); \
+void QUANTIZER(_destroy)(QUANTIZER() _q); \
+void QUANTIZER(_print)(QUANTIZER() _q); \
+void QUANTIZER(_execute_adc)(QUANTIZER() _q, \
+ T _x, \
+ unsigned int * _sample); \
+void QUANTIZER(_execute_dac)(QUANTIZER() _q, \
+ unsigned int _sample, \
+ T * _x);
+
+LIQUID_QUANTIZER_DEFINE_API(QUANTIZER_MANGLE_FLOAT, float)
+LIQUID_QUANTIZER_DEFINE_API(QUANTIZER_MANGLE_CFLOAT, liquid_float_complex)
+
+
+//
+// MODULE : random (number generators)
+//
+
+
+// Uniform random number generator, (0,1]
+float randf();
+float randf_pdf(float _x);
+float randf_cdf(float _x);
+
+// Gauss random number generator, N(0,1)
+// f(x) = 1/sqrt(2*pi*sigma^2) * exp{-(x-eta)^2/(2*sigma^2)}
+//
+// where
+// eta = mean
+// sigma = standard deviation
+//
+float randnf();
+void awgn(float *_x, float _nstd);
+void crandnf(liquid_float_complex *_y);
+void cawgn(liquid_float_complex *_x, float _nstd);
+float randnf_pdf(float _x, float _eta, float _sig);
+float randnf_cdf(float _x, float _eta, float _sig);
+
+// Exponential
+// f(x) = lambda exp{ -lambda x }
+// where
+// lambda = spread parameter, lambda > 0
+// x >= 0
+float randexpf(float _lambda);
+float randexpf_pdf(float _x, float _lambda);
+float randexpf_cdf(float _x, float _lambda);
+
+// Weibull
+// f(x) = (a/b) (x/b)^(a-1) exp{ -(x/b)^a }
+// where
+// a = alpha : shape parameter
+// b = beta : scaling parameter
+// g = gamma : location (threshold) parameter
+//
+float randweibf(float _alpha, float _beta, float _gamma);
+float randweibf_pdf(float _x, float _a, float _b, float _g);
+float randweibf_cdf(float _x, float _a, float _b, float _g);
+
+// Gamma
+// x^(a-1) exp(-x/b)
+// f(x) = -------------------
+// Gamma(a) b^a
+// where
+// a = alpha : shape parameter, a > 0
+// b = beta : scale parameter, b > 0
+// Gamma(z) = regular gamma function
+// x >= 0
+float randgammaf(float _alpha, float _beta);
+float randgammaf_pdf(float _x, float _alpha, float _beta);
+float randgammaf_cdf(float _x, float _alpha, float _beta);
+
+// Nakagami-m
+// f(x) = (2/Gamma(m)) (m/omega)^m x^(2m-1) exp{-(m/omega)x^2}
+// where
+// m : shape parameter, m >= 0.5
+// omega : spread parameter, omega > 0
+// Gamma(z): regular complete gamma function
+// x >= 0
+float randnakmf(float _m, float _omega);
+float randnakmf_pdf(float _x, float _m, float _omega);
+float randnakmf_cdf(float _x, float _m, float _omega);
+
+// Rice-K
+// f(x) = (x/sigma^2) exp{ -(x^2+s^2)/(2sigma^2) } I0( x s / sigma^2 )
+// where
+// s = sqrt( omega*K/(K+1) )
+// sigma = sqrt(0.5 omega/(K+1))
+// and
+// K = shape parameter
+// omega = spread parameter
+// I0 = modified Bessel function of the first kind
+// x >= 0
+float randricekf(float _K, float _omega);
+float randricekf_cdf(float _x, float _K, float _omega);
+float randricekf_pdf(float _x, float _K, float _omega);
+
+
+// Data scrambler : whiten data sequence
+void scramble_data(unsigned char * _x, unsigned int _len);
+void unscramble_data(unsigned char * _x, unsigned int _len);
+void unscramble_data_soft(unsigned char * _x, unsigned int _len);
+
+//
+// MODULE : sequence
+//
+
+// Binary sequence (generic)
+
+typedef struct bsequence_s * bsequence;
+
+// Create a binary sequence of a specific length (number of bits)
+bsequence bsequence_create(unsigned int num_bits);
+
+// Free memory in a binary sequence
+void bsequence_destroy(bsequence _bs);
+
+// Clear binary sequence (set to 0's)
+void bsequence_clear(bsequence _bs);
+
+// initialize sequence on external array
+void bsequence_init(bsequence _bs,
+ unsigned char * _v);
+
+// Print sequence to the screen
+void bsequence_print(bsequence _bs);
+
+// Push bit into to back of a binary sequence
+void bsequence_push(bsequence _bs,
+ unsigned int _bit);
+
+// circular shift (left)
+void bsequence_circshift(bsequence _bs);
+
+// Correlate two binary sequences together
+int bsequence_correlate(bsequence _bs1, bsequence _bs2);
+
+// compute the binary addition of two bit sequences
+void bsequence_add(bsequence _bs1, bsequence _bs2, bsequence _bs3);
+
+// compute the binary multiplication of two bit sequences
+void bsequence_mul(bsequence _bs1, bsequence _bs2, bsequence _bs3);
+
+// accumulate the 1's in a binary sequence
+unsigned int bsequence_accumulate(bsequence _bs);
+
+// accessor functions
+unsigned int bsequence_get_length(bsequence _bs);
+unsigned int bsequence_index(bsequence _bs, unsigned int _i);
+
+// Complementary codes
+
+// intialize two sequences to complementary codes. sequences must
+// be of length at least 8 and a power of 2 (e.g. 8, 16, 32, 64,...)
+// _a : sequence 'a' (bsequence object)
+// _b : sequence 'b' (bsequence object)
+void bsequence_create_ccodes(bsequence _a,
+ bsequence _b);
+
+
+// M-Sequence
+
+#define LIQUID_MAX_MSEQUENCE_LENGTH 32767
+
+// default m-sequence generators: g (hex) m n g (oct) g (binary)
+#define LIQUID_MSEQUENCE_GENPOLY_M2 0x0007 // 2 3 7 111
+#define LIQUID_MSEQUENCE_GENPOLY_M3 0x000B // 3 7 13 1011
+#define LIQUID_MSEQUENCE_GENPOLY_M4 0x0013 // 4 15 23 10011
+#define LIQUID_MSEQUENCE_GENPOLY_M5 0x0025 // 5 31 45 100101
+#define LIQUID_MSEQUENCE_GENPOLY_M6 0x0043 // 6 63 103 1000011
+#define LIQUID_MSEQUENCE_GENPOLY_M7 0x0089 // 7 127 211 10001001
+#define LIQUID_MSEQUENCE_GENPOLY_M8 0x011D // 8 255 435 100101101
+#define LIQUID_MSEQUENCE_GENPOLY_M9 0x0211 // 9 511 1021 1000010001
+#define LIQUID_MSEQUENCE_GENPOLY_M10 0x0409 // 10 1023 2011 10000001001
+#define LIQUID_MSEQUENCE_GENPOLY_M11 0x0805 // 11 2047 4005 100000000101
+#define LIQUID_MSEQUENCE_GENPOLY_M12 0x1053 // 12 4095 10123 1000001010011
+#define LIQUID_MSEQUENCE_GENPOLY_M13 0x201b // 13 8191 20033 10000000011011
+#define LIQUID_MSEQUENCE_GENPOLY_M14 0x402b // 14 16383 40053 100000000101011
+#define LIQUID_MSEQUENCE_GENPOLY_M15 0x8003 // 15 32767 100003 1000000000000011
+
+typedef struct msequence_s * msequence;
+
+// create a maximal-length sequence (m-sequence) object with
+// an internal shift register length of _m bits.
+// _m : generator polynomial length, sequence length is (2^m)-1
+// _g : generator polynomial, starting with most-significant bit
+// _a : initial shift register state, default: 000...001
+msequence msequence_create(unsigned int _m,
+ unsigned int _g,
+ unsigned int _a);
+
+// create a maximal-length sequence (m-sequence) object from a generator polynomial
+msequence msequence_create_genpoly(unsigned int _g);
+
+// creates a default maximal-length sequence
+msequence msequence_create_default(unsigned int _m);
+
+// destroy an msequence object, freeing all internal memory
+void msequence_destroy(msequence _m);
+
+// prints the sequence's internal state to the screen
+void msequence_print(msequence _m);
+
+// advance msequence on shift register, returning output bit
+unsigned int msequence_advance(msequence _ms);
+
+// generate pseudo-random symbol from shift register by
+// advancing _bps bits and returning compacted symbol
+// _ms : m-sequence object
+// _bps : bits per symbol of output
+unsigned int msequence_generate_symbol(msequence _ms,
+ unsigned int _bps);
+
+// reset msequence shift register to original state, typically '1'
+void msequence_reset(msequence _ms);
+
+// initialize a bsequence object on an msequence object
+// _bs : bsequence object
+// _ms : msequence object
+void bsequence_init_msequence(bsequence _bs,
+ msequence _ms);
+
+// get the length of the sequence
+unsigned int msequence_get_length(msequence _ms);
+
+// get the internal state of the sequence
+unsigned int msequence_get_state(msequence _ms);
+
+// set the internal state of the sequence
+void msequence_set_state(msequence _ms,
+ unsigned int _a);
+
+
+//
+// MODULE : utility
+//
+
+// pack binary array with symbol(s)
+// _src : source array [size: _n x 1]
+// _n : input source array length
+// _k : bit index to write in _src
+// _b : number of bits in input symbol
+// _sym_in : input symbol
+void liquid_pack_array(unsigned char * _src,
+ unsigned int _n,
+ unsigned int _k,
+ unsigned int _b,
+ unsigned char _sym_in);
+
+// unpack symbols from binary array
+// _src : source array [size: _n x 1]
+// _n : input source array length
+// _k : bit index to write in _src
+// _b : number of bits in output symbol
+// _sym_out : output symbol
+void liquid_unpack_array(unsigned char * _src,
+ unsigned int _n,
+ unsigned int _k,
+ unsigned int _b,
+ unsigned char * _sym_out);
+
+// pack one-bit symbols into bytes (8-bit symbols)
+// _sym_in : input symbols array [size: _sym_in_len x 1]
+// _sym_in_len : number of input symbols
+// _sym_out : output symbols
+// _sym_out_len : number of bytes allocated to output symbols array
+// _num_written : number of output symbols actually written
+void liquid_pack_bytes(unsigned char * _sym_in,
+ unsigned int _sym_in_len,
+ unsigned char * _sym_out,
+ unsigned int _sym_out_len,
+ unsigned int * _num_written);
+
+// unpack 8-bit symbols (full bytes) into one-bit symbols
+// _sym_in : input symbols array [size: _sym_in_len x 1]
+// _sym_in_len : number of input symbols
+// _sym_out : output symbols array
+// _sym_out_len : number of bytes allocated to output symbols array
+// _num_written : number of output symbols actually written
+void liquid_unpack_bytes(unsigned char * _sym_in,
+ unsigned int _sym_in_len,
+ unsigned char * _sym_out,
+ unsigned int _sym_out_len,
+ unsigned int * _num_written);
+
+// repack bytes with arbitrary symbol sizes
+// _sym_in : input symbols array [size: _sym_in_len x 1]
+// _sym_in_bps : number of bits per input symbol
+// _sym_in_len : number of input symbols
+// _sym_out : output symbols array
+// _sym_out_bps : number of bits per output symbol
+// _sym_out_len : number of bytes allocated to output symbols array
+// _num_written : number of output symbols actually written
+void liquid_repack_bytes(unsigned char * _sym_in,
+ unsigned int _sym_in_bps,
+ unsigned int _sym_in_len,
+ unsigned char * _sym_out,
+ unsigned int _sym_out_bps,
+ unsigned int _sym_out_len,
+ unsigned int * _num_written);
+
+// shift array to the left _b bits, filling in zeros
+// _src : source address [size: _n x 1]
+// _n : input data array size
+// _b : number of bits to shift
+void liquid_lbshift(unsigned char * _src,
+ unsigned int _n,
+ unsigned int _b);
+
+// shift array to the right _b bits, filling in zeros
+// _src : source address [size: _n x 1]
+// _n : input data array size
+// _b : number of bits to shift
+void liquid_rbshift(unsigned char * _src,
+ unsigned int _n,
+ unsigned int _b);
+
+// circularly shift array to the left _b bits
+// _src : source address [size: _n x 1]
+// _n : input data array size
+// _b : number of bits to shift
+void liquid_lbcircshift(unsigned char * _src,
+ unsigned int _n,
+ unsigned int _b);
+
+// circularly shift array to the right _b bits
+// _src : source address [size: _n x 1]
+// _n : input data array size
+// _b : number of bits to shift
+void liquid_rbcircshift(unsigned char * _src,
+ unsigned int _n,
+ unsigned int _b);
+
+
+
+
+// shift array to the left _b bytes, filling in zeros
+// _src : source address [size: _n x 1]
+// _n : input data array size
+// _b : number of bytes to shift
+void liquid_lshift(unsigned char * _src,
+ unsigned int _n,
+ unsigned int _b);
+
+// shift array to the right _b bytes, filling in zeros
+// _src : source address [size: _n x 1]
+// _n : input data array size
+// _b : number of bytes to shift
+void liquid_rshift(unsigned char * _src,
+ unsigned int _n,
+ unsigned int _b);
+
+// circular shift array to the left _b bytes
+// _src : source address [size: _n x 1]
+// _n : input data array size
+// _b : number of bytes to shift
+void liquid_lcircshift(unsigned char * _src,
+ unsigned int _n,
+ unsigned int _b);
+
+// circular shift array to the right _b bytes
+// _src : source address [size: _n x 1]
+// _n : input data array size
+// _b : number of bytes to shift
+void liquid_rcircshift(unsigned char * _src,
+ unsigned int _n,
+ unsigned int _b);
+
+// Count the number of ones in an integer
+unsigned int liquid_count_ones(unsigned int _x);
+
+// count number of ones in an integer, modulo 2
+unsigned int liquid_count_ones_mod2(unsigned int _x);
+
+// compute bindary dot-product between two integers
+unsigned int liquid_bdotprod(unsigned int _x,
+ unsigned int _y);
+
+// Count leading zeros in an integer
+unsigned int liquid_count_leading_zeros(unsigned int _x);
+
+// Most-significant bit index
+unsigned int liquid_msb_index(unsigned int _x);
+
+// Print string of bits to stdout
+void liquid_print_bitstring(unsigned int _x,
+ unsigned int _n);
+
+// reverse byte, word, etc.
+unsigned char liquid_reverse_byte( unsigned char _x);
+unsigned int liquid_reverse_uint16(unsigned int _x);
+unsigned int liquid_reverse_uint24(unsigned int _x);
+unsigned int liquid_reverse_uint32(unsigned int _x);
+
+//
+// MODULE : vector
+//
+
+#define VECTOR_MANGLE_RF(name) LIQUID_CONCAT(liquid_vectorf, name)
+#define VECTOR_MANGLE_CF(name) LIQUID_CONCAT(liquid_vectorcf,name)
+
+// large macro
+// VECTOR : name-mangling macro
+// T : data type
+// TP : data type (primitive)
+#define LIQUID_VECTOR_DEFINE_API(VECTOR,T,TP) \
+ \
+/* initialize vector with scalar: x[i] = c (scalar) */ \
+void VECTOR(_init)(T _c, \
+ T * _x, \
+ unsigned int _n); \
+ \
+/* add each element: z[i] = x[i] + y[i] */ \
+void VECTOR(_add)(T * _x, \
+ T * _y, \
+ unsigned int _n, \
+ T * _z); \
+/* add scalar to each element: y[i] = x[i] + c */ \
+void VECTOR(_addscalar)(T * _x, \
+ unsigned int _n, \
+ T _c, \
+ T * _y); \
+ \
+/* multiply each element: z[i] = x[i] * y[i] */ \
+void VECTOR(_mul)(T * _x, \
+ T * _y, \
+ unsigned int _n, \
+ T * _z); \
+/* multiply each element with scalar: y[i] = x[i] * c */ \
+void VECTOR(_mulscalar)(T * _x, \
+ unsigned int _n, \
+ T _c, \
+ T * _y); \
+ \
+/* compute complex phase rotation: x[i] = exp{j theta[i]} */ \
+void VECTOR(_cexpj)(TP * _theta, \
+ unsigned int _n, \
+ T * _x); \
+/* compute angle of each element: theta[i] = arg{ x[i] } */ \
+void VECTOR(_carg)(T * _x, \
+ unsigned int _n, \
+ TP * _theta); \
+/* compute absolute value of each element: y[i] = |x[i]| */ \
+void VECTOR(_abs)(T * _x, \
+ unsigned int _n, \
+ TP * _y); \
+ \
+/* compute sum of squares: sum{ |x|^2 } */ \
+TP VECTOR(_sumsq)(T * _x, \
+ unsigned int _n); \
+ \
+/* compute l-2 norm: sqrt{ sum{ |x|^2 } } */ \
+TP VECTOR(_norm)(T * _x, \
+ unsigned int _n); \
+ \
+/* compute l-p norm: { sum{ |x|^p } }^(1/p) */ \
+TP VECTOR(_pnorm)(T * _x, \
+ unsigned int _n, \
+ TP _p); \
+ \
+/* scale vector elements by l-2 norm: y[i] = x[i]/norm(x) */ \
+void VECTOR(_normalize)(T * _x, \
+ unsigned int _n, \
+ T * _y); \
+
+LIQUID_VECTOR_DEFINE_API(VECTOR_MANGLE_RF, float, float);
+LIQUID_VECTOR_DEFINE_API(VECTOR_MANGLE_CF, liquid_float_complex, float);
+
+//
+// mixed types
+//
+#if 0
+void liquid_vectorf_add(float * _a,
+ float * _b,
+ unsigned int _n,
+ float * _c);
+#endif
+
+#ifdef __cplusplus
+} //extern "C"
+#endif // __cplusplus
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+
+#endif // __LIQUID_H__
+
diff --git a/external/liquid-dsp/lib/libliquid.a b/external/liquid-dsp/lib/libliquid.a
new file mode 100644
index 0000000..473d57d
Binary files /dev/null and b/external/liquid-dsp/lib/libliquid.a differ
diff --git a/external/liquid-dsp/lib/libliquid.def b/external/liquid-dsp/lib/libliquid.def
new file mode 100644
index 0000000..6df6363
--- /dev/null
+++ b/external/liquid-dsp/lib/libliquid.def
@@ -0,0 +1,1871 @@
+EXPORTS
+ agc_crcf_create @1
+ agc_crcf_destroy @2
+ agc_crcf_execute @3
+ agc_crcf_execute_block @4
+ agc_crcf_get_bandwidth @5
+ agc_crcf_get_gain @6
+ agc_crcf_get_rssi @7
+ agc_crcf_get_signal_level @8
+ agc_crcf_init @9
+ agc_crcf_lock @10
+ agc_crcf_print @11
+ agc_crcf_reset @12
+ agc_crcf_set_bandwidth @13
+ agc_crcf_set_gain @14
+ agc_crcf_set_rssi @15
+ agc_crcf_set_signal_level @16
+ agc_crcf_unlock @17
+ agc_rrrf_create @18
+ agc_rrrf_destroy @19
+ agc_rrrf_execute @20
+ agc_rrrf_execute_block @21
+ agc_rrrf_get_bandwidth @22
+ agc_rrrf_get_gain @23
+ agc_rrrf_get_rssi @24
+ agc_rrrf_get_signal_level @25
+ agc_rrrf_init @26
+ agc_rrrf_lock @27
+ agc_rrrf_print @28
+ agc_rrrf_reset @29
+ agc_rrrf_set_bandwidth @30
+ agc_rrrf_set_gain @31
+ agc_rrrf_set_rssi @32
+ agc_rrrf_set_signal_level @33
+ agc_rrrf_unlock @34
+ ampmodem_create @35
+ ampmodem_debug_print @36
+ ampmodem_demodulate @37
+ ampmodem_destroy @38
+ ampmodem_modulate @39
+ ampmodem_print @40
+ ampmodem_reset @41
+ apsk128_map @42 DATA
+ apsk128_num_levels @43 DATA
+ apsk128_p @44 DATA
+ apsk128_phi @45 DATA
+ apsk128_r @46 DATA
+ apsk128_r_slicer @47 DATA
+ apsk16_map @48 DATA
+ apsk16_num_levels @49 DATA
+ apsk16_p @50 DATA
+ apsk16_phi @51 DATA
+ apsk16_r @52 DATA
+ apsk16_r_slicer @53 DATA
+ apsk256_map @54 DATA
+ apsk256_num_levels @55 DATA
+ apsk256_p @56 DATA
+ apsk256_phi @57 DATA
+ apsk256_r @58 DATA
+ apsk256_r_slicer @59 DATA
+ apsk32_map @60 DATA
+ apsk32_num_levels @61 DATA
+ apsk32_p @62 DATA
+ apsk32_phi @63 DATA
+ apsk32_r @64 DATA
+ apsk32_r_slicer @65 DATA
+ apsk4_map @66 DATA
+ apsk4_num_levels @67 DATA
+ apsk4_p @68 DATA
+ apsk4_phi @69 DATA
+ apsk4_r @70 DATA
+ apsk4_r_slicer @71 DATA
+ apsk64_map @72 DATA
+ apsk64_num_levels @73 DATA
+ apsk64_p @74 DATA
+ apsk64_phi @75 DATA
+ apsk64_r @76 DATA
+ apsk64_r_slicer @77 DATA
+ apsk8_map @78 DATA
+ apsk8_num_levels @79 DATA
+ apsk8_p @80 DATA
+ apsk8_phi @81 DATA
+ apsk8_r @82 DATA
+ apsk8_r_slicer @83 DATA
+ asgram_create @84
+ asgram_destroy @85
+ asgram_execute @86
+ asgram_push @87
+ asgram_reset @88
+ asgram_set_scale @89
+ autocorr_cccf_create @90
+ autocorr_cccf_destroy @91
+ autocorr_cccf_execute @92
+ autocorr_cccf_execute_block @93
+ autocorr_cccf_get_energy @94
+ autocorr_cccf_print @95
+ autocorr_cccf_push @96
+ autocorr_cccf_reset @97
+ autocorr_rrrf_create @98
+ autocorr_rrrf_destroy @99
+ autocorr_rrrf_execute @100
+ autocorr_rrrf_execute_block @101
+ autocorr_rrrf_get_energy @102
+ autocorr_rrrf_print @103
+ autocorr_rrrf_push @104
+ autocorr_rrrf_reset @105
+ awgn @106
+ bessel_azpkf @107
+ bilinear_zpkf @108
+ blackmanharris @109
+ bpacketgen_assemble_header @110
+ bpacketgen_assemble_pnsequence @111
+ bpacketgen_compute_packet_len @112
+ bpacketgen_create @113
+ bpacketgen_destroy @114
+ bpacketgen_encode @115
+ bpacketgen_get_packet_len @116
+ bpacketgen_print @117
+ bpacketgen_recreate @118
+ bpacketsync_assemble_pnsequence @119
+ bpacketsync_create @120
+ bpacketsync_decode_header @121
+ bpacketsync_decode_payload @122
+ bpacketsync_destroy @123
+ bpacketsync_execute @124
+ bpacketsync_execute_bit @125
+ bpacketsync_execute_byte @126
+ bpacketsync_execute_rxheader @127
+ bpacketsync_execute_rxpayload @128
+ bpacketsync_execute_seekpn @129
+ bpacketsync_execute_sym @130
+ bpacketsync_print @131
+ bpacketsync_reconfig @132
+ bpacketsync_reset @133
+ bpresync_cccf_correlate @134
+ bpresync_cccf_correlatex @135
+ bpresync_cccf_create @136
+ bpresync_cccf_destroy @137
+ bpresync_cccf_print @138
+ bpresync_cccf_push @139
+ bpresync_cccf_reset @140
+ bsequence_accumulate @141
+ bsequence_add @142
+ bsequence_circshift @143
+ bsequence_clear @144
+ bsequence_correlate @145
+ bsequence_create @146
+ bsequence_create_ccodes @147
+ bsequence_destroy @148
+ bsequence_get_length @149
+ bsequence_index @150
+ bsequence_init @151
+ bsequence_init_msequence @152
+ bsequence_mul @153
+ bsequence_print @154
+ bsequence_push @155
+ bsync_cccf_correlate @156
+ bsync_cccf_create @157
+ bsync_cccf_create_msequence @158
+ bsync_cccf_destroy @159
+ bsync_cccf_print @160
+ bsync_crcf_correlate @161
+ bsync_crcf_create @162
+ bsync_crcf_create_msequence @163
+ bsync_crcf_destroy @164
+ bsync_crcf_print @165
+ bsync_rrrf_correlate @166
+ bsync_rrrf_create @167
+ bsync_rrrf_create_msequence @168
+ bsync_rrrf_destroy @169
+ bsync_rrrf_print @170
+ butter_azpkf @171
+ cawgn @172
+ cbuffercf_clear @173
+ cbuffercf_create @174
+ cbuffercf_create_max @175
+ cbuffercf_debug_print @176
+ cbuffercf_destroy @177
+ cbuffercf_is_full @178
+ cbuffercf_linearize @179
+ cbuffercf_max_read @180
+ cbuffercf_max_size @181
+ cbuffercf_pop @182
+ cbuffercf_print @183
+ cbuffercf_push @184
+ cbuffercf_read @185
+ cbuffercf_release @186
+ cbuffercf_size @187
+ cbuffercf_space_available @188
+ cbuffercf_write @189
+ cbufferf_clear @190
+ cbufferf_create @191
+ cbufferf_create_max @192
+ cbufferf_debug_print @193
+ cbufferf_destroy @194
+ cbufferf_is_full @195
+ cbufferf_linearize @196
+ cbufferf_max_read @197
+ cbufferf_max_size @198
+ cbufferf_pop @199
+ cbufferf_print @200
+ cbufferf_push @201
+ cbufferf_read @202
+ cbufferf_release @203
+ cbufferf_size @204
+ cbufferf_space_available @205
+ cbufferf_write @206
+ cheby1_azpkf @207
+ cheby2_azpkf @208
+ checksum_generate_key @209
+ chromosome_clear @210
+ chromosome_copy @211
+ chromosome_create @212
+ chromosome_create_basic @213
+ chromosome_create_clone @214
+ chromosome_crossover @215
+ chromosome_destroy @216
+ chromosome_get_num_traits @217
+ chromosome_init @218
+ chromosome_init_random @219
+ chromosome_initf @220
+ chromosome_mutate @221
+ chromosome_print @222
+ chromosome_printf @223
+ chromosome_value @224
+ chromosome_valuef @225
+ compress_cf_mulaw @226
+ compress_mulaw @227
+ count_bit_errors @228
+ count_bit_errors_array @229
+ crandnf @230
+ crc16_generate_key @231
+ crc24_generate_key @232
+ crc32_generate_key @233
+ crc8_generate_key @234
+ crc_generate_key @235
+ crc_get_length @236
+ crc_scheme_str @237 DATA
+ crc_validate_message @238
+ cvsd_create @239
+ cvsd_decode @240
+ cvsd_decode8 @241
+ cvsd_destroy @242
+ cvsd_encode @243
+ cvsd_encode8 @244
+ cvsd_print @245
+ detector_cccf_compute_dotprods @246
+ detector_cccf_correlate @247
+ detector_cccf_create @248
+ detector_cccf_debug_print @249
+ detector_cccf_destroy @250
+ detector_cccf_estimate_offsets @251
+ detector_cccf_print @252
+ detector_cccf_reset @253
+ detector_cccf_update_sumsq @254
+ dotprod_cccf_create @255
+ dotprod_cccf_destroy @256
+ dotprod_cccf_execute @257
+ dotprod_cccf_print @258
+ dotprod_cccf_recreate @259
+ dotprod_cccf_run @260
+ dotprod_cccf_run4 @261
+ dotprod_crcf_create @262
+ dotprod_crcf_destroy @263
+ dotprod_crcf_execute @264
+ dotprod_crcf_print @265
+ dotprod_crcf_recreate @266
+ dotprod_crcf_run @267
+ dotprod_crcf_run4 @268
+ dotprod_rrrf_create @269
+ dotprod_rrrf_destroy @270
+ dotprod_rrrf_execute @271
+ dotprod_rrrf_print @272
+ dotprod_rrrf_recreate @273
+ dotprod_rrrf_run @274
+ dotprod_rrrf_run4 @275
+ ellip_acdf @276
+ ellip_asnf @277
+ ellip_azpkf @278
+ ellip_cdf @279
+ ellip_snf @280
+ ellipdegf @281
+ ellipkf @282
+ eqlms_cccf_create @283
+ eqlms_cccf_create_rnyquist @284
+ eqlms_cccf_destroy @285
+ eqlms_cccf_execute @286
+ eqlms_cccf_get_bw @287
+ eqlms_cccf_get_weights @288
+ eqlms_cccf_print @289
+ eqlms_cccf_push @290
+ eqlms_cccf_recreate @291
+ eqlms_cccf_reset @292
+ eqlms_cccf_set_bw @293
+ eqlms_cccf_step @294
+ eqlms_cccf_train @295
+ eqlms_cccf_update_sumsq @296
+ eqlms_rrrf_create @297
+ eqlms_rrrf_create_rnyquist @298
+ eqlms_rrrf_destroy @299
+ eqlms_rrrf_execute @300
+ eqlms_rrrf_get_bw @301
+ eqlms_rrrf_get_weights @302
+ eqlms_rrrf_print @303
+ eqlms_rrrf_push @304
+ eqlms_rrrf_recreate @305
+ eqlms_rrrf_reset @306
+ eqlms_rrrf_set_bw @307
+ eqlms_rrrf_step @308
+ eqlms_rrrf_train @309
+ eqlms_rrrf_update_sumsq @310
+ eqrls_cccf_create @311
+ eqrls_cccf_destroy @312
+ eqrls_cccf_execute @313
+ eqrls_cccf_get_bw @314
+ eqrls_cccf_get_weights @315
+ eqrls_cccf_print @316
+ eqrls_cccf_push @317
+ eqrls_cccf_recreate @318
+ eqrls_cccf_reset @319
+ eqrls_cccf_set_bw @320
+ eqrls_cccf_step @321
+ eqrls_cccf_train @322
+ eqrls_rrrf_create @323
+ eqrls_rrrf_destroy @324
+ eqrls_rrrf_execute @325
+ eqrls_rrrf_get_bw @326
+ eqrls_rrrf_get_weights @327
+ eqrls_rrrf_print @328
+ eqrls_rrrf_push @329
+ eqrls_rrrf_recreate @330
+ eqrls_rrrf_reset @331
+ eqrls_rrrf_set_bw @332
+ eqrls_rrrf_step @333
+ eqrls_rrrf_train @334
+ estimate_req_filter_As @335
+ estimate_req_filter_df @336
+ estimate_req_filter_len @337
+ estimate_req_filter_len_Herrmann @338
+ estimate_req_filter_len_Kaiser @339
+ expand_cf_mulaw @340
+ expand_mulaw @341
+ fec_block_get_enc_msg_len @342
+ fec_conv27_poly @343 DATA
+ fec_conv27p23_matrix @344 DATA
+ fec_conv27p34_matrix @345 DATA
+ fec_conv27p45_matrix @346 DATA
+ fec_conv27p56_matrix @347 DATA
+ fec_conv27p67_matrix @348 DATA
+ fec_conv27p78_matrix @349 DATA
+ fec_conv29_poly @350 DATA
+ fec_conv29p23_matrix @351 DATA
+ fec_conv29p34_matrix @352 DATA
+ fec_conv29p45_matrix @353 DATA
+ fec_conv29p56_matrix @354 DATA
+ fec_conv29p67_matrix @355 DATA
+ fec_conv29p78_matrix @356 DATA
+ fec_conv39_poly @357 DATA
+ fec_conv615_poly @358 DATA
+ fec_conv_create @359
+ fec_conv_destroy @360
+ fec_conv_get_enc_msg_len @361
+ fec_conv_punctured_create @362
+ fec_conv_punctured_decode @363
+ fec_conv_punctured_destroy @364
+ fec_conv_punctured_encode @365
+ fec_create @366
+ fec_decode @367
+ fec_decode_soft @368
+ fec_destroy @369
+ fec_encode @370
+ fec_get_enc_msg_length @371
+ fec_get_rate @372
+ fec_golay2412_create @373
+ fec_golay2412_decode @374
+ fec_golay2412_decode_symbol @375
+ fec_golay2412_destroy @376
+ fec_golay2412_encode @377
+ fec_golay2412_encode_symbol @378
+ fec_hamming128_create @379
+ fec_hamming128_decode @380
+ fec_hamming128_decode_soft @381
+ fec_hamming128_decode_symbol @382
+ fec_hamming128_destroy @383
+ fec_hamming128_encode @384
+ fec_hamming128_encode_symbol @385
+ fec_hamming1511_decode_symbol @386
+ fec_hamming1511_encode_symbol @387
+ fec_hamming3126_decode_symbol @388
+ fec_hamming3126_encode_symbol @389
+ fec_hamming74_create @390
+ fec_hamming74_decode @391
+ fec_hamming74_decode_soft @392
+ fec_hamming74_destroy @393
+ fec_hamming74_encode @394
+ fec_hamming84_create @395
+ fec_hamming84_decode @396
+ fec_hamming84_decode_soft @397
+ fec_hamming84_destroy @398
+ fec_hamming84_encode @399
+ fec_pass_create @400
+ fec_pass_decode @401
+ fec_pass_destroy @402
+ fec_pass_encode @403
+ fec_pass_print @404
+ fec_print @405
+ fec_recreate @406
+ fec_rep3_create @407
+ fec_rep3_decode @408
+ fec_rep3_decode_soft @409
+ fec_rep3_destroy @410
+ fec_rep3_encode @411
+ fec_rep3_print @412
+ fec_rep5_create @413
+ fec_rep5_decode @414
+ fec_rep5_decode_soft @415
+ fec_rep5_destroy @416
+ fec_rep5_encode @417
+ fec_rep5_print @418
+ fec_rs_create @419
+ fec_rs_decode @420
+ fec_rs_destroy @421
+ fec_rs_encode @422
+ fec_rs_get_enc_msg_len @423
+ fec_scheme_is_convolutional @424
+ fec_scheme_is_hamming @425
+ fec_scheme_is_punctured @426
+ fec_scheme_is_reedsolomon @427
+ fec_scheme_is_repeat @428
+ fec_scheme_str @429 DATA
+ fec_secded2216_compute_parity @430
+ fec_secded2216_compute_syndrome @431
+ fec_secded2216_create @432
+ fec_secded2216_decode @433
+ fec_secded2216_decode_symbol @434
+ fec_secded2216_destroy @435
+ fec_secded2216_encode @436
+ fec_secded2216_encode_symbol @437
+ fec_secded2216_estimate_ehat @438
+ fec_secded3932_compute_parity @439
+ fec_secded3932_compute_syndrome @440
+ fec_secded3932_create @441
+ fec_secded3932_decode @442
+ fec_secded3932_decode_symbol @443
+ fec_secded3932_destroy @444
+ fec_secded3932_encode @445
+ fec_secded3932_encode_symbol @446
+ fec_secded3932_estimate_ehat @447
+ fec_secded7264_compute_parity @448
+ fec_secded7264_compute_syndrome @449
+ fec_secded7264_create @450
+ fec_secded7264_decode @451
+ fec_secded7264_decode_symbol @452
+ fec_secded7264_destroy @453
+ fec_secded7264_encode @454
+ fec_secded7264_encode_symbol @455
+ fec_secded7264_estimate_ehat @456
+ fec_sumproduct @457
+ fec_sumproduct_step @458
+ fecsoft_hamming128_decode @459
+ fecsoft_hamming128_decode_n3 @460
+ fecsoft_hamming128_n3 @461 DATA
+ fecsoft_hamming74_decode @462
+ fecsoft_hamming84_decode @463
+ fft_create_plan @464
+ fft_create_plan_dft @465
+ fft_create_plan_mixed_radix @466
+ fft_create_plan_r2r_1d @467
+ fft_create_plan_rader @468
+ fft_create_plan_rader2 @469
+ fft_create_plan_radix2 @470
+ fft_destroy_plan @471
+ fft_destroy_plan_dft @472
+ fft_destroy_plan_mixed_radix @473
+ fft_destroy_plan_r2r_1d @474
+ fft_destroy_plan_rader @475
+ fft_destroy_plan_rader2 @476
+ fft_destroy_plan_radix2 @477
+ fft_estimate_mixed_radix @478
+ fft_execute @479
+ fft_execute_REDFT00 @480
+ fft_execute_REDFT01 @481
+ fft_execute_REDFT10 @482
+ fft_execute_REDFT11 @483
+ fft_execute_RODFT00 @484
+ fft_execute_RODFT01 @485
+ fft_execute_RODFT10 @486
+ fft_execute_RODFT11 @487
+ fft_execute_dft @488
+ fft_execute_dft_16 @489
+ fft_execute_dft_2 @490
+ fft_execute_dft_3 @491
+ fft_execute_dft_4 @492
+ fft_execute_dft_5 @493
+ fft_execute_dft_6 @494
+ fft_execute_dft_7 @495
+ fft_execute_dft_8 @496
+ fft_execute_mixed_radix @497
+ fft_execute_rader @498
+ fft_execute_rader2 @499
+ fft_execute_radix2 @500
+ fft_is_radix2 @501
+ fft_print_plan @502
+ fft_print_plan_r2r_1d @503
+ fft_print_plan_recursive @504
+ fft_r2r_1d_run @505
+ fft_reverse_index @506
+ fft_run @507
+ fft_shift @508
+ fftfilt_cccf_create @509
+ fftfilt_cccf_destroy @510
+ fftfilt_cccf_execute @511
+ fftfilt_cccf_get_length @512
+ fftfilt_cccf_print @513
+ fftfilt_cccf_reset @514
+ fftfilt_cccf_set_scale @515
+ fftfilt_crcf_create @516
+ fftfilt_crcf_destroy @517
+ fftfilt_crcf_execute @518
+ fftfilt_crcf_get_length @519
+ fftfilt_crcf_print @520
+ fftfilt_crcf_reset @521
+ fftfilt_crcf_set_scale @522
+ fftfilt_rrrf_create @523
+ fftfilt_rrrf_destroy @524
+ fftfilt_rrrf_execute @525
+ fftfilt_rrrf_get_length @526
+ fftfilt_rrrf_print @527
+ fftfilt_rrrf_reset @528
+ fftfilt_rrrf_set_scale @529
+ fir_group_delay @530
+ firdecim_cccf_clear @531
+ firdecim_cccf_create @532
+ firdecim_cccf_create_prototype @533
+ firdecim_cccf_create_rnyquist @534
+ firdecim_cccf_destroy @535
+ firdecim_cccf_execute @536
+ firdecim_cccf_execute_block @537
+ firdecim_cccf_print @538
+ firdecim_crcf_clear @539
+ firdecim_crcf_create @540
+ firdecim_crcf_create_prototype @541
+ firdecim_crcf_create_rnyquist @542
+ firdecim_crcf_destroy @543
+ firdecim_crcf_execute @544
+ firdecim_crcf_execute_block @545
+ firdecim_crcf_print @546
+ firdecim_rrrf_clear @547
+ firdecim_rrrf_create @548
+ firdecim_rrrf_create_prototype @549
+ firdecim_rrrf_create_rnyquist @550
+ firdecim_rrrf_destroy @551
+ firdecim_rrrf_execute @552
+ firdecim_rrrf_execute_block @553
+ firdecim_rrrf_print @554
+ firdespm_compute_error @555
+ firdespm_compute_interp @556
+ firdespm_compute_taps @557
+ firdespm_create @558
+ firdespm_destroy @559
+ firdespm_execute @560
+ firdespm_iext_search @561
+ firdespm_init_grid @562
+ firdespm_is_search_complete @563
+ firdespm_print @564
+ firdespm_run @565
+ firfarrow_crcf_create @566
+ firfarrow_crcf_destroy @567
+ firfarrow_crcf_execute @568
+ firfarrow_crcf_execute_block @569
+ firfarrow_crcf_freqresponse @570
+ firfarrow_crcf_genpoly @571
+ firfarrow_crcf_get_coefficients @572
+ firfarrow_crcf_get_length @573
+ firfarrow_crcf_groupdelay @574
+ firfarrow_crcf_print @575
+ firfarrow_crcf_push @576
+ firfarrow_crcf_reset @577
+ firfarrow_crcf_set_delay @578
+ firfarrow_rrrf_create @579
+ firfarrow_rrrf_destroy @580
+ firfarrow_rrrf_execute @581
+ firfarrow_rrrf_execute_block @582
+ firfarrow_rrrf_freqresponse @583
+ firfarrow_rrrf_genpoly @584
+ firfarrow_rrrf_get_coefficients @585
+ firfarrow_rrrf_get_length @586
+ firfarrow_rrrf_groupdelay @587
+ firfarrow_rrrf_print @588
+ firfarrow_rrrf_push @589
+ firfarrow_rrrf_reset @590
+ firfarrow_rrrf_set_delay @591
+ firfilt_cccf_create @592
+ firfilt_cccf_create_kaiser @593
+ firfilt_cccf_create_rnyquist @594
+ firfilt_cccf_destroy @595
+ firfilt_cccf_execute @596
+ firfilt_cccf_execute_block @597
+ firfilt_cccf_freqresponse @598
+ firfilt_cccf_get_length @599
+ firfilt_cccf_groupdelay @600
+ firfilt_cccf_print @601
+ firfilt_cccf_push @602
+ firfilt_cccf_recreate @603
+ firfilt_cccf_reset @604
+ firfilt_cccf_set_scale @605
+ firfilt_crcf_create @606
+ firfilt_crcf_create_kaiser @607
+ firfilt_crcf_create_rnyquist @608
+ firfilt_crcf_destroy @609
+ firfilt_crcf_execute @610
+ firfilt_crcf_execute_block @611
+ firfilt_crcf_freqresponse @612
+ firfilt_crcf_get_length @613
+ firfilt_crcf_groupdelay @614
+ firfilt_crcf_print @615
+ firfilt_crcf_push @616
+ firfilt_crcf_recreate @617
+ firfilt_crcf_reset @618
+ firfilt_crcf_set_scale @619
+ firfilt_rrrf_create @620
+ firfilt_rrrf_create_kaiser @621
+ firfilt_rrrf_create_rnyquist @622
+ firfilt_rrrf_destroy @623
+ firfilt_rrrf_execute @624
+ firfilt_rrrf_execute_block @625
+ firfilt_rrrf_freqresponse @626
+ firfilt_rrrf_get_length @627
+ firfilt_rrrf_groupdelay @628
+ firfilt_rrrf_print @629
+ firfilt_rrrf_push @630
+ firfilt_rrrf_recreate @631
+ firfilt_rrrf_reset @632
+ firfilt_rrrf_set_scale @633
+ firhilbf_c2r_execute @634
+ firhilbf_create @635
+ firhilbf_decim_execute @636
+ firhilbf_destroy @637
+ firhilbf_interp_execute @638
+ firhilbf_print @639
+ firhilbf_r2c_execute @640
+ firhilbf_reset @641
+ firinterp_cccf_create @642
+ firinterp_cccf_create_nyquist @643
+ firinterp_cccf_create_prototype @644
+ firinterp_cccf_create_rnyquist @645
+ firinterp_cccf_destroy @646
+ firinterp_cccf_execute @647
+ firinterp_cccf_execute_block @648
+ firinterp_cccf_print @649
+ firinterp_cccf_reset @650
+ firinterp_crcf_create @651
+ firinterp_crcf_create_nyquist @652
+ firinterp_crcf_create_prototype @653
+ firinterp_crcf_create_rnyquist @654
+ firinterp_crcf_destroy @655
+ firinterp_crcf_execute @656
+ firinterp_crcf_execute_block @657
+ firinterp_crcf_print @658
+ firinterp_crcf_reset @659
+ firinterp_rrrf_create @660
+ firinterp_rrrf_create_nyquist @661
+ firinterp_rrrf_create_prototype @662
+ firinterp_rrrf_create_rnyquist @663
+ firinterp_rrrf_destroy @664
+ firinterp_rrrf_execute @665
+ firinterp_rrrf_execute_block @666
+ firinterp_rrrf_print @667
+ firinterp_rrrf_reset @668
+ firpfb_cccf_create @669
+ firpfb_cccf_create_drnyquist @670
+ firpfb_cccf_create_rnyquist @671
+ firpfb_cccf_destroy @672
+ firpfb_cccf_execute @673
+ firpfb_cccf_print @674
+ firpfb_cccf_push @675
+ firpfb_cccf_recreate @676
+ firpfb_cccf_reset @677
+ firpfb_crcf_create @678
+ firpfb_crcf_create_drnyquist @679
+ firpfb_crcf_create_rnyquist @680
+ firpfb_crcf_destroy @681
+ firpfb_crcf_execute @682
+ firpfb_crcf_print @683
+ firpfb_crcf_push @684
+ firpfb_crcf_recreate @685
+ firpfb_crcf_reset @686
+ firpfb_rrrf_create @687
+ firpfb_rrrf_create_drnyquist @688
+ firpfb_rrrf_create_rnyquist @689
+ firpfb_rrrf_destroy @690
+ firpfb_rrrf_execute @691
+ firpfb_rrrf_print @692
+ firpfb_rrrf_push @693
+ firpfb_rrrf_recreate @694
+ firpfb_rrrf_reset @695
+ firpfbch2_crcf_create @696
+ firpfbch2_crcf_create_kaiser @697
+ firpfbch2_crcf_destroy @698
+ firpfbch2_crcf_execute @699
+ firpfbch2_crcf_execute_analyzer @700
+ firpfbch2_crcf_execute_synthesizer @701
+ firpfbch2_crcf_print @702
+ firpfbch2_crcf_reset @703
+ firpfbch_cccf_analyzer_execute @704
+ firpfbch_cccf_analyzer_push @705
+ firpfbch_cccf_analyzer_run @706
+ firpfbch_cccf_create @707
+ firpfbch_cccf_create_kaiser @708
+ firpfbch_cccf_create_rnyquist @709
+ firpfbch_cccf_destroy @710
+ firpfbch_cccf_print @711
+ firpfbch_cccf_reset @712
+ firpfbch_cccf_synthesizer_execute @713
+ firpfbch_crcf_analyzer_execute @714
+ firpfbch_crcf_analyzer_push @715
+ firpfbch_crcf_analyzer_run @716
+ firpfbch_crcf_create @717
+ firpfbch_crcf_create_kaiser @718
+ firpfbch_crcf_create_rnyquist @719
+ firpfbch_crcf_destroy @720
+ firpfbch_crcf_print @721
+ firpfbch_crcf_reset @722
+ firpfbch_crcf_synthesizer_execute @723
+ flexframegen_assemble @724
+ flexframegen_create @725
+ flexframegen_destroy @726
+ flexframegen_encode_header @727
+ flexframegen_getframelen @728
+ flexframegen_getprops @729
+ flexframegen_is_assembled @730
+ flexframegen_modulate_header @731
+ flexframegen_modulate_payload @732
+ flexframegen_print @733
+ flexframegen_reconfigure @734
+ flexframegen_reset @735
+ flexframegen_setprops @736
+ flexframegen_write_header @737
+ flexframegen_write_payload @738
+ flexframegen_write_preamble @739
+ flexframegen_write_samples @740
+ flexframegen_write_tail @741
+ flexframegenprops_init_default @742
+ flexframesync_create @743
+ flexframesync_debug_disable @744
+ flexframesync_debug_enable @745
+ flexframesync_debug_print @746
+ flexframesync_decode_header @747
+ flexframesync_decode_payload @748
+ flexframesync_destroy @749
+ flexframesync_execute @750
+ flexframesync_execute_rxheader @751
+ flexframesync_execute_rxpayload @752
+ flexframesync_execute_rxpn @753
+ flexframesync_execute_seekpn @754
+ flexframesync_print @755
+ flexframesync_pushpn @756
+ flexframesync_reset @757
+ flexframesync_syncpn @758
+ flexframesync_update_symsync @759
+ fpoly_bessel @760
+ fpoly_bessel_roots @761
+ fpoly_bessel_roots_orchard @762
+ fpoly_bessel_roots_orchard_recursion @763
+ framegen64_byte_to_syms @764
+ framegen64_create @765
+ framegen64_destroy @766
+ framegen64_execute @767
+ framegen64_print @768
+ framesync64_create @769
+ framesync64_debug_disable @770
+ framesync64_debug_enable @771
+ framesync64_debug_print @772
+ framesync64_decode_payload @773
+ framesync64_destroy @774
+ framesync64_execute @775
+ framesync64_execute_rxpayload @776
+ framesync64_execute_rxpreamble @777
+ framesync64_execute_seekpn @778
+ framesync64_print @779
+ framesync64_pushpn @780
+ framesync64_reset @781
+ framesync64_syncpn @782
+ framesync64_update_symsync @783
+ framesyncstats_default @784 DATA
+ framesyncstats_init_default @785
+ framesyncstats_print @786
+ freqdem_create @787
+ freqdem_demodulate @788
+ freqdem_demodulate_block @789
+ freqdem_destroy @790
+ freqdem_print @791
+ freqdem_reset @792
+ freqmod_create @793
+ freqmod_destroy @794
+ freqmod_modulate @795
+ freqmod_modulate_block @796
+ freqmod_print @797
+ freqmod_reset @798
+ gasearch_create @799
+ gasearch_create_advanced @800
+ gasearch_crossover @801
+ gasearch_destroy @802
+ gasearch_evaluate @803
+ gasearch_evolve @804
+ gasearch_getopt @805
+ gasearch_mutate @806
+ gasearch_print @807
+ gasearch_rank @808
+ gasearch_run @809
+ gasearch_set_mutation_rate @810
+ gasearch_set_population_size @811
+ gmskdem_create @812
+ gmskdem_debug_print @813
+ gmskdem_demodulate @814
+ gmskdem_destroy @815
+ gmskdem_print @816
+ gmskdem_reset @817
+ gmskdem_set_eq_bw @818
+ gmskframegen_assemble @819
+ gmskframegen_create @820
+ gmskframegen_destroy @821
+ gmskframegen_encode_header @822
+ gmskframegen_getframelen @823
+ gmskframegen_print @824
+ gmskframegen_reset @825
+ gmskframegen_write_header @826
+ gmskframegen_write_payload @827
+ gmskframegen_write_preamble @828
+ gmskframegen_write_samples @829
+ gmskframegen_write_tail @830
+ gmskframesync_create @831
+ gmskframesync_debug_disable @832
+ gmskframesync_debug_enable @833
+ gmskframesync_debug_print @834
+ gmskframesync_decode_header @835
+ gmskframesync_destroy @836
+ gmskframesync_execute @837
+ gmskframesync_execute_detectframe @838
+ gmskframesync_execute_rxheader @839
+ gmskframesync_execute_rxpayload @840
+ gmskframesync_execute_rxpreamble @841
+ gmskframesync_print @842
+ gmskframesync_pushpn @843
+ gmskframesync_reset @844
+ gmskframesync_syncpn @845
+ gmskframesync_update_fi @846
+ gmskframesync_update_symsync @847
+ gmskmod_create @848
+ gmskmod_destroy @849
+ gmskmod_modulate @850
+ gmskmod_print @851
+ gmskmod_reset @852
+ golay2412_Gt @853 DATA
+ golay2412_H @854 DATA
+ golay2412_P @855 DATA
+ golay2412_matrix_mul @856
+ golay2412_parity_search @857
+ gradsearch_create @858
+ gradsearch_destroy @859
+ gradsearch_execute @860
+ gradsearch_gradient @861
+ gradsearch_linesearch @862
+ gradsearch_norm @863
+ gradsearch_print @864
+ gradsearch_step @865
+ gray_decode @866
+ gray_encode @867
+ hamming @868
+ hamming128_enc_gentab @869 DATA
+ hamming74_dec_gentab @870 DATA
+ hamming74_enc_gentab @871 DATA
+ hamming84_dec_gentab @872 DATA
+ hamming84_enc_gentab @873 DATA
+ hann @874
+ icrandnf @875
+ iir_group_delay @876
+ iirdecim_cccf_create @877
+ iirdecim_cccf_create_prototype @878
+ iirdecim_cccf_destroy @879
+ iirdecim_cccf_execute @880
+ iirdecim_cccf_execute_block @881
+ iirdecim_cccf_groupdelay @882
+ iirdecim_cccf_print @883
+ iirdecim_cccf_reset @884
+ iirdecim_crcf_create @885
+ iirdecim_crcf_create_prototype @886
+ iirdecim_crcf_destroy @887
+ iirdecim_crcf_execute @888
+ iirdecim_crcf_execute_block @889
+ iirdecim_crcf_groupdelay @890
+ iirdecim_crcf_print @891
+ iirdecim_crcf_reset @892
+ iirdecim_rrrf_create @893
+ iirdecim_rrrf_create_prototype @894
+ iirdecim_rrrf_destroy @895
+ iirdecim_rrrf_execute @896
+ iirdecim_rrrf_execute_block @897
+ iirdecim_rrrf_groupdelay @898
+ iirdecim_rrrf_print @899
+ iirdecim_rrrf_reset @900
+ iirdes_dzpk2sosf @901
+ iirdes_dzpk2tff @902
+ iirdes_dzpk_lp2bp @903
+ iirdes_dzpk_lp2hp @904
+ iirdes_freqprewarp @905
+ iirdes_isstable @906
+ iirdes_pll_active_PI @907
+ iirdes_pll_active_lag @908
+ iirfilt_cccf_create @909
+ iirfilt_cccf_create_dc_blocker @910
+ iirfilt_cccf_create_differentiator @911
+ iirfilt_cccf_create_integrator @912
+ iirfilt_cccf_create_pll @913
+ iirfilt_cccf_create_prototype @914
+ iirfilt_cccf_create_sos @915
+ iirfilt_cccf_destroy @916
+ iirfilt_cccf_execute @917
+ iirfilt_cccf_execute_block @918
+ iirfilt_cccf_execute_norm @919
+ iirfilt_cccf_execute_sos @920
+ iirfilt_cccf_freqresponse @921
+ iirfilt_cccf_get_length @922
+ iirfilt_cccf_groupdelay @923
+ iirfilt_cccf_print @924
+ iirfilt_cccf_reset @925
+ iirfilt_crcf_create @926
+ iirfilt_crcf_create_dc_blocker @927
+ iirfilt_crcf_create_differentiator @928
+ iirfilt_crcf_create_integrator @929
+ iirfilt_crcf_create_pll @930
+ iirfilt_crcf_create_prototype @931
+ iirfilt_crcf_create_sos @932
+ iirfilt_crcf_destroy @933
+ iirfilt_crcf_execute @934
+ iirfilt_crcf_execute_block @935
+ iirfilt_crcf_execute_norm @936
+ iirfilt_crcf_execute_sos @937
+ iirfilt_crcf_freqresponse @938
+ iirfilt_crcf_get_length @939
+ iirfilt_crcf_groupdelay @940
+ iirfilt_crcf_print @941
+ iirfilt_crcf_reset @942
+ iirfilt_rrrf_create @943
+ iirfilt_rrrf_create_dc_blocker @944
+ iirfilt_rrrf_create_differentiator @945
+ iirfilt_rrrf_create_integrator @946
+ iirfilt_rrrf_create_pll @947
+ iirfilt_rrrf_create_prototype @948
+ iirfilt_rrrf_create_sos @949
+ iirfilt_rrrf_destroy @950
+ iirfilt_rrrf_execute @951
+ iirfilt_rrrf_execute_block @952
+ iirfilt_rrrf_execute_norm @953
+ iirfilt_rrrf_execute_sos @954
+ iirfilt_rrrf_freqresponse @955
+ iirfilt_rrrf_get_length @956
+ iirfilt_rrrf_groupdelay @957
+ iirfilt_rrrf_print @958
+ iirfilt_rrrf_reset @959
+ iirfiltsos_cccf_create @960
+ iirfiltsos_cccf_destroy @961
+ iirfiltsos_cccf_execute @962
+ iirfiltsos_cccf_execute_df1 @963
+ iirfiltsos_cccf_execute_df2 @964
+ iirfiltsos_cccf_groupdelay @965
+ iirfiltsos_cccf_print @966
+ iirfiltsos_cccf_reset @967
+ iirfiltsos_cccf_set_coefficients @968
+ iirfiltsos_crcf_create @969
+ iirfiltsos_crcf_destroy @970
+ iirfiltsos_crcf_execute @971
+ iirfiltsos_crcf_execute_df1 @972
+ iirfiltsos_crcf_execute_df2 @973
+ iirfiltsos_crcf_groupdelay @974
+ iirfiltsos_crcf_print @975
+ iirfiltsos_crcf_reset @976
+ iirfiltsos_crcf_set_coefficients @977
+ iirfiltsos_rrrf_create @978
+ iirfiltsos_rrrf_destroy @979
+ iirfiltsos_rrrf_execute @980
+ iirfiltsos_rrrf_execute_df1 @981
+ iirfiltsos_rrrf_execute_df2 @982
+ iirfiltsos_rrrf_groupdelay @983
+ iirfiltsos_rrrf_print @984
+ iirfiltsos_rrrf_reset @985
+ iirfiltsos_rrrf_set_coefficients @986
+ iirinterp_cccf_create @987
+ iirinterp_cccf_create_prototype @988
+ iirinterp_cccf_destroy @989
+ iirinterp_cccf_execute @990
+ iirinterp_cccf_execute_block @991
+ iirinterp_cccf_groupdelay @992
+ iirinterp_cccf_print @993
+ iirinterp_cccf_reset @994
+ iirinterp_crcf_create @995
+ iirinterp_crcf_create_prototype @996
+ iirinterp_crcf_destroy @997
+ iirinterp_crcf_execute @998
+ iirinterp_crcf_execute_block @999
+ iirinterp_crcf_groupdelay @1000
+ iirinterp_crcf_print @1001
+ iirinterp_crcf_reset @1002
+ iirinterp_rrrf_create @1003
+ iirinterp_rrrf_create_prototype @1004
+ iirinterp_rrrf_destroy @1005
+ iirinterp_rrrf_execute @1006
+ iirinterp_rrrf_execute_block @1007
+ iirinterp_rrrf_groupdelay @1008
+ iirinterp_rrrf_print @1009
+ iirinterp_rrrf_reset @1010
+ interleaver_create @1011
+ interleaver_decode @1012
+ interleaver_decode_soft @1013
+ interleaver_destroy @1014
+ interleaver_encode @1015
+ interleaver_encode_soft @1016
+ interleaver_permute @1017
+ interleaver_permute_mask @1018
+ interleaver_permute_mask_soft @1019
+ interleaver_permute_soft @1020
+ interleaver_print @1021
+ interleaver_set_depth @1022
+ kaiser @1023
+ kaiser_beta_As @1024
+ landenf @1025
+ liquid_MarcumQ1f @1026
+ liquid_MarcumQf @1027
+ liquid_Qf @1028
+ liquid_apsk128 @1029 DATA
+ liquid_apsk16 @1030 DATA
+ liquid_apsk256 @1031 DATA
+ liquid_apsk32 @1032 DATA
+ liquid_apsk4 @1033 DATA
+ liquid_apsk64 @1034 DATA
+ liquid_apsk8 @1035 DATA
+ liquid_asechf @1036
+ liquid_bdotprod @1037
+ liquid_besseli0f @1038
+ liquid_besselif @1039
+ liquid_besselj0f @1040
+ liquid_besseljf @1041
+ liquid_c_leading_zeros @1042 DATA
+ liquid_c_ones @1043 DATA
+ liquid_c_ones_mod2 @1044 DATA
+ liquid_cacosf @1045
+ liquid_cargf_approx @1046
+ liquid_casinf @1047
+ liquid_catanf @1048
+ liquid_cexpf @1049
+ liquid_clogf @1050
+ liquid_cosf @1051
+ liquid_count_leading_zeros @1052
+ liquid_count_ones @1053
+ liquid_count_ones_mod2 @1054
+ liquid_cplxpair @1055
+ liquid_cplxpair_cleanup @1056
+ liquid_csqrtf @1057
+ liquid_expf @1058
+ liquid_factor @1059
+ liquid_factorialf @1060
+ liquid_fft_estimate_method @1061
+ liquid_filter_autocorr @1062
+ liquid_filter_crosscorr @1063
+ liquid_filter_energy @1064
+ liquid_filter_isi @1065
+ liquid_firdes_arkaiser @1066
+ liquid_firdes_doppler @1067
+ liquid_firdes_farcsech @1068
+ liquid_firdes_farcsech_freqresponse @1069
+ liquid_firdes_fexp @1070
+ liquid_firdes_fexp_freqresponse @1071
+ liquid_firdes_fnyquist @1072
+ liquid_firdes_fsech @1073
+ liquid_firdes_fsech_freqresponse @1074
+ liquid_firdes_gmskrx @1075
+ liquid_firdes_gmsktx @1076
+ liquid_firdes_hM3 @1077
+ liquid_firdes_kaiser @1078
+ liquid_firdes_nyquist @1079
+ liquid_firdes_rcos @1080
+ liquid_firdes_rfarcsech @1081
+ liquid_firdes_rfexp @1082
+ liquid_firdes_rfsech @1083
+ liquid_firdes_rkaiser @1084
+ liquid_firdes_rkaiser_bisection @1085
+ liquid_firdes_rkaiser_internal_isi @1086
+ liquid_firdes_rkaiser_quadratic @1087
+ liquid_firdes_rnyquist @1088
+ liquid_firdes_rrcos @1089
+ liquid_gammaf @1090
+ liquid_getopt_str2crc @1091
+ liquid_getopt_str2fec @1092
+ liquid_getopt_str2firfilt @1093
+ liquid_getopt_str2mod @1094
+ liquid_iirdes @1095
+ liquid_invgauss @1096
+ liquid_is_prime @1097
+ liquid_kbd @1098
+ liquid_kbd_window @1099
+ liquid_lbcircshift @1100
+ liquid_lbshift @1101
+ liquid_lcircshift @1102
+ liquid_levinson @1103
+ liquid_libversion @1104
+ liquid_libversion_number @1105
+ liquid_lnbesselif @1106
+ liquid_lngammaf @1107
+ liquid_lnlowergammaf @1108
+ liquid_lnuppergammaf @1109
+ liquid_logf @1110
+ liquid_lowergammaf @1111
+ liquid_lpc @1112
+ liquid_lshift @1113
+ liquid_modem_is_apsk @1114
+ liquid_modem_is_ask @1115
+ liquid_modem_is_dpsk @1116
+ liquid_modem_is_psk @1117
+ liquid_modem_is_qam @1118
+ liquid_modpow @1119
+ liquid_msb_index @1120
+ liquid_multimodal @1121
+ liquid_nchoosek @1122
+ liquid_nextpow2 @1123
+ liquid_pack_array @1124
+ liquid_pack_bytes @1125
+ liquid_pack_soft_bits @1126
+ liquid_primitive_root @1127
+ liquid_primitive_root_prime @1128
+ liquid_print_bitstring @1129
+ liquid_print_crc_schemes @1130
+ liquid_print_fec_schemes @1131
+ liquid_print_modulation_schemes @1132
+ liquid_rbcircshift @1133
+ liquid_rbshift @1134
+ liquid_rcircshift @1135
+ liquid_repack_bytes @1136
+ liquid_reverse_byte @1137
+ liquid_reverse_byte_gentab @1138 DATA
+ liquid_reverse_uint16 @1139
+ liquid_reverse_uint24 @1140
+ liquid_reverse_uint32 @1141
+ liquid_rosenbrock @1142
+ liquid_rshift @1143
+ liquid_sincosf @1144
+ liquid_sinf @1145
+ liquid_spiral @1146
+ liquid_sumsqcf @1147
+ liquid_sumsqf @1148
+ liquid_tanf @1149
+ liquid_totient @1150
+ liquid_unique_factor @1151
+ liquid_unpack_array @1152
+ liquid_unpack_bytes @1153
+ liquid_unpack_soft_bits @1154
+ liquid_unwrap_phase @1155
+ liquid_unwrap_phase2 @1156
+ liquid_uppergammaf @1157
+ liquid_vectorcf_abs @1158
+ liquid_vectorcf_add @1159
+ liquid_vectorcf_addscalar @1160
+ liquid_vectorcf_carg @1161
+ liquid_vectorcf_cexpj @1162
+ liquid_vectorcf_mul @1163
+ liquid_vectorcf_mulscalar @1164
+ liquid_vectorcf_norm @1165
+ liquid_vectorcf_normalize @1166
+ liquid_vectorf_abs @1167
+ liquid_vectorf_add @1168
+ liquid_vectorf_addscalar @1169
+ liquid_vectorf_carg @1170
+ liquid_vectorf_cexpj @1171
+ liquid_vectorf_mul @1172
+ liquid_vectorf_mulscalar @1173
+ liquid_vectorf_norm @1174
+ liquid_vectorf_normalize @1175
+ liquid_version @1176 DATA
+ matrix_add @1177
+ matrix_aug @1178
+ matrix_cgsolve @1179
+ matrix_chol @1180
+ matrix_det @1181
+ matrix_det2x2 @1182
+ matrix_div @1183
+ matrix_eye @1184
+ matrix_gjelim @1185
+ matrix_gramschmidt @1186
+ matrix_hermitian @1187
+ matrix_hermitian_mul @1188
+ matrix_inv @1189
+ matrix_linsolve @1190
+ matrix_ludecomp_crout @1191
+ matrix_ludecomp_doolittle @1192
+ matrix_mul @1193
+ matrix_mul_hermitian @1194
+ matrix_mul_transpose @1195
+ matrix_ones @1196
+ matrix_pdiv @1197
+ matrix_pivot @1198
+ matrix_pmul @1199
+ matrix_print @1200
+ matrix_proj @1201
+ matrix_qrdecomp_gramschmidt @1202
+ matrix_sub @1203
+ matrix_swaprows @1204
+ matrix_trans @1205
+ matrix_transpose_mul @1206
+ matrix_zeros @1207
+ matrixc_add @1208
+ matrixc_aug @1209
+ matrixc_cgsolve @1210
+ matrixc_chol @1211
+ matrixc_det @1212
+ matrixc_det2x2 @1213
+ matrixc_div @1214
+ matrixc_eye @1215
+ matrixc_gjelim @1216
+ matrixc_gramschmidt @1217
+ matrixc_hermitian @1218
+ matrixc_hermitian_mul @1219
+ matrixc_inv @1220
+ matrixc_linsolve @1221
+ matrixc_ludecomp_crout @1222
+ matrixc_ludecomp_doolittle @1223
+ matrixc_mul @1224
+ matrixc_mul_hermitian @1225
+ matrixc_mul_transpose @1226
+ matrixc_ones @1227
+ matrixc_pdiv @1228
+ matrixc_pivot @1229
+ matrixc_pmul @1230
+ matrixc_print @1231
+ matrixc_proj @1232
+ matrixc_qrdecomp_gramschmidt @1233
+ matrixc_sub @1234
+ matrixc_swaprows @1235
+ matrixc_trans @1236
+ matrixc_transpose_mul @1237
+ matrixc_zeros @1238
+ matrixcf_add @1239
+ matrixcf_aug @1240
+ matrixcf_cgsolve @1241
+ matrixcf_chol @1242
+ matrixcf_det @1243
+ matrixcf_det2x2 @1244
+ matrixcf_div @1245
+ matrixcf_eye @1246
+ matrixcf_gjelim @1247
+ matrixcf_gramschmidt @1248
+ matrixcf_hermitian @1249
+ matrixcf_hermitian_mul @1250
+ matrixcf_inv @1251
+ matrixcf_linsolve @1252
+ matrixcf_ludecomp_crout @1253
+ matrixcf_ludecomp_doolittle @1254
+ matrixcf_mul @1255
+ matrixcf_mul_hermitian @1256
+ matrixcf_mul_transpose @1257
+ matrixcf_ones @1258
+ matrixcf_pdiv @1259
+ matrixcf_pivot @1260
+ matrixcf_pmul @1261
+ matrixcf_print @1262
+ matrixcf_proj @1263
+ matrixcf_qrdecomp_gramschmidt @1264
+ matrixcf_sub @1265
+ matrixcf_swaprows @1266
+ matrixcf_trans @1267
+ matrixcf_transpose_mul @1268
+ matrixcf_zeros @1269
+ matrixf_add @1270
+ matrixf_aug @1271
+ matrixf_cgsolve @1272
+ matrixf_chol @1273
+ matrixf_det @1274
+ matrixf_det2x2 @1275
+ matrixf_div @1276
+ matrixf_eye @1277
+ matrixf_gjelim @1278
+ matrixf_gramschmidt @1279
+ matrixf_hermitian @1280
+ matrixf_hermitian_mul @1281
+ matrixf_inv @1282
+ matrixf_linsolve @1283
+ matrixf_ludecomp_crout @1284
+ matrixf_ludecomp_doolittle @1285
+ matrixf_mul @1286
+ matrixf_mul_hermitian @1287
+ matrixf_mul_transpose @1288
+ matrixf_ones @1289
+ matrixf_pdiv @1290
+ matrixf_pivot @1291
+ matrixf_pmul @1292
+ matrixf_print @1293
+ matrixf_proj @1294
+ matrixf_qrdecomp_gramschmidt @1295
+ matrixf_sub @1296
+ matrixf_swaprows @1297
+ matrixf_trans @1298
+ matrixf_transpose_mul @1299
+ matrixf_zeros @1300
+ modem_arb128opt @1301 DATA
+ modem_arb16opt @1302 DATA
+ modem_arb256opt @1303 DATA
+ modem_arb32opt @1304 DATA
+ modem_arb64opt @1305 DATA
+ modem_arb_V29 @1306 DATA
+ modem_arb_balance_iq @1307
+ modem_arb_init @1308
+ modem_arb_init_file @1309
+ modem_arb_scale @1310
+ modem_arb_sqam128 @1311 DATA
+ modem_arb_sqam32 @1312 DATA
+ modem_arb_vt64 @1313 DATA
+ modem_create @1314
+ modem_create_V29 @1315
+ modem_create_apsk @1316
+ modem_create_arb @1317
+ modem_create_arb128opt @1318
+ modem_create_arb16opt @1319
+ modem_create_arb256opt @1320
+ modem_create_arb32opt @1321
+ modem_create_arb64opt @1322
+ modem_create_arb64vt @1323
+ modem_create_arbitrary @1324
+ modem_create_ask @1325
+ modem_create_bpsk @1326
+ modem_create_dpsk @1327
+ modem_create_ook @1328
+ modem_create_psk @1329
+ modem_create_qam @1330
+ modem_create_qpsk @1331
+ modem_create_sqam128 @1332
+ modem_create_sqam32 @1333
+ modem_demodsoft_gentab @1334
+ modem_demodulate @1335
+ modem_demodulate_apsk @1336
+ modem_demodulate_arb @1337
+ modem_demodulate_ask @1338
+ modem_demodulate_bpsk @1339
+ modem_demodulate_dpsk @1340
+ modem_demodulate_linear_array @1341
+ modem_demodulate_linear_array_ref @1342
+ modem_demodulate_ook @1343
+ modem_demodulate_psk @1344
+ modem_demodulate_qam @1345
+ modem_demodulate_qpsk @1346
+ modem_demodulate_soft @1347
+ modem_demodulate_soft_arb @1348
+ modem_demodulate_soft_bpsk @1349
+ modem_demodulate_soft_qpsk @1350
+ modem_demodulate_soft_table @1351
+ modem_demodulate_sqam128 @1352
+ modem_demodulate_sqam32 @1353
+ modem_destroy @1354
+ modem_gen_rand_sym @1355
+ modem_get_bps @1356
+ modem_get_demodulator_evm @1357
+ modem_get_demodulator_phase_error @1358
+ modem_get_demodulator_sample @1359
+ modem_init @1360
+ modem_init_map @1361
+ modem_modulate @1362
+ modem_modulate_apsk @1363
+ modem_modulate_arb @1364
+ modem_modulate_ask @1365
+ modem_modulate_bpsk @1366
+ modem_modulate_dpsk @1367
+ modem_modulate_map @1368
+ modem_modulate_ook @1369
+ modem_modulate_psk @1370
+ modem_modulate_qam @1371
+ modem_modulate_qpsk @1372
+ modem_modulate_sqam128 @1373
+ modem_modulate_sqam32 @1374
+ modem_print @1375
+ modem_recreate @1376
+ modem_reset @1377
+ modulation_types @1378 DATA
+ msequence_advance @1379
+ msequence_create @1380
+ msequence_create_default @1381
+ msequence_create_genpoly @1382
+ msequence_default @1383 DATA
+ msequence_destroy @1384
+ msequence_generate_symbol @1385
+ msequence_get_length @1386
+ msequence_get_state @1387
+ msequence_print @1388
+ msequence_reset @1389
+ msequence_set_state @1390
+ msresamp2_cccf_create @1391
+ msresamp2_cccf_decim_execute @1392
+ msresamp2_cccf_destroy @1393
+ msresamp2_cccf_execute @1394
+ msresamp2_cccf_get_delay @1395
+ msresamp2_cccf_interp_execute @1396
+ msresamp2_cccf_print @1397
+ msresamp2_cccf_reset @1398
+ msresamp2_crcf_create @1399
+ msresamp2_crcf_decim_execute @1400
+ msresamp2_crcf_destroy @1401
+ msresamp2_crcf_execute @1402
+ msresamp2_crcf_get_delay @1403
+ msresamp2_crcf_interp_execute @1404
+ msresamp2_crcf_print @1405
+ msresamp2_crcf_reset @1406
+ msresamp2_rrrf_create @1407
+ msresamp2_rrrf_decim_execute @1408
+ msresamp2_rrrf_destroy @1409
+ msresamp2_rrrf_execute @1410
+ msresamp2_rrrf_get_delay @1411
+ msresamp2_rrrf_interp_execute @1412
+ msresamp2_rrrf_print @1413
+ msresamp2_rrrf_reset @1414
+ msresamp_cccf_create @1415
+ msresamp_cccf_decim_execute @1416
+ msresamp_cccf_destroy @1417
+ msresamp_cccf_execute @1418
+ msresamp_cccf_get_delay @1419
+ msresamp_cccf_interp_execute @1420
+ msresamp_cccf_print @1421
+ msresamp_cccf_reset @1422
+ msresamp_crcf_create @1423
+ msresamp_crcf_decim_execute @1424
+ msresamp_crcf_destroy @1425
+ msresamp_crcf_execute @1426
+ msresamp_crcf_get_delay @1427
+ msresamp_crcf_interp_execute @1428
+ msresamp_crcf_print @1429
+ msresamp_crcf_reset @1430
+ msresamp_rrrf_create @1431
+ msresamp_rrrf_decim_execute @1432
+ msresamp_rrrf_destroy @1433
+ msresamp_rrrf_execute @1434
+ msresamp_rrrf_get_delay @1435
+ msresamp_rrrf_interp_execute @1436
+ msresamp_rrrf_print @1437
+ msresamp_rrrf_reset @1438
+ nco_crcf_adjust_frequency @1439
+ nco_crcf_adjust_phase @1440
+ nco_crcf_cexpf @1441
+ nco_crcf_compute_sincos_nco @1442
+ nco_crcf_compute_sincos_vco @1443
+ nco_crcf_constrain_frequency @1444
+ nco_crcf_constrain_phase @1445
+ nco_crcf_cos @1446
+ nco_crcf_create @1447
+ nco_crcf_destroy @1448
+ nco_crcf_get_frequency @1449
+ nco_crcf_get_phase @1450
+ nco_crcf_mix_block_down @1451
+ nco_crcf_mix_block_up @1452
+ nco_crcf_mix_down @1453
+ nco_crcf_mix_up @1454
+ nco_crcf_pll_reset @1455
+ nco_crcf_pll_set_bandwidth @1456
+ nco_crcf_pll_step @1457
+ nco_crcf_reset @1458
+ nco_crcf_set_frequency @1459
+ nco_crcf_set_phase @1460
+ nco_crcf_sin @1461
+ nco_crcf_sincos @1462
+ nco_crcf_step @1463
+ ofdmflexframegen_assemble @1464
+ ofdmflexframegen_create @1465
+ ofdmflexframegen_destroy @1466
+ ofdmflexframegen_encode_header @1467
+ ofdmflexframegen_getframelen @1468
+ ofdmflexframegen_getprops @1469
+ ofdmflexframegen_is_assembled @1470
+ ofdmflexframegen_modulate_header @1471
+ ofdmflexframegen_print @1472
+ ofdmflexframegen_reconfigure @1473
+ ofdmflexframegen_reset @1474
+ ofdmflexframegen_setprops @1475
+ ofdmflexframegen_write_S0a @1476
+ ofdmflexframegen_write_S0b @1477
+ ofdmflexframegen_write_S1 @1478
+ ofdmflexframegen_write_header @1479
+ ofdmflexframegen_write_payload @1480
+ ofdmflexframegen_writesymbol @1481
+ ofdmflexframegenprops_init_default @1482
+ ofdmflexframesync_create @1483
+ ofdmflexframesync_debug_disable @1484
+ ofdmflexframesync_debug_enable @1485
+ ofdmflexframesync_debug_print @1486
+ ofdmflexframesync_decode_header @1487
+ ofdmflexframesync_destroy @1488
+ ofdmflexframesync_execute @1489
+ ofdmflexframesync_get_cfo @1490
+ ofdmflexframesync_get_rssi @1491
+ ofdmflexframesync_internal_callback @1492
+ ofdmflexframesync_print @1493
+ ofdmflexframesync_reset @1494
+ ofdmflexframesync_rxheader @1495
+ ofdmflexframesync_rxpayload @1496
+ ofdmframe_init_S0 @1497
+ ofdmframe_init_S1 @1498
+ ofdmframe_init_default_sctype @1499
+ ofdmframe_print_sctype @1500
+ ofdmframe_validate_sctype @1501
+ ofdmframegen_create @1502
+ ofdmframegen_destroy @1503
+ ofdmframegen_gensymbol @1504
+ ofdmframegen_print @1505
+ ofdmframegen_reset @1506
+ ofdmframegen_write_S0a @1507
+ ofdmframegen_write_S0b @1508
+ ofdmframegen_write_S1 @1509
+ ofdmframegen_writesymbol @1510
+ ofdmframegen_writetail @1511
+ ofdmframesync_S0_metrics @1512
+ ofdmframesync_create @1513
+ ofdmframesync_debug_disable @1514
+ ofdmframesync_debug_enable @1515
+ ofdmframesync_debug_print @1516
+ ofdmframesync_destroy @1517
+ ofdmframesync_estimate_eqgain @1518
+ ofdmframesync_estimate_eqgain_poly @1519
+ ofdmframesync_estimate_gain_S0 @1520
+ ofdmframesync_estimate_gain_S1 @1521
+ ofdmframesync_execute @1522
+ ofdmframesync_execute_S0a @1523
+ ofdmframesync_execute_S0b @1524
+ ofdmframesync_execute_S1 @1525
+ ofdmframesync_execute_rxsymbols @1526
+ ofdmframesync_execute_seekplcp @1527
+ ofdmframesync_get_cfo @1528
+ ofdmframesync_get_rssi @1529
+ ofdmframesync_print @1530
+ ofdmframesync_reset @1531
+ ofdmframesync_rxsymbol @1532
+ optim_sort @1533
+ optim_threshold_switch @1534
+ packetizer_compute_dec_msg_len @1535
+ packetizer_compute_enc_msg_len @1536
+ packetizer_create @1537
+ packetizer_decode @1538
+ packetizer_decode_soft @1539
+ packetizer_destroy @1540
+ packetizer_encode @1541
+ packetizer_get_dec_msg_len @1542
+ packetizer_get_enc_msg_len @1543
+ packetizer_print @1544
+ packetizer_realloc_buffers @1545
+ packetizer_recreate @1546
+ packetizer_set_scheme @1547
+ poly_expandbinomial @1548
+ poly_expandbinomial_pm @1549
+ poly_expandroots @1550
+ poly_expandroots2 @1551
+ poly_findroots @1552
+ poly_findroots_bairstow @1553
+ poly_findroots_bairstow_recursion @1554
+ poly_findroots_durandkerner @1555
+ poly_fit @1556
+ poly_fit_lagrange @1557
+ poly_fit_lagrange_barycentric @1558
+ poly_interp_lagrange @1559
+ poly_mul @1560
+ poly_val @1561
+ poly_val_lagrange_barycentric @1562
+ polyc_expandbinomial @1563
+ polyc_expandbinomial_pm @1564
+ polyc_expandroots @1565
+ polyc_expandroots2 @1566
+ polyc_findroots @1567
+ polyc_findroots_bairstow @1568
+ polyc_findroots_bairstow_recursion @1569
+ polyc_findroots_durandkerner @1570
+ polyc_fit @1571
+ polyc_fit_lagrange @1572
+ polyc_fit_lagrange_barycentric @1573
+ polyc_interp_lagrange @1574
+ polyc_mul @1575
+ polyc_val @1576
+ polyc_val_lagrange_barycentric @1577
+ polycf_expandbinomial @1578
+ polycf_expandbinomial_pm @1579
+ polycf_expandroots @1580
+ polycf_expandroots2 @1581
+ polycf_findroots @1582
+ polycf_findroots_bairstow @1583
+ polycf_findroots_bairstow_recursion @1584
+ polycf_findroots_durandkerner @1585
+ polycf_fit @1586
+ polycf_fit_lagrange @1587
+ polycf_fit_lagrange_barycentric @1588
+ polycf_interp_lagrange @1589
+ polycf_mul @1590
+ polycf_val @1591
+ polycf_val_lagrange_barycentric @1592
+ polyf_expandbinomial @1593
+ polyf_expandbinomial_pm @1594
+ polyf_expandroots @1595
+ polyf_expandroots2 @1596
+ polyf_findroots @1597
+ polyf_findroots_bairstow @1598
+ polyf_findroots_bairstow_recursion @1599
+ polyf_findroots_durandkerner @1600
+ polyf_fit @1601
+ polyf_fit_lagrange @1602
+ polyf_fit_lagrange_barycentric @1603
+ polyf_interp_lagrange @1604
+ polyf_mul @1605
+ polyf_val @1606
+ polyf_val_lagrange_barycentric @1607
+ presync_cccf_correlate @1608
+ presync_cccf_correlatex @1609
+ presync_cccf_create @1610
+ presync_cccf_destroy @1611
+ presync_cccf_print @1612
+ presync_cccf_push @1613
+ presync_cccf_reset @1614
+ qnsearch_compute_Hessian @1615
+ qnsearch_compute_gradient @1616
+ qnsearch_create @1617
+ qnsearch_destroy @1618
+ qnsearch_normalize_gradient @1619
+ qnsearch_print @1620
+ qnsearch_reset @1621
+ qnsearch_run @1622
+ qnsearch_step @1623
+ quantize_adc @1624
+ quantize_dac @1625
+ quantizercf_create @1626
+ quantizercf_destroy @1627
+ quantizercf_execute_adc @1628
+ quantizercf_execute_dac @1629
+ quantizercf_print @1630
+ quantizerf_create @1631
+ quantizerf_destroy @1632
+ quantizerf_execute_adc @1633
+ quantizerf_execute_dac @1634
+ quantizerf_print @1635
+ randexpf @1636
+ randexpf_cdf @1637
+ randexpf_pdf @1638
+ randf @1639
+ randf_cdf @1640
+ randf_pdf @1641
+ randgammaf @1642
+ randgammaf_cdf @1643
+ randgammaf_delta @1644
+ randgammaf_pdf @1645
+ randnakmf @1646
+ randnakmf_cdf @1647
+ randnakmf_pdf @1648
+ randnf @1649
+ randnf_cdf @1650
+ randnf_pdf @1651
+ randricekf @1652
+ randricekf_cdf @1653
+ randricekf_pdf @1654
+ randweibf @1655
+ randweibf_cdf @1656
+ randweibf_pdf @1657
+ resamp2_cccf_analyzer_execute @1658
+ resamp2_cccf_clear @1659
+ resamp2_cccf_create @1660
+ resamp2_cccf_decim_execute @1661
+ resamp2_cccf_destroy @1662
+ resamp2_cccf_filter_execute @1663
+ resamp2_cccf_get_delay @1664
+ resamp2_cccf_interp_execute @1665
+ resamp2_cccf_print @1666
+ resamp2_cccf_recreate @1667
+ resamp2_cccf_synthesizer_execute @1668
+ resamp2_crcf_analyzer_execute @1669
+ resamp2_crcf_clear @1670
+ resamp2_crcf_create @1671
+ resamp2_crcf_decim_execute @1672
+ resamp2_crcf_destroy @1673
+ resamp2_crcf_filter_execute @1674
+ resamp2_crcf_get_delay @1675
+ resamp2_crcf_interp_execute @1676
+ resamp2_crcf_print @1677
+ resamp2_crcf_recreate @1678
+ resamp2_crcf_synthesizer_execute @1679
+ resamp2_rrrf_analyzer_execute @1680
+ resamp2_rrrf_clear @1681
+ resamp2_rrrf_create @1682
+ resamp2_rrrf_decim_execute @1683
+ resamp2_rrrf_destroy @1684
+ resamp2_rrrf_filter_execute @1685
+ resamp2_rrrf_get_delay @1686
+ resamp2_rrrf_interp_execute @1687
+ resamp2_rrrf_print @1688
+ resamp2_rrrf_recreate @1689
+ resamp2_rrrf_synthesizer_execute @1690
+ resamp_cccf_create @1691
+ resamp_cccf_destroy @1692
+ resamp_cccf_execute @1693
+ resamp_cccf_execute_block @1694
+ resamp_cccf_get_delay @1695
+ resamp_cccf_print @1696
+ resamp_cccf_reset @1697
+ resamp_cccf_setrate @1698
+ resamp_cccf_update_timing_state @1699
+ resamp_crcf_create @1700
+ resamp_crcf_destroy @1701
+ resamp_crcf_execute @1702
+ resamp_crcf_execute_block @1703
+ resamp_crcf_get_delay @1704
+ resamp_crcf_print @1705
+ resamp_crcf_reset @1706
+ resamp_crcf_setrate @1707
+ resamp_crcf_update_timing_state @1708
+ resamp_rrrf_create @1709
+ resamp_rrrf_destroy @1710
+ resamp_rrrf_execute @1711
+ resamp_rrrf_execute_block @1712
+ resamp_rrrf_get_delay @1713
+ resamp_rrrf_print @1714
+ resamp_rrrf_reset @1715
+ resamp_rrrf_setrate @1716
+ resamp_rrrf_update_timing_state @1717
+ rkaiser_approximate_rho @1718
+ scramble_data @1719
+ secded2216_P @1720 DATA
+ secded2216_syndrome_w1 @1721 DATA
+ secded3932_P @1722 DATA
+ secded3932_syndrome_w1 @1723 DATA
+ secded7264_P @1724 DATA
+ secded7264_syndrome_w1 @1725 DATA
+ sincf @1726
+ smatrix_indexsearch @1727
+ smatrixb_clear @1728
+ smatrixb_create @1729
+ smatrixb_create_array @1730
+ smatrixb_delete @1731
+ smatrixb_destroy @1732
+ smatrixb_eye @1733
+ smatrixb_get @1734
+ smatrixb_insert @1735
+ smatrixb_isset @1736
+ smatrixb_mul @1737
+ smatrixb_mulf @1738
+ smatrixb_print @1739
+ smatrixb_print_expanded @1740
+ smatrixb_reset @1741
+ smatrixb_reset_max_mlist @1742
+ smatrixb_reset_max_nlist @1743
+ smatrixb_set @1744
+ smatrixb_size @1745
+ smatrixb_vmul @1746
+ smatrixb_vmulf @1747
+ smatrixf_clear @1748
+ smatrixf_create @1749
+ smatrixf_create_array @1750
+ smatrixf_delete @1751
+ smatrixf_destroy @1752
+ smatrixf_eye @1753
+ smatrixf_get @1754
+ smatrixf_insert @1755
+ smatrixf_isset @1756
+ smatrixf_mul @1757
+ smatrixf_print @1758
+ smatrixf_print_expanded @1759
+ smatrixf_reset @1760
+ smatrixf_reset_max_mlist @1761
+ smatrixf_reset_max_nlist @1762
+ smatrixf_set @1763
+ smatrixf_size @1764
+ smatrixf_vmul @1765
+ smatrixi_clear @1766
+ smatrixi_create @1767
+ smatrixi_create_array @1768
+ smatrixi_delete @1769
+ smatrixi_destroy @1770
+ smatrixi_eye @1771
+ smatrixi_get @1772
+ smatrixi_insert @1773
+ smatrixi_isset @1774
+ smatrixi_mul @1775
+ smatrixi_print @1776
+ smatrixi_print_expanded @1777
+ smatrixi_reset @1778
+ smatrixi_reset_max_mlist @1779
+ smatrixi_reset_max_nlist @1780
+ smatrixi_set @1781
+ smatrixi_size @1782
+ smatrixi_vmul @1783
+ spgramcf_accumulate_psd @1784
+ spgramcf_create @1785
+ spgramcf_create_kaiser @1786
+ spgramcf_destroy @1787
+ spgramcf_estimate_psd @1788
+ spgramcf_execute @1789
+ spgramcf_push @1790
+ spgramcf_reset @1791
+ spgramcf_write_accumulation @1792
+ spgramf_accumulate_psd @1793
+ spgramf_create @1794
+ spgramf_create_kaiser @1795
+ spgramf_destroy @1796
+ spgramf_estimate_psd @1797
+ spgramf_execute @1798
+ spgramf_push @1799
+ spgramf_reset @1800
+ spgramf_write_accumulation @1801
+ sumproduct_phi @1802
+ symsync_crcf_advance_internal_loop @1803
+ symsync_crcf_create @1804
+ symsync_crcf_create_kaiser @1805
+ symsync_crcf_create_rnyquist @1806
+ symsync_crcf_destroy @1807
+ symsync_crcf_execute @1808
+ symsync_crcf_get_tau @1809
+ symsync_crcf_lock @1810
+ symsync_crcf_output_debug_file @1811
+ symsync_crcf_print @1812
+ symsync_crcf_reset @1813
+ symsync_crcf_set_lf_bw @1814
+ symsync_crcf_set_output_rate @1815
+ symsync_crcf_setrate @1816
+ symsync_crcf_step @1817
+ symsync_crcf_unlock @1818
+ symsync_rrrf_advance_internal_loop @1819
+ symsync_rrrf_create @1820
+ symsync_rrrf_create_kaiser @1821
+ symsync_rrrf_create_rnyquist @1822
+ symsync_rrrf_destroy @1823
+ symsync_rrrf_execute @1824
+ symsync_rrrf_get_tau @1825
+ symsync_rrrf_lock @1826
+ symsync_rrrf_output_debug_file @1827
+ symsync_rrrf_print @1828
+ symsync_rrrf_reset @1829
+ symsync_rrrf_set_lf_bw @1830
+ symsync_rrrf_set_output_rate @1831
+ symsync_rrrf_setrate @1832
+ symsync_rrrf_step @1833
+ symsync_rrrf_unlock @1834
+ unscramble_data @1835
+ unscramble_data_soft @1836
+ wdelaycf_clear @1837
+ wdelaycf_create @1838
+ wdelaycf_destroy @1839
+ wdelaycf_print @1840
+ wdelaycf_push @1841
+ wdelaycf_read @1842
+ wdelaycf_recreate @1843
+ wdelayf_clear @1844
+ wdelayf_create @1845
+ wdelayf_destroy @1846
+ wdelayf_print @1847
+ wdelayf_push @1848
+ wdelayf_read @1849
+ wdelayf_recreate @1850
+ windowcf_clear @1851
+ windowcf_create @1852
+ windowcf_debug_print @1853
+ windowcf_destroy @1854
+ windowcf_index @1855
+ windowcf_print @1856
+ windowcf_push @1857
+ windowcf_read @1858
+ windowcf_recreate @1859
+ windowcf_write @1860
+ windowf_clear @1861
+ windowf_create @1862
+ windowf_debug_print @1863
+ windowf_destroy @1864
+ windowf_index @1865
+ windowf_print @1866
+ windowf_push @1867
+ windowf_read @1868
+ windowf_recreate @1869
+ windowf_write @1870
diff --git a/external/liquid-dsp/lib/libliquid.dll b/external/liquid-dsp/lib/libliquid.dll
new file mode 100644
index 0000000..84dbf2d
Binary files /dev/null and b/external/liquid-dsp/lib/libliquid.dll differ
diff --git a/src/CubicSDRDefs.h b/src/CubicSDRDefs.h
index 649a715..0e9c236 100644
--- a/src/CubicSDRDefs.h
+++ b/src/CubicSDRDefs.h
@@ -2,7 +2,7 @@
#define BUF_SIZE (16 * 32 * 256)
#define SRATE 2500000
-#define FFT_SIZE 4096
+#define FFT_SIZE BUF_SIZE / 2
#define DEFAULT_FREQ 105700000
diff --git a/src/PrimaryGLContext.cpp b/src/PrimaryGLContext.cpp
index cd1c960..51d6e7b 100644
--- a/src/PrimaryGLContext.cpp
+++ b/src/PrimaryGLContext.cpp
@@ -15,6 +15,8 @@
#include "AppFrame.h"
#include
#include "Demodulate.h"
+#include "liquid.h"
+#include "complex.h"
wxString glGetwxString(GLenum name) {
const GLubyte *v = glGetString(name);
@@ -113,8 +115,8 @@ TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) :
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * in_block_size);
out[0] = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * out_block_size);
out[1] = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * out_block_size);
- plan[0] = fftw_plan_dft_1d(out_block_size, in, out[0], FFTW_BACKWARD, FFTW_MEASURE);
- plan[1] = fftw_plan_dft_1d(out_block_size, in, out[1], FFTW_FORWARD, FFTW_MEASURE);
+ plan[0] = fftw_plan_dft_1d(out_block_size, in, out[0], FFTW_FORWARD, FFTW_MEASURE);
+ plan[1] = fftw_plan_dft_1d(out_block_size, out[0], out[1], FFTW_BACKWARD, FFTW_MEASURE);
fft_ceil_ma = fft_ceil_maa = 1.0;
@@ -140,7 +142,7 @@ TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) :
format = AL_FORMAT_MONO16;
for (int i = 0; i < AL_NUM_BUFFERS; i++) {
- alBufferData(buffers[i], format, buffer_init, AL_BUFFER_SIZE, demod.output.rate);
+ alBufferData(buffers[i], format, buffer_init, AL_BUFFER_SIZE, demod.output.rate);
}
if (alGetError() != AL_NO_ERROR) {
std::cout << "Error priming :(\n";
@@ -152,6 +154,29 @@ TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList) :
std::cout << "Error starting :(\n";
}
+ // define filter length, type, number of bands
+ unsigned int n = 55;
+ liquid_firdespm_btype btype = LIQUID_FIRDESPM_BANDPASS;
+ unsigned int num_bands = 3;
+
+ // band edge description [size: num_bands x 2]
+ float bands[6] = { 0.0f, 0.14f, 0.15f, 0.35f, 0.36f, 0.5f };
+
+ // desired response [size: num_bands x 1]
+ float des[3] = { 1.0f, 0.0f, 1.0f };
+
+ // relative weights [size: num_bands x 1]
+ float weights[3] = { 1.0f, 1.0f, 1.0f };
+
+ // in-band weighting functions [size: num_bands x 1]
+ liquid_firdespm_wtype wtype[3] = { LIQUID_FIRDESPM_FLATWEIGHT, LIQUID_FIRDESPM_EXPWEIGHT, LIQUID_FIRDESPM_FLATWEIGHT };
+
+ // allocate memory for array and design filter
+ float h[n];
+ firdespm_run(n, num_bands, bands, des, weights, wtype, btype, h);
+
+ fir_filter = firfilt_crcf_create(h, n);
+
}
TestGLCanvas::~TestGLCanvas() {
@@ -203,77 +228,87 @@ void TestGLCanvas::OnKeyDown(wxKeyEvent& event) {
void TestGLCanvas::setData(std::vector *data) {
if (data && data->size()) {
+ /*
+ std::vector tmp(data->begin(), data->end());
+ demod.demod(tmp);
- std::vector tmp(data->begin(), data->end());
- demod.demod(tmp);
+ if (waveform_points.size() < demod.lp_len * 2) {
+ waveform_points.resize(demod.lp_len * 2);
+ }
- if (waveform_points.size() < demod.lp_len * 2) {
- waveform_points.resize(demod.lp_len * 2);
- }
+ float waveform_ceil = 0;
- float waveform_ceil = 0;
+ for (int i = 0, iMax = demod.lp_len; i < iMax; i++) {
+ float v = fabs(demod.lowpassed[i]);
+ if (v > waveform_ceil) {
+ waveform_ceil = v;
+ }
+ }
- for (int i = 0, iMax = demod.lp_len; i < iMax; i++) {
- float v = fabs(demod.lowpassed[i]);
- if (v > waveform_ceil) {
- waveform_ceil = v;
- }
- }
+ for (int i = 0, iMax = demod.lp_len; i < iMax; i++) {
+ waveform_points[i * 2 + 1] = (float) demod.lowpassed[i] / waveform_ceil;
+ waveform_points[i * 2] = ((double) i / (double) iMax);
+ }
- for (int i = 0, iMax = demod.lp_len; i < iMax; i++) {
- waveform_points[i * 2 + 1] = (float) demod.lowpassed[i] / waveform_ceil;
- waveform_points[i * 2] = ((double) i / (double) iMax);
- }
+ ALint val;
+ ALuint buffer;
- ALint val;
- ALuint buffer;
+ alGetSourcei(source, AL_SOURCE_STATE, &val);
+ if (val != AL_PLAYING) {
+ alSourcePlay(source);
+ }
- alGetSourcei(source, AL_SOURCE_STATE, &val);
- if (val != AL_PLAYING) {
- alSourcePlay(source);
- }
-
- // std::cout << "buffer: " << demod.output_target->len << "@" << frequency << std::endl;
- std::vector *newBuffer = new std::vector;
- newBuffer->resize(demod.output_target->len);
- memcpy(&(*newBuffer)[0],demod.output_target->buf,demod.output_target->len*2);
- audio_queue.push(newBuffer);
+ // std::cout << "buffer: " << demod.output_target->len << "@" << frequency << std::endl;
+ std::vector *newBuffer = new std::vector;
+ newBuffer->resize(demod.output_target->len);
+ memcpy(&(*newBuffer)[0],demod.output_target->buf,demod.output_target->len*2);
+ audio_queue.push(newBuffer);
- frequency = demod.output.rate;
+ frequency = demod.output.rate;
- while (audio_queue.size()>8) {
- alGetSourcei(source, AL_BUFFERS_PROCESSED, &val);
- if (val <= 0) {
- break;
- }
-
- std::vector *nextBuffer = audio_queue.front();
-
- alSourceUnqueueBuffers(source, 1, &buffer);
- alBufferData(buffer, format, &(*nextBuffer)[0], nextBuffer->size()*2, frequency);
- alSourceQueueBuffers(source, 1, &buffer);
+ while (audio_queue.size()>8) {
+ alGetSourcei(source, AL_BUFFERS_PROCESSED, &val);
+ if (val <= 0) {
+ break;
+ }
- audio_queue.pop();
-
- delete nextBuffer;
+ std::vector *nextBuffer = audio_queue.front();
- if (alGetError() != AL_NO_ERROR) {
- std::cout << "Error buffering :(\n";
- }
- }
+ alSourceUnqueueBuffers(source, 1, &buffer);
+ alBufferData(buffer, format, &(*nextBuffer)[0], nextBuffer->size()*2, frequency);
+ alSourceQueueBuffers(source, 1, &buffer);
+
+ audio_queue.pop();
+
+ delete nextBuffer;
+
+ if (alGetError() != AL_NO_ERROR) {
+ std::cout << "Error buffering :(\n";
+ }
+ }
+ */
if (spectrum_points.size() < FFT_SIZE * 2) {
spectrum_points.resize(FFT_SIZE * 2);
}
for (int i = 0; i < BUF_SIZE / 2; i++) {
- in[i][0] = (double) (*data)[i * 2] / 127.0f;
- in[i][1] = (double) (*data)[i * 2 + 1] / 127.0f;
+
+ liquid_float_complex x;
+ liquid_float_complex y;
+
+ x.real = (float) (*data)[i * 2] / 127.0f;
+ x.imag = (float) (*data)[i * 2 + 1] / 127.0f;
+
+ firfilt_crcf_push(fir_filter, x); // push input sample
+ firfilt_crcf_execute(fir_filter, &y); // compute output
+
+ in[i][0] = y.real;
+ in[i][1] = y.imag;
}
fftw_execute(plan[0]);
- fftw_execute(plan[1]);
double fft_ceil = 0;
// fft_floor,
@@ -284,23 +319,25 @@ void TestGLCanvas::setData(std::vector *data) {
fft_result_maa.resize(FFT_SIZE);
}
+ for (int i = 0, iMax = FFT_SIZE; i < iMax; i++) {
+ if (i>FFT_SIZE/4 && i < FFT_SIZE-FFT_SIZE/4) {
+ out[0][i][0] = 0;
+ out[0][i][1] = 0;
+ }
+ }
+
for (int j = 0; j < 2; j++) {
for (int i = 0, iMax = FFT_SIZE / 2; i < iMax; i++) {
- double a = out[j][j ? i : ((iMax - 1) - i)][0];
- double b = out[j][j ? i : ((iMax - 1) - i)][1];
+ double a = out[0][i][0];
+ double b = out[0][i][1];
double c = sqrt(a * a + b * b);
- double x = out[j ? 0 : 1][j ? ((FFT_SIZE - 1) - i) : ((FFT_SIZE / 2) + i)][0];
- double y = out[j ? 0 : 1][j ? ((FFT_SIZE - 1) - i) : ((FFT_SIZE / 2) + i)][1];
+ double x = out[0][FFT_SIZE / 2 + i][0];
+ double y = out[0][FFT_SIZE / 2 + i][1];
double z = sqrt(x * x + y * y);
- double r = (c < z) ? c : z;
-
- if (!j) {
- fft_result[i] = r;
- } else {
- fft_result[(FFT_SIZE / 2) + i] = r;
- }
+ fft_result[i] = z;
+ fft_result[FFT_SIZE/2 + i] = c;
}
}
@@ -318,6 +355,9 @@ void TestGLCanvas::setData(std::vector *data) {
fft_ceil_ma = fft_ceil_ma + (fft_ceil - fft_ceil_ma) * 0.05;
fft_ceil_maa = fft_ceil_maa + (fft_ceil - fft_ceil_maa) * 0.05;
+
+ fftw_execute(plan[1]);
+
for (int i = 0, iMax = FFT_SIZE; i < iMax; i++) {
spectrum_points[i * 2 + 1] = fft_result_maa[i] / fft_ceil_maa;
spectrum_points[i * 2] = ((double) i / (double) iMax);
diff --git a/src/PrimaryGLContext.h b/src/PrimaryGLContext.h
index 8c30aeb..e2eee7d 100644
--- a/src/PrimaryGLContext.h
+++ b/src/PrimaryGLContext.h
@@ -9,6 +9,8 @@
#include "CubicSDRDefs.h"
#include "fftw3.h"
+#include "liquid.h"
+
#include "Demodulate.h"
#ifdef WIN32
@@ -53,6 +55,8 @@ private:
fftw_complex *in, *out[2];
fftw_plan plan[2];
+ firfilt_crcf fir_filter;
+
float fft_ceil_ma, fft_ceil_maa;
std::vector fft_result;