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;