DELETED COPYING
Index: COPYING
==================================================================
--- COPYING
+++ COPYING
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- Copyright (C)
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-.
Index: Makefile
==================================================================
--- Makefile
+++ Makefile
@@ -1,49 +1,33 @@
-PROG = fex
-VER = 2.0
-CC ?= gcc
-DEPS = x11 cairo fftw3 sndfile
-DEFS = -DPROGRAM_NAME=${PROG} -DPROGRAM_VER=${VER}
-CFLAGS += $(shell pkg-config --cflags ${DEPS}) ${DEFS}
-LDLIBS += $(shell pkg-config --libs ${DEPS}) -lm -lXpm
-PREFIX ?= /usr
-MODULES = config fex fft spectro wave xlib
-HEADERS = fex.h
-MANPAGES = fex.1 fex-help.1
-VPATH = src:doc
+PROG = fex
+VER = 3.0pre
+PREFIX ?= /usr
+CC = g++
+CONFFILE ?= ${PREFIX}/share/${PROG}/${PROG}rc
+DEFS = -DPROGRAM_NAME=${PROG} -DPROGRAM_VER=${VER} -DDEFAULT_CONFIG=${CONFFILE}
+CPPFLAGS ?= -D_FORTIFY_SOURCE=2
+CXXFLAGS ?= -march=native -O2 -pipe -fstack-protector-strong -Wstack-protector
+LDFLAGS ?= -Wl,-O1,--sort-common,--as-needed,-z,relro
+CXXFLAGS += $(shell pkg-config --cflags sfml-all fftw3) -std=c++11 ${DEFS}
+LDLIBS += $(shell pkg-config --libs sfml-all fftw3)
+MODULES = config fex fft spectrogram
+MANPAGES = ${PROG}.1 ${PROG}rc.5
+VPATH = src
${PROG}: ${MODULES:%=%.o}
-xlib.o: xlib.c xlib_toolwin.c xlib_events.c xlib_actions.c ${HEADERS}
-
-config.o: config.c config.h ${HEADERS}
-
-%.o: %.c ${HEADERS}
+%.o: %.cpp %.hpp
install: ${PROG}
- @install -Dm755 ${PROG} ${DESTDIR}${PREFIX}/bin/${PROG}
- @install -Dm755 src/${PROG}-gtk ${DESTDIR}${PREFIX}/bin/${PROG}-gtk
- @install -Dm644 doc/${PROG}.1 ${DESTDIR}${PREFIX}/share/man/man1/${PROG}.1
- @install -Dm644 doc/${PROG}-help.1 ${DESTDIR}${PREFIX}/share/man/man1/${PROG}-help.1
- @mkdir -p ${DESTDIR}${PREFIX}/share/${PROG}
- @install -Dm644 share/config ${DESTDIR}${PREFIX}/share/${PROG}/config
- @install -Dm644 share/icon.png ${DESTDIR}${PREFIX}/share/pixmaps/${PROG}.png
- @install -Dm644 share/${PROG}.desktop ${DESTDIR}${PREFIX}/share/applications/${PROG}.desktop
-
-${MANPAGES}: fex%.1: fex%-1.tex
- @latex2man $< doc/$@
-
-man: ${MANPAGES}
+ @echo ${PROG}-${VER} is not a release candidate and is not suitable for installation
clean:
- @rm -f ${MODULES:%=%.o}
+ @rm -rf ${PROG}-*.tar.gz
+ @rm -rf ${MODULES:%=%.o}
distclean: clean
- @rm -f ${PROG} ${PROG}-${VER}.tar.gz
+ @rm -rf ${PROG}
-moreclean: distclean
- @cd doc && rm -f ${MANPAGES}
-
-dist: distclean
+tarball: distclean
@tar -czf ${PROG}-${VER}.tar.gz *
-.PHONY: clean dist distclean man
+.PHONY: clean distclean install tarball
ADDED Makefile.win
Index: Makefile.win
==================================================================
--- Makefile.win
+++ Makefile.win
@@ -0,0 +1,44 @@
+PROG = fex
+VER = 3.0pre
+PREFIX ?= /usr
+CC = i686-w64-mingw32-c++
+CXX = i686-w64-mingw32-c++
+CONFFILE ?= ${PREFIX}/share/${PROG}/${PROG}rc
+DEFS = -DPROGRAM_NAME=${PROG} -DPROGRAM_VER=${VER} -DDEFAULT_CONFIG=${CONFFILE}
+CPPFLAGS ?= -D_FORTIFY_SOURCE=2
+CXXFLAGS ?= -O2 -pipe --param=ssp-buffer-size=4
+LDFLAGS ?= -Wl,-O1,--sort-common,--as-needed
+CXXFLAGS += $(shell i686-w64-mingw32-pkg-config --cflags fftw3) -std=c++11 ${DEFS}
+LDLIBS += $(shell i686-w64-mingw32-pkg-config --libs fftw3) $(shell pkg-config --libs sfml-all)
+MODULES = config fex fft spectrogram
+MANPAGES = ${PROG}.1 ${PROG}rc.5
+VPATH = src
+
+${PROG}: ${MODULES:%=%.o}
+
+%.o: %.cpp %.hpp
+
+clean:
+ @rm -rf ${PROG}-*.tar.gz
+ @rm -rf ${MODULES:%=%.o}
+
+distclean: clean
+ @rm -rf ${PROG} *.tar.gz
+
+tarball: distclean
+ @tar -czf ${PROG}-${VER}.tar.gz *
+
+bundle: ${PROG}
+ @mv ${PROG} ${PROG}.exe
+ @cp /usr/i686-w64-mingw32/bin/libfftw3-3.dll ./
+ @cp /usr/i686-w64-mingw32/bin/libfftw3f-3.dll ./
+ @cp /usr/i686-w64-mingw32/bin/libfftw3l-3.dll ./
+ @cp /usr/i686-w64-mingw32/bin/sfml-audio-2.dll ./
+ @cp /usr/i686-w64-mingw32/bin/sfml-graphics-2.dll ./
+ @cp /usr/i686-w64-mingw32/bin/sfml-network-2.dll ./
+ @cp /usr/i686-w64-mingw32/bin/sfml-system-2.dll ./
+ @cp /usr/i686-w64-mingw32/bin/sfml-window-2.dll ./
+ @tar -czf ${PROG}-${VER}-win32.tar.gz ${PROG}.exe *.dll
+ @rm -f *.dll
+
+.PHONY: clean distclean tarball bundle
Index: README.md
==================================================================
--- README.md
+++ README.md
@@ -1,13 +1,8 @@
-#FEX
-
-The Frequency Excursion Calculator
-
-##Description
-
-FEX is a spectrographic analysis tool for bioacoustic signals.
-
-Further details will be described in an upcoming publication.
-
-
-
-
+
+2016.02.16 SFML branch is now minimally functional but not feature complete,
+well tested, or at all documented. The brave are free to tinker with it.
+Anyone with experience building for Windows is invited to fix my massively
+broken windows Makefile(s).
+
+2016.01.10 Branch created to test SFML. This branch is not yet ready for use.
+Please use Master branch.
ADDED TODO
Index: TODO
==================================================================
--- TODO
+++ TODO
@@ -0,0 +1,18 @@
+
+x Add eraser function to spectrogram module
+ - needs testing
+- Too many "magic numbers" for eraser sizes...
+x Implement config file reading
+ * offloaded to pyfex
+ * fex only uses command line parameters
+ * this makes porting across platforms easier
+ * at least for me: I have no idea where a Win user would keep config files.
+- Complete the python front end
+ x Parse config (ini) file to pass CLI parameters to fex binary
+ - Show file selection dialogs for chosing songs, and saving data
+ - Make either UI agnostic, or seperate versions for GTK, QT, etc
+ - Are there Win / Mac native python dialog APIs?
+ - Or do these need to use GTK/QT or Tk/Wx/...
+ - Need input from python coders (pull requests welcomed!)
+
+
DELETED doc/fex-1.tex
Index: doc/fex-1.tex
==================================================================
--- doc/fex-1.tex
+++ doc/fex-1.tex
@@ -1,117 +0,0 @@
-\documentclass{latex2man}
-
-\begin{Name}{1}{fex}{Jesse McClure}{Frequency Excusion}{FEX --- The frequency excursion calculator}
-
-\Prog{Fex} - The frequency excursion calculator
-
-\end{Name}
-
-\section{Synopsis}
-
-\Prog{fex}
- [\Opt{-l}|\Opt{--long}]
- [\Opt{-v}|\Opt{--version}]
- [\Opt{-v}|\Opt{--version}]
- \Arg{}
-
-\Prog{fex-gtk}
- [\Opt{-l}|\Opt{--long}]
- \Arg{}
- [\Arg{} ...]
-
-
-\section{Description}
-
-\Prog{Fex} is a bioacoustic analysis tool for calculating the frequency
-excursion of an audio recording of bird songs or other sound waves.
-
-\Prog{Fex-gtk} is a wrapper script for fex that facilitates batch
-processing of large numbers of wave files. \Prog{Fex-gtk} can be
-provided a list of file names, or can be run with no parameters to
-provide a dialog window to select input wave files. \Prog{Fex} will be
-run on each input file, and the results can either be stored to a data
-file or displayed in a dialog window upon completion.
-
-\Prog{Fex-gtk} is also the executable target of \File{fex.desktop} to
-allow for drag-and-drop operation of \Prog{fex}. The desktop file can
-accept any number of wave files as a drop target.
-
-\section{Options}
-
-\begin{description}
-\item[\Opt{-l}|\Opt{--long}]
- Provide three column output specifying the path length, path
- duration, and frequency excursion (calculated as path length over
- duration). Default is to provide only the frequency excursion value.
-\item[\Opt{-h}|\Opt{--help}]
- Print help message and exit.
-\item[\Opt{-v}|\Opt{--version}]
- Print version information and exit.
-\end{description}
-
-\section{Configuration}
-\Prog{Fex} is configured via a runtime configuration file read from one
-of
-\File{\$XDG\_CONFIG\_HOME/fex/config},
-\File{\$HOME/.config/fex/config},
-\File{\$HOME/.fexrc}, or
-\File{/usr/share/fex/config}.
-
-Read the example configuration file at \File{/usr/share/fex/config} for
-a complete description of the available options. Those listed below are
-only the most likely to be changed. Settings not listed below should be
-changed only with caution.
-
-\subsection{Settings}
-
-The options below are configured with the following format:
-
-\Opt{set} \Arg{option} = \Arg{value}
-
-\begin{description}
-\item[\Opt{threshold}]
- Amplitude at which points can be considered part of the signal
- in dB below the maximum amplitude.
-\item[\Opt{floor}]
- Sound floor for the spectrogram display
- in dB below the maximum amplitude.
-\item[\Opt{bandpass}]
- Hi pass and low pass filter values in kHz.
-\end{description}
-
-
-\subsection{Colors}
-
-Colors are configured with the following format where each setting is a
-floating point value between 0.00 and 1.00:
-
-\Opt{color} \Arg{element} = \Arg{Red} \Arg{Green} \Arg{Blue} \Arg{Alpha}
-\Arg{Width}
-
-\begin{description}
-\item[\Opt{spectrogram}]
- Background spectrogram
-\item[\Opt{threshold}]
- Points above the current threshold
-\item[\Opt{points}]
- Points included in the current frequency excursion calculation
-\item[\Opt{lines}]
- Lines connecting the peak points
-\end{description}
-
-\section{See Also}
-
-\Opt{fex-help}(1)
-
-\URL{http://wiki.behaviorenterprises.com/index.php?title=Frequency_Excursion}
-
-\section{Author}
-Copyright \copyright 2013-2014 Jesse McClure \\
-License GPLv3: GNU GPL version 3 \URL{http://gnu.org/licenses/gpl.html} \\
-This is free software: you are free to change and redistribute it. \\
-There is NO WARRANTY, to the extent permitted by law.
-
-Submit bug reports via the website: \\
-\URL{http://behaviorenterprises.com/?page=software\&package=fex}
-
-\LatexManEnd
DELETED doc/fex-help-1.tex
Index: doc/fex-help-1.tex
==================================================================
--- doc/fex-help-1.tex
+++ doc/fex-help-1.tex
@@ -1,85 +0,0 @@
-\documentclass{latex2man}
-
-\begin{Name}{1}{fex}{Jesse McClure}{Frequency Excusion Controls}{FEX --- The frequency excursion calculator}
-
-\Prog{Fex} can be readily controlled with either the keyboard or a mouse
-with a two-axis scroll wheel.
-
-\end{Name}
-
-\section{Directional Commands}
-
-Direction commands are specified by holding a modifier key and
-indicating the direction with a mouse scroll wheel, the home row
-directional keys (h k j l), or cursor arrow keys.
-
-\begin{Table}{5}
-\\\hline
-\Opt{Modifiers} &
- \Opt{Up} & \Opt{Down} & \Opt{Left} & \Opt{Right} \\\hline
-\Arg{None} &
- scroll & scroll & scroll & scroll \\
-&
- up & down & left & right \\
-\\
-\Arg{Control} &
- zoom & zoom & - & - \\
-&
- in & out & & & \\
-\\
-\Arg{Alt} &
- bigger & smaller & narrow & wider \\
-&
- eraser & eraser & eraser & eraser \\
-\\
-\Arg{Shift} &
- bigger & smaller & narrower & wider \\
-&
- points & points & lines & lines \\
-\\
-\Arg{Control+Shift} &
- fewer & more & darker & lighter \\
-&
- points & points & spectrogram & spectrogram \\\hline
-\end{Table}
-
-\section{Other Controls}
-
-\begin{description}
-\item[\Opt{Control+q}] Quit
-\item[\Opt{Control+s}] Save an image of the current view
-\item[\Opt{Shift+s}] Save an image of each layer of the current view
-(layers: spectrogram, threshold overlay, points/lines overlay)
-\item[\Opt{F1}] Show this help page
-\item[\Opt{F2}] Toggle visibility of the tool window
-\item[\Opt{t}] Toggle spectrogram layers
-\item[\Opt{c}] Toggle crop mode
-\item[\Opt{e}] Toggle eraser mode
-\item[\Opt{Esc}] Return to normal mode
-\item[\Opt{u}] Undo last erase, in erase mode only, up to 7 undo levels
-\item[\Opt{p}] Play the currently displayed signal
-\item[\Opt{Shift+p}] Play the currently displayed signal at half speed
-\item[\Opt{Ctrl+p}] Play the currently displayed signal at 1/3 speed
-\item[\Opt{Alt+p}] Play the currently displayed signal at 1/4 speed
-\item[\Opt{Shift+Ctrl+p}] Play the currently displayed signal at 1/6 speed
-\item[\Opt{Shift+Alt+p}] Play the currently displayed signal at 1/12 speed
-\end{description}
-
-\section{Tool Window}
-
-The tool window displays the current cursor position and the currently
-calculated frequency excursion. The tool window also allows for
-point-and-click access to the available modes.
-
-\begin{description}
-\item[\Opt{Erase}] Toggle erase mode
-\item[\Opt{Crop}] \Arg{Left-click}: Toggle crop mode \Arg{Right-click}:
-Undo all cropping
-\end{description}
-
-
-\section{See Also}
-
-\Opt{fex}(1)
-
-\LatexManEnd
DELETED doc/fex-help.1
Index: doc/fex-help.1
==================================================================
--- doc/fex-help.1
+++ doc/fex-help.1
@@ -1,235 +0,0 @@
-'\" t
-.\" Manual page created with latex2man on Wed Jul 2 13:29:59 EDT 2014
-.\" NOTE: This file is generated, DO NOT EDIT.
-.de Vb
-.ft CW
-.nf
-..
-.de Ve
-.ft R
-
-.fi
-..
-.TH "FEX" "1" "02 July 2014" "Frequency Excusion Controls " "Frequency Excusion Controls "
-.SH NAME
-
-.PP
-Fex
-can be readily controlled with either the keyboard or a mouse
-with a two\-axis scroll wheel.
-.PP
-.SH DIRECTIONAL COMMANDS
-
-.PP
-Direction commands are specified by holding a modifier key and
-indicating the direction with a mouse scroll wheel, the home row
-directional keys (h k j l), or cursor arrow keys.
-.PP
-.TS
-tab(&);
-l l l l l.
-T{
-T}
-_
-T{
-\fBModifiers\fP
-T}&T{
-\fBUp\fP
-T}&T{
-\fBDown\fP
-T}&T{
-\fBLeft\fP
-T}&T{
-\fBRight\fP
-T}
-_
-T{
-\fINone\fP
-T}&T{
-scroll
-T}&T{
-scroll
-T}&T{
-scroll
-T}&T{
-scroll
-T}
-T{
-T}&T{
-up
-T}&T{
-down
-T}&T{
-left
-T}&T{
-right
-T}
-T{
-T}
-T{
-\fIControl\fP
-T}&T{
-zoom
-T}&T{
-zoom
-T}&T{
-\-
-T}&T{
-\-
-T}
-T{
-T}&T{
-in
-T}&T{
-out
-T}&T{
-T}&T{
-T}&T{
-T}
-T{
-T}
-T{
-\fIAlt\fP
-T}&T{
-bigger
-T}&T{
-smaller
-T}&T{
-narrow
-T}&T{
-wider
-T}
-T{
-T}&T{
-eraser
-T}&T{
-eraser
-T}&T{
-eraser
-T}&T{
-eraser
-T}
-T{
-T}
-T{
-\fIShift\fP
-T}&T{
-bigger
-T}&T{
-smaller
-T}&T{
-narrower
-T}&T{
-wider
-T}
-T{
-T}&T{
-points
-T}&T{
-points
-T}&T{
-lines
-T}&T{
-lines
-T}
-T{
-T}
-T{
-\fIControl+Shift\fP
-T}&T{
-fewer
-T}&T{
-more
-T}&T{
-darker
-T}&T{
-lighter
-T}
-T{
-T}&T{
-points
-T}&T{
-points
-T}&T{
-spectrogram
-T}&T{
-spectrogram
-T}
-_
-.TE
-.PP
-.SH OTHER CONTROLS
-
-.PP
-.TP
-\fBControl+q\fP
- Quit
-.TP
-\fBControl+s\fP
- Save an image of the current view
-.TP
-\fBShift+s\fP
- Save an image of each layer of the current view
-(layers: spectrogram, threshold overlay, points/lines overlay)
-.TP
-\fBF1\fP
- Show this help page
-.TP
-\fBF2\fP
- Toggle visibility of the tool window
-.TP
-\fBt\fP
- Toggle spectrogram layers
-.TP
-\fBc\fP
- Toggle crop mode
-.TP
-\fBe\fP
- Toggle eraser mode
-.TP
-\fBEsc\fP
- Return to normal mode
-.TP
-\fBu\fP
- Undo last erase, in erase mode only, up to 7 undo levels
-.TP
-\fBp\fP
- Play the currently displayed signal
-.TP
-\fBShift+p\fP
- Play the currently displayed signal at half speed
-.TP
-\fBCtrl+p\fP
- Play the currently displayed signal at 1/3 speed
-.TP
-\fBAlt+p\fP
- Play the currently displayed signal at 1/4 speed
-.TP
-\fBShift+Ctrl+p\fP
- Play the currently displayed signal at 1/6 speed
-.TP
-\fBShift+Alt+p\fP
- Play the currently displayed signal at 1/12 speed
-.PP
-.SH TOOL WINDOW
-
-.PP
-The tool window displays the current cursor position and the currently
-calculated frequency excursion. The tool window also allows for
-point\-and\-click access to the available modes.
-.PP
-.TP
-\fBErase\fP
- Toggle erase mode
-.TP
-\fBCrop\fP
- \fILeft\-click\fP:
-Toggle crop mode \fIRight\-click\fP:
-Undo all cropping
-.PP
-.SH SEE ALSO
-
-.PP
-\fBfex\fP(1)
-.PP
-.\" NOTE: This file is generated, DO NOT EDIT.
DELETED doc/fex.1
Index: doc/fex.1
==================================================================
--- doc/fex.1
+++ doc/fex.1
@@ -1,158 +0,0 @@
-'\" t
-.\" Manual page created with latex2man on Wed Oct 1 12:46:47 EDT 2014
-.\" NOTE: This file is generated, DO NOT EDIT.
-.de Vb
-.ft CW
-.nf
-..
-.de Ve
-.ft R
-
-.fi
-..
-.TH "FEX" "1" "01 October 2014" "Frequency Excusion " "Frequency Excusion "
-.SH NAME
-
-.PP
-Fex
-\- The frequency excursion calculator
-.PP
-.SH SYNOPSIS
-
-.PP
-fex
-[\fB\-l\fP|\fB\-\-long\fP]
-[\fB\-v\fP|\fB\-\-version\fP]
-[\fB\-v\fP|\fB\-\-version\fP]
-\fI\fP
-.PP
-fex\-gtk
-[\fB\-l\fP|\fB\-\-long\fP]
-\fI\fP
-[\fI\fP
-\&.\&.\&.]
-.PP
-.SH DESCRIPTION
-
-.PP
-Fex
-is a bioacoustic analysis tool for calculating the frequency
-excursion of an audio recording of bird songs or other sound waves.
-.PP
-Fex\-gtk
-is a wrapper script for fex that facilitates batch
-processing of large numbers of wave files. Fex\-gtk
-can be
-provided a list of file names, or can be run with no parameters to
-provide a dialog window to select input wave files. Fex
-will be
-run on each input file, and the results can either be stored to a data
-file or displayed in a dialog window upon completion.
-.PP
-Fex\-gtk
-is also the executable target of fex.desktop
-to
-allow for drag\-and\-drop operation of fex\&.
-The desktop file can
-accept any number of wave files as a drop target.
-.PP
-.SH OPTIONS
-
-.PP
-.TP
-\fB\-l\fP|\fB\-\-long\fP
- Provide three column output specifying the path length, path
-duration, and frequency excursion (calculated as path length over
-duration). Default is to provide only the frequency excursion value.
-.TP
-\fB\-h\fP|\fB\-\-help\fP
- Print help message and exit.
-.TP
-\fB\-v\fP|\fB\-\-version\fP
- Print version information and exit.
-.PP
-.SH CONFIGURATION
-
-Fex
-is configured via a runtime configuration file read from one
-of
-$XDG_CONFIG_HOME/fex/config,
-$HOME/.config/fex/config,
-$HOME/.fexrc,
-or
-/usr/share/fex/config\&.
-.PP
-Read the example configuration file at /usr/share/fex/config
-for
-a complete description of the available options. Those listed below are
-only the most likely to be changed. Settings not listed below should be
-changed only with caution.
-.PP
-.SS SETTINGS
-.PP
-The options below are configured with the following format:
-.PP
-\fBset\fP
-\fIoption\fP
-= \fIvalue\fP
-.PP
-.TP
-\fBthreshold\fP
- Amplitude at which points can be considered part of the signal
-in dB below the maximum amplitude.
-.TP
-\fBfloor\fP
- Sound floor for the spectrogram display
-in dB below the maximum amplitude.
-.TP
-\fBbandpass\fP
- Hi pass and low pass filter values in kHz.
-.PP
-.SS COLORS
-.PP
-Colors are configured with the following format where each setting is a
-floating point value between 0.00 and 1.00:
-.PP
-\fBcolor\fP
-\fIelement\fP
-= \fIRed\fP
-\fIGreen\fP
-\fIBlue\fP
-\fIAlpha\fP
-\fIWidth\fP
-.PP
-.TP
-\fBspectrogram\fP
- Background spectrogram
-.TP
-\fBthreshold\fP
- Points above the current threshold
-.TP
-\fBpoints\fP
- Points included in the current frequency excursion calculation
-.TP
-\fBlines\fP
- Lines connecting the peak points
-.PP
-.SH SEE ALSO
-
-.PP
-\fBfex\-help\fP(1)
-.PP
-\fBhttp://wiki.behaviorenterprises.com/index.php?title=Frequency_Excursion\fP
-.PP
-.SH AUTHOR
-
-Copyright (C)2013\-2014 Jesse McClure
-.br
-License GPLv3: GNU GPL version 3 \fBhttp://gnu.org/licenses/gpl.html\fP
-.br
-This is free software: you are free to change and redistribute it.
-.br
-There is NO WARRANTY, to the extent permitted by law.
-.PP
-Submit bug reports via the website:
-.br
-\fBhttp://behaviorenterprises.com/?page=software&package=fex\fP
-.PP
-.\" NOTE: This file is generated, DO NOT EDIT.
DELETED pkg/README.md
Index: pkg/README.md
==================================================================
--- pkg/README.md
+++ pkg/README.md
@@ -1,48 +0,0 @@
-###FEX Distibion and packaging
-
-For distributions equipped to build from git sources (e.g. Archlinux),
-all packaging materials will be provided in subdirectories here.
-
-For other distrobutions, I will work on making suitable packaging materials
-available and/or will gladly accept pull requests from those who are more
-familiar with other distros. The directories for such distros contain the
-materials I currently use to build packages for those targets.
-
-Binary and/or source packages will be available at the site below as they
-become available:
-
-http://behaviorenterprises.com/repo/
-
-####Dependencies
-
-The following packages and all their dependencies are required.
-
-+ cairo
-+ desktop-file-utils
-+ fftw
-+ libxpm
-+ libsndfile
-+ python2
-
-Dependencies for building fex include the above packages, along with any
-associated -dev or -devel packages for distros that use split packages, and,
-of course, git to pull the source code.
-
-####Building
-
-There is no need to configure:
-
-```bash
-git clone http://github.com/TrilbyWhite/fex.git
-cd fex
-make
-```
-
-####Installation
-
-make install accepts DESTDIR and PREFIX variables:
-
-```bash
-make DESTDIR=/path/to/pkgdir PREFIX=/usr install
-```
-
DELETED pkg/archlinux/PKGBUILD
Index: pkg/archlinux/PKGBUILD
==================================================================
--- pkg/archlinux/PKGBUILD
+++ pkg/archlinux/PKGBUILD
@@ -1,29 +0,0 @@
-# Maintainer: Jesse AKA "Trilby"
-_gitname="fex"
-pkgname="${_gitname}-git"
-pkgver=2.0
-pkgrel=1
-pkgdesc='Frequency Excursion Calculator'
-url='http://github.com/TrilbyWhite/fex.git'
-arch=('i686' 'x86_64')
-license=('GPL3')
-depends=('cairo' 'desktop-file-utils' 'fftw' 'libxpm' 'libsndfile' 'python2' 'pygtk' 'sox')
-makedepends=('git')
-install="${_gitname}.install"
-source=("${_gitname}::git://github.com/TrilbyWhite/fex.git")
-sha256sums=('SKIP')
-
-pkgver() {
- cd "${_gitname}";
- echo "2.$(git rev-list --count HEAD).$(git describe --always )"
-}
-
-build() {
- cd "${_gitname}"
- make
-}
-
-package() {
- cd "${_gitname}"
- make DESTDIR="${pkgdir}" install
-}
DELETED pkg/archlinux/fex.install
Index: pkg/archlinux/fex.install
==================================================================
--- pkg/archlinux/fex.install
+++ pkg/archlinux/fex.install
@@ -1,11 +0,0 @@
-post_install() {
- update-desktop-database -q
-}
-
-post_upgrade() {
- post_install $1
-}
-
-post_remove() {
- post_install $1
-}
DELETED pkg/deb/README
Index: pkg/deb/README
==================================================================
--- pkg/deb/README
+++ pkg/deb/README
@@ -1,8 +0,0 @@
-
-makedeb is experimental - use at your own risk.
-
-The goal is to be able to build debian packages from an rpm spec file -
-or something very close to it.
-
-26 Sept 2014 - makedeb succesfully built an installable deb package on ubunt 14
-
DELETED pkg/deb/fex-calc.spec
Index: pkg/deb/fex-calc.spec
==================================================================
--- pkg/deb/fex-calc.spec
+++ pkg/deb/fex-calc.spec
@@ -1,46 +0,0 @@
-summary: Frequency Excursion Calculator
-name: fex
-version: 2
-release: 1
-license: GPL3
-group: Applications/Science
-source: https://github.com/BehaviorEnterprises/Fex.git
-url: https://wiki.BehaviorEnterprises.com
-vendor: Behavior Enterprises
-packager: Jesse McClure
-requires: desktop-file-utils, libasound2, libcairo2, libfftw3-3, libsndfile1, libxpm4, python, python-gtk2
-buildrequires: libasound2-dev, libcairo2-dev, libfftw3-dev, gcc, libsndfile1-dev, libx11-dev, libxpm-dev, pkg-config
-prefix: /usr
-
-%description
-Frequency Excursion Calculator
-
-%prep
-%setup -c
-
-%build
-make
-
-%install
-make "DESTDIR=${RPM_BUILD_ROOT}" install
-
-%clean
-rm -rf "${RPM_BUILD_ROOT}"
-
-%post
-update-desktop-database -q
-
-%postun
-update-desktop-database -q
-
-%files
-/usr/bin/fex
-/usr/bin/fex-gtk
-/usr/share/applications/
-/usr/share/applications/fex.desktop
-/usr/share/fex/
-/usr/share/fex/config
-/usr/share/man/man1/fex-help.1.gz
-/usr/share/man/man1/fex.1.gz
-/usr/share/pixmaps/fex.png
-
DELETED pkg/deb/makedeb
Index: pkg/deb/makedeb
==================================================================
--- pkg/deb/makedeb
+++ pkg/deb/makedeb
@@ -1,88 +0,0 @@
-#!/bin/bash
-
-## VERSION:
-#V#MakeDEB
-#V# version 1.0, copyright 2014, Jesse McClure
-#V# license: CC-BY-SA https://creativecommons.org/licenses/by-sa/2.0/
-## HELP:
-
-if [[ -n $1 ]]; then
- case $1 in
- -h|--help|help) awk '/^#[VH]#/ { sub(/^#[VH]#/,""); print $0; }' $0 ;;
- -v|--ver*|ver*) awk '/^#V#/ { sub(/^#V#/,""); print $0; }' $0 ;;
- esac
- exit
-fi
-
-start_dir=$(pwd)
-
-spec=$(find -maxdepth 1 -name "*.spec")
-if [[ ! -f ${spec} ]]; then
- echo "No spec file found"
- exit 1
-fi
-
-## GET VALUES FROM SPEC FILE:
-pkgbase=$(awk -F ': ' '/^name:/ { print $2; }' ${spec})
-pkgname=$(basename ${spec})
-pkgname=${pkgname/\.spec/}
-git_url=$(awk -F ': ' '/^source:/ { print $2; }' ${spec})
-pkgver_base=$(awk -F ': ' '/^version:/ { print $2; }' ${spec})
-email=$(awk -F ': ' '/^packager:/ { print $2; }' ${spec})
-license=$(awk -F ': ' '/^license:/ { print $2; }' ${spec})
-upstream_url=$(awk -F ': ' '/^url:/ { print $2; }' ${spec})
-description=$(awk -F ': ' '/^summary:/ { print $2; }' ${spec})
-section=$(awk -F ': ' '/^group:/ { print $2; }' ${spec})
-build_deps=$(awk -F ': ' '/^buildrequires:/ { print $2; }' ${spec})
-deps=$(awk -F ': ' '/^requires:/ { print $2; }' ${spec})
-
-## CHECK BUILD ENVIRONMENT:
-#sudo apt-get install build-essential autoconf automake autotools-dev dh-make debhelper devscripts fakeroot xutils lintian pbuilder
-topdir=/tmp/makeDEB
-rm -rf ${topdir}/${pkgname}
-mkdir -p ${topdir}/${pkgname}
-
-## GET CODE AND MAKE SOURCE TARBALL:
-if [[ -d ${pkgname} ]]; then
- cd ${pkgname};
- git pull;
-else
- git clone ${git_url} ${pkgname}
- cd ${pkgname}
-fi
-pkgver="${pkgver_base}.$(git rev-list --count HEAD)"
-make dist
-mv ${pkgbase}*.tar.gz ${topdir}/${pkgname}/${pkgname}-${pkgver}.tar.gz
-
-## BUILD FOLDER PREPARATION
-cd ${start_dir}
-mv ${pkgname} ${topdir}/${pkgname}/${pkgname}-${pkgver}
-
-## DEBIANIZE
-cd ${topdir}/${pkgname}/${pkgname}-${pkgver}
-dh_make \
- --copyright "${license}" \
- --email "${email}" \
- --file "../${pkgname}-${pkgver}.tar.gz" \
- --single \
- --yes
-
-## EDIT CONTROL FILE
-sed -i 's|^Depends:.*|Depends: '"${deps}"'|' debian/control
-sed -i 's|^Build-Depends:.*|Build-Depends: '"${build_deps}"'|' debian/control
-sed -i 's|^Maintainer:.*|Maintainer: '"${email}"'|' debian/control
-sed -i 's|^Homepage:.*|Homepage: '"${upstream_url}"'|' debian/control
-sed -i 's|^Description:.*|Description: '"${description}"'|' debian/control
-sed -i 's|^Section:.*|Section: '"${section}"'|' debian/control
-
-## CREATE CHANGELOG
-#echo "${pkgname} (${pkgver}-1) unstable; urgency=low" > debian/changelog
-#echo "* Initial release" >> debian/changelog
-#echo "-- ${maintainer} <${email}> " >> debian/changelog
-
-## BUILD THE PACKAGE
-dpkg-buildpackage
-
-## CLEAN UP:
-cd ${startdir}
-
DELETED pkg/rpm/README
Index: pkg/rpm/README
==================================================================
--- pkg/rpm/README
+++ pkg/rpm/README
@@ -1,7 +0,0 @@
-makerpm uses rpmbuild and a slightly modified spec file (allowing a git
-source) to build an installable rpm file.
-
-Currently makerpm is being developed and tested on Fedora 20.
-
-TODO:
- find dependency for asoundlib.h
DELETED pkg/rpm/fex.spec
Index: pkg/rpm/fex.spec
==================================================================
--- pkg/rpm/fex.spec
+++ pkg/rpm/fex.spec
@@ -1,46 +0,0 @@
-summary: Frequency Excursion Calculator
-name: fex
-version: 2
-release: 1
-license: GPL3
-group: Applications/Science
-source: https://github.com/BehaviorEnterprises/Fex.git
-url: https://wiki.BehaviorEnterprises.com
-vendor: Behavior Enterprises
-packager: Jesse McClure jesse [at] mccluresk9 [dot] com
-requires: cairo, desktop-file-utils, fftw, libsndfile, libXpm, python, pygtk2, sox
-buildrequires: cairo-devel, fftw-devel, gcc, libsndfile-devel, libX11-devel, libXpm-devel, pkgconfig
-prefix: /usr
-
-%description
-Frequency Excursion Calculator
-
-%prep
-%setup -c
-
-%build
-make
-
-%install
-make "DESTDIR=${RPM_BUILD_ROOT}" install
-
-%clean
-rm -rf "${RPM_BUILD_ROOT}"
-
-%post
-update-desktop-database -q
-
-%postun
-update-desktop-database -q
-
-%files
-/usr/bin/fex
-/usr/bin/fex-gtk
-/usr/share/applications/
-/usr/share/applications/fex.desktop
-/usr/share/fex/
-/usr/share/fex/config
-/usr/share/man/man1/fex-help.1.gz
-/usr/share/man/man1/fex.1.gz
-/usr/share/pixmaps/fex.png
-
DELETED pkg/rpm/makerpm
Index: pkg/rpm/makerpm
==================================================================
--- pkg/rpm/makerpm
+++ pkg/rpm/makerpm
@@ -1,82 +0,0 @@
-#!/bin/bash
-
-## VERSION:
-#V#MakeRPM
-#V# version 1.0, copyright 2014, Jesse McClure
-#V# license: CC-BY-SA https://creativecommons.org/licenses/by-sa/2.0/
-## HELP:
-#H#
-#H#makerpm will look in the current working directory for a spec file with
-#H#the following requirements:
-#H#
-#H#1) The "source" line should provide a full git url from which the source
-#H#can be cloned
-#H#
-#H#2) The "version" line should provide only a base number upon which the
-#H#commit count will be appended
-#H#
-#H#The upstream git source must also include a Makefile in the toplevel
-#H#directory with a directive called 'dist' which will make a source
-#H#tarball (.tar.gz) in that same directory.
-#H#
-#H#makerpm will 1) revise the source and version lines in a copy placed in
-#H#rpmbuild's topdir/SPECS/ folder, 2) install the build dependencies if it
-#H#is the first build for the package on the machine, 3) obtain the git
-#H#source, 4) make the tarball and move it to topdir/SOURCES/, 5) build the
-#H#rpm and srpm, and 6) clean up / remove the cloned git dir.
-
-if [[ -n $1 ]]; then
- case $1 in
- -h|--help|help) awk '/^#[VH]#/ { sub(/^#[VH]#/,""); print $0; }' $0 ;;
- -v|--ver*|ver*) awk '/^#V#/ { sub(/^#V#/,""); print $0; }' $0 ;;
- esac
- exit
-fi
-exit
-
-start_dir=$(pwd)
-
-## CHECK FOR SPEC FILE:
-spec=$(find -name "*.spec")
-if [[ ! -f ${spec} ]]; then
- echo "No spec file found"
- return
-fi
-
-## GET VALUES FROM SPEC FILE:
-pkgname=$(awk '/^name:/ { print $2; }' ${spec})
-git_url=$(awk '/^source:/ { print $2; }' ${spec})
-pkgver_base=$(awk '/^version:/ { print $2; }' ${spec})
-
-return
-
-## CHECK BUILD ENVIRONMENT:
-topdir=$(rpmbuild --eval '%_topdir')
-mkdir -p ${topdir}/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
-
-## INSTALL BUILD DEPS IF FIRST BUILD:
-builds=$(find ${topdir}/RPMS/ -name "${pkgname}*")
-[[ -z $builds ]] && sudo yum-builddep ${spec}
-
-## GET CODE AND MAKE SOURCE TARBALL:
-git clone ${git_url}
-cd ${pkgname}
-pkgver="${pkgver_base}.$(git rev-list --count HEAD)"
-make dist
-mv ./${pkgname}*.tar.gz ${topdir}/SOURCES/${pkgname}-${pkgver}.tar.gz
-
-## PREPARE SPEC FILE:
-cd ${start_dir}
-cp ${spec} ${topdir}/SPECS/
-cd ${topdir}/SPECS/
-sed -i 's/^version: .*$/version: '${pkgver}'/' ${pkgname}.spec
-sed -i 's/^source: .*$/source: '${pkgname}-${pkgver}'.tar.gz/' ${pkgname}.spec
-
-## RUN RPMBUILD:
-cd ${topdir}/SPECS
-rpmbuild -ba ${pkgname}.spec
-
-## CLEAN UP:
-cd ${startdir}
-rm -rf ${pkgname}
-
ADDED pyfex/default.ini
Index: pyfex/default.ini
==================================================================
--- pyfex/default.ini
+++ pyfex/default.ini
@@ -0,0 +1,29 @@
+
+[defaults]
+window length = 256
+bin size = 64
+low pass = 01.25
+high pass = 10.00
+threshold = 18.00
+floor = 24.00
+log transform = false
+
+[colors]
+window background = #606468FF
+spectrogram background = #FFFFFFFF
+spectrogram foreground = #000000FF
+threshold = #58749848
+point border = #3399FFFF
+point fill = #3399FF48
+lines = #E86850FF
+cursor = #FF0000AA
+
+[warbler]
+#match file extension = wav
+#match mime type = audio/x-wav
+match path = warber
+threshold = 14.00
+
+[sparrow]
+match path = sparrow
+threshold = 24.00
ADDED pyfex/fexUI
Index: pyfex/fexUI
==================================================================
--- pyfex/fexUI
+++ pyfex/fexUI
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+
+from sys import argv
+from subprocess import DEVNULL, check_output
+from configparser import ConfigParser
+
+ini = ConfigParser()
+ini.read('default.ini')
+conf = ini['defaults']
+col = ini['colors']
+args = [
+ './fex',
+ '--winSize=' + conf['window length'],
+ '--binSize=' + conf['bin size'],
+ '--loPass=' + conf['low pass'],
+ '--hiPass=' + conf['high pass'],
+ '--threshold=' + conf['threshold'],
+ '--floor=' + conf['floor'],
+ '--log10=' + conf['log transform'],
+ '--winBG=' + col['window background'],
+ '--specBG=' + col['spectrogram background'],
+ '--specFG=' + col['spectrogram foreground'],
+ '--threshFG=' + col['threshold'],
+ '--pointBG=' + col['point fill'],
+ '--pointFG=' + col['point border'],
+ '--linesFG=' + col['lines']
+ '--cursorFG=' + col['cursor']
+]
+
+def run_fex(files):
+ if len(files) == 0:
+ print("zero")
+ # prompt with dialog returning list of files
+ # run_fex(list of files)
+ elif len(files) == 1:
+ print(check_output(args + [files[0]],stderr=DEVNULL).decode("utf-8"))
+ else:
+ print("many")
+ # loop through files running fex on each
+
+argv.remove(argv[0])
+run_fex(argv)
+
+
DELETED share/config
Index: share/config
==================================================================
--- share/config
+++ share/config
@@ -1,60 +0,0 @@
-## FEX Configuration
-##
-## Copy this file to one of the following locations for editing
-## $XDG_CONFIG_HOME/fex/config
-## $HOME/.config/fex/config
-## $HOME/.fexrc
-
-## Lines starting with a '#' sign are ignored as comments
-## but this file is not parsed by a shell interpreter.
-
-## Entries should be of one of two forms: 'set' or 'color'
-## set =
-## color =
-
-## Settings
-## threshold: decibels below the peak amplitude to include in signal
-## floor: decibels below the peak amplitude to show in the spectrogram
-## samples: number of samples per window for FFT
-## bandpass: bandpass filter in kHz
-## scale: number of graphical units per data unit
-## window: one of the following window functions for the FFT
-## hanning, hamming, blackman, nutall, blackman-nutall,
-## blackman-harris, rectangular, custom
-## Custom must be followed by up to 4 numbers specifying the
-## coefficients for a generalized cosine window function
-## fontFamily: font name
-## fontSize: font size in pixels
-## help: command for launching the help page
-## output: any combination of the following:
-## path: print path length
-## time: print path duration
-set threshold = 18.0
-set floor = 30.0
-set samples = 256
-set bandpass = 1.25 10.0
-set scale = 8
-set window = hanning
-set fontFamily = droid sans
-set fontSize = 14
-set help = xterm -e man fex-help
-
-## Colors
-## spectrogram: background spectrogram
-## threshold: points included in the signal
-## points: points included in the current excursion calculation
-## lines: lines connecting points in the current calculation
-## eraser1/2: two colors for eraser block
-## crop: crop window lines
-color spectrogram 0.0 0.0 0.0 1.0 1.0
-color threshold 0.0 1.0 0.8 0.4 1.0
-color points 0.0 0.1 0.5 0.8 8.0
-color lines 1.0 0.0 0.0 0.8 4.0
-color eraser1 1.0 1.0 0.6 1.0 1.0
-color eraser2 1.0 0.6 0.6 1.0 1.0
-color crop 0.0 1.0 0.2 1.0 2.0
-
-## NOTES:
-## For more information on configuring and using Fex, please see
-## http://wiki.behaviorenterprises.com/?title=Frequency_Excursion
-
DELETED share/fex.desktop
Index: share/fex.desktop
==================================================================
--- share/fex.desktop
+++ share/fex.desktop
@@ -1,10 +0,0 @@
-[Desktop Entry]
-Name=Fex
-Comment=Calculates the frequency excursion of a sound wave
-Exec=fex-gtk %F
-#Exec=fex-gtk --long %F
-Terminal=false
-Type=Application
-Categories=Science
-Icon=/usr/share/pixmaps/fex.png
-MimeType=audio/*
DELETED share/icon.png
Index: share/icon.png
==================================================================
--- share/icon.png
+++ share/icon.png
cannot compute difference between binary files
DELETED src/config.c
Index: src/config.c
==================================================================
--- src/config.c
+++ src/config.c
@@ -1,178 +0,0 @@
-/**********************************************************************\
-* FEX - The Frequency Excursion Calculator
-*
-* Author: Jesse McClure, copyright 2013-2014
-* License: GPL3
-*
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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
-* .
-*
-\**********************************************************************/
-
-#include "fex.h"
-
-#define CONF_SET 0x01
-#define CONF_COL 0x02
-
-#define C_TYPE__ 0x00
-#define C_TYPE_D 0x01
-#define C_TYPE_F 0x02
-#define C_TYPE_LF 0x03
-#define C_TYPE_S 0x04
-#define C_TYPE_LN 0x05
-
-#define STRING(s) STRINGIFY(s)
-#define STRINGIFY(s) #s
-#define LINE_LEN 256
-
-static WindowFunction custom;
-static WindowFunction windows[] = {
- { "hanning", {0.5, 0.5, 0.0, 0.0} },
- { "hamming", {0.54, 0.46, 0.0, 0.0} },
- { "blackman", {0.42659, 0.49656, 0.076849, 0.0} },
- { "nuttall", {0.355768, 0.487396, 0.144232, 0.012604} },
- { "blackman-nutall", {0.3635819, 0.4891775, 0.1365995, 0.0106411} },
- { "blackman-harris", {0.35875, 0.48829, 0.14128, 0.01168} },
- { "rectangular", {1.0, 0.0, 0.0, 0.0} },
-};
-
-static inline void version() {
- printf(STRING(PROGRAM_NAME) " v" STRING(PROGRAM_VER)
-", Copyright © 2013-2014 Jesse McClure \n"
-"You should have received a copy of the GNU General Public License\n"
-"along with this program. If not, see .\n");
- exit(0);
-}
-
-static inline void help() {
- printf("\n"
- "USAGE\n " STRING(PROGRAM_NAME) " \n\n"
- "OPTIONS\n"
- " -l|--long long output (path, duration, + FE)\n"
- " -v|--version show version information then exit\n"
- " -h|--help show help information then exit\n\n"
- "SEE ALSO\n"
- " fex(1) and fex-help(1)\n"
- "\n" );
- exit(0);
-}
-
-const char *configure(int argc, const char **argv) {
- int i;
- /* set defaults */
- const char *arg, *fname = NULL, *rcname = NULL;
- char help_cmd[256] = "xterm -e man man";
- conf.help_cmd = NULL;
- conf.long_out = False;
- conf.layers = True;
- /* process command line */
- for (i = 1; i < argc; i++) {
- arg = argv[i];
- if (strncmp(arg,"--h",3) == 0 || strncmp(arg,"-h",2) == 0)
- help();
- else if (strncmp(arg,"--v",3) == 0 || strncmp(arg,"-v",2) == 0)
- version();
- else if (strncmp(arg,"--l",3) == 0 || strncmp(arg,"-l",2) == 0)
- conf.long_out = True;
- else if (strncmp(arg,"-c",2) == 0 && (++i) < argc)
- rcname = argv[i];
- else
- fname = argv[i];
- }
- if (!fname) die("no audio file provided");
- /* find configuration file */
- FILE *rc = NULL;
- char *pwd = getenv("PWD");
- if (rcname) rc = fopen(rcname,"r");
- else if ( (!chdir(getenv("XDG_CONFIG_HOME")) && !chdir("fex")) ||
- (!chdir(getenv("HOME")) && !chdir(".config/fex")) )
- rc = fopen("config","r");
- if (!rc && !chdir(getenv("HOME"))) rc = fopen(".fexrc","r");
- chdir(pwd);
- if (!rc) rc = fopen("/usr/share/fex/config","r");
- if (!rc) die("unable to open configuration file");
- /* initialize conf structure and config reading variables */
- char line[LINE_LEN], prefix[32], option[32], fmt[LINE_LEN];
- char window[32], font_fam[LINE_LEN];
- const char *fspec[] = { "", "%d ","%f ", "%lf ", "%s", "%[^\n]" };
- int j, mode;
- conf.thresh = 14.0;
- conf.spect_floor = 40.0;
- conf.hipass = 12.0;
- conf.lopass = 800.0;
- conf.winlen = 256;
- conf.hop = 0;
- conf.win = (WindowFunction *) windows;
- struct {
- const char *name;
- int mode;
- int type[5];
- void *var[5];
- } cf[] = {
- #include "config.h"
- };
- /* read config file */
- while (fgets(line,LINE_LEN,rc)) {
- if (line[0] == '#' || line[0] == '\n') continue;
- sscanf(line,"%s %s",prefix,option);
- if (strncasecmp(prefix,"set",3) == 0) mode = CONF_SET;
- else if (strncasecmp(prefix,"col",3) == 0) mode = CONF_COL;
- else fprintf(stderr,"bad config entry: %s",line);
- sprintf(fmt,"%s %s ",prefix,option);
- if (mode == CONF_SET) strcat(fmt,"= ");
- for (i = 0; i < sizeof(cf) / sizeof(cf[0]); i++) {
- if ( !strncasecmp(option,cf[i].name,strlen(cf[i].name)) &&
- cf[i].mode == mode ) {
- for (j = 0; j < 5; j++) strcat(fmt,fspec[cf[i].type[j]]);
- sscanf(line,fmt,cf[i].var[0],cf[i].var[1],cf[i].var[2],
- cf[i].var[3],cf[i].var[4]);
- }
- }
- }
- /* set hop, threshold, floor, and windowing function */
- if (!conf.hop) conf.hop = conf.winlen / 4;
- conf.thresh *= -1;
- conf.spect_floor *= -1;
- if (strncasecmp(window,"custom",6) == 0)
- conf.win = (WindowFunction *) &custom;
- else if (strlen(window))
- for (i = 0; i < sizeof(windows)/sizeof(windows[0]); i++)
- if (!strncasecmp(window,windows[i].type,strlen(window)))
- conf.win = (WindowFunction *) &windows[i];
- /* set fonts */
- conf.font = cairo_toy_font_face_create(font_fam, CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_NORMAL);
- conf.bfont = cairo_toy_font_face_create(font_fam, CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
- /* prep 'help' function */
- char *help_arg = strtok(help_cmd," ");
- for (i = 0; help_arg; i++) {
- conf.help_cmd = realloc(conf.help_cmd, (i+2) * sizeof(char *));
- conf.help_cmd[i] = strdup(help_arg);
- conf.help_cmd[i+1] = NULL;
- help_arg = strtok(NULL," ");
- }
- /* return audio file name */
- return fname;
-}
-
-int deconfigure() {
- /* clean up, free data */
- int i;
- for (i = 0; conf.help_cmd[i]; i++) free(conf.help_cmd[i]);
- free(conf.help_cmd);
- cairo_font_face_destroy(conf.font);
- cairo_font_face_destroy(conf.bfont);
- return 0;
-}
ADDED src/config.cpp
Index: src/config.cpp
==================================================================
--- src/config.cpp
+++ src/config.cpp
@@ -0,0 +1,74 @@
+
+#include "config.hpp"
+#include
+
+sf::Color toColor(char *str) {
+ if (str[0] == '#') ++str;
+ unsigned long hex = strtoul(str,NULL,16);
+ unsigned short int r,g,b,a;
+ r = (hex & 0xFF000000) >> 24;
+ g = (hex & 0x00FF0000) >> 16;
+ b = (hex & 0x0000FF00) >> 8;
+ a = (hex & 0x000000FF);
+ return sf::Color(r,g,b,a);
+}
+
+bool toBool(char *str) {
+ switch (str[0]) {
+ case 'T': case 't': case '1': case 'Y': case 'y': return true; break;
+ case 'F': case 'f': case '0': case 'N': case 'n': return false; break;
+ default: return false;
+ }
+}
+
+Config::Config(int argc, char *const *argv) {
+ struct option opts[] = {
+ { "winSize", optional_argument, 0, 0 },
+ { "binSize", optional_argument, 0, 0 },
+ { "loPass", optional_argument, 0, 0 },
+ { "hiPass", optional_argument, 0, 0 },
+ { "threshold", optional_argument, 0, 0 },
+ { "floor", optional_argument, 0, 0 },
+ { "log10", optional_argument, 0, 0 },
+ { "winBG", optional_argument, 0, 0 },
+ { "specBG", optional_argument, 0, 0 },
+ { "specFG", optional_argument, 0, 0 },
+ { "threshFG", optional_argument, 0, 0 },
+ { "pointBG", optional_argument, 0, 0 },
+ { "pointFG", optional_argument, 0, 0 },
+ { "linesFG", optional_argument, 0, 0 },
+ { "cursorFG", optional_argument, 0, 0 },
+ {0, 0, 0, 0 }
+ };
+ int i, c, index;
+ char noarg[] = "";
+ for (i = 1; (c=getopt_long_only(argc, argv, "", opts, &index)) != -1; ++i) {
+ if (c != 0 || !optarg) continue;
+ else if (index == 0) conf.winlen = atoi(optarg);
+ else if (index == 1) conf.hop = atoi(optarg);
+ else if (index == 2) conf.lopass = atof(optarg);
+ else if (index == 3) conf.hipass = atof(optarg);
+ else if (index == 4) conf.threshold = atof(optarg);
+ else if (index == 5) conf.floor = atof(optarg);
+ else if (index == 6) conf.log10 = toBool(optarg);
+ else if (index == 7) conf.winBG = toColor(optarg);
+ else if (index == 8) conf.specBG = toColor(optarg);
+ else if (index == 9) conf.specFG = toColor(optarg);
+ else if (index == 10) conf.threshFG = toColor(optarg);
+ else if (index == 11) conf.pointBG = toColor(optarg);
+ else if (index == 12) conf.pointFG = toColor(optarg);
+ else if (index == 13) conf.linesFG = toColor(optarg);
+ else if (index == 14) conf.cursorFG = toColor(optarg);
+ }
+ if (i > argc) exit(1);
+ fname = strdup(argv[i]);
+ char *dup = strdup(argv[i]);
+ name = strdup(basename(dup));
+ free(dup);
+}
+
+Config::~Config() {
+ if (name) free(name);
+ if (fname) free(fname);
+}
+
DELETED src/config.h
Index: src/config.h
==================================================================
--- src/config.h
+++ src/config.h
@@ -1,63 +0,0 @@
-
-/* set */
-{ "threshold", CONF_SET,
- { C_TYPE_LF, C_TYPE__, C_TYPE__, C_TYPE__, C_TYPE__ },
- { &conf.thresh, NULL, NULL, NULL, NULL}, },
-{ "floor", CONF_SET,
- { C_TYPE_LF, C_TYPE__, C_TYPE__, C_TYPE__, C_TYPE__ },
- { &conf.spect_floor, NULL, NULL, NULL, NULL}, },
-{ "samples", CONF_SET,
- { C_TYPE_D, C_TYPE__, C_TYPE__, C_TYPE__, C_TYPE__ },
- { &conf.winlen, NULL, NULL, NULL, NULL}, },
-{ "hop", CONF_SET,
- { C_TYPE_D, C_TYPE__, C_TYPE__, C_TYPE__, C_TYPE__ },
- { &conf.hop, NULL, NULL, NULL, NULL}, },
-{ "bandpass", CONF_SET,
- { C_TYPE_LF, C_TYPE_LF, C_TYPE__, C_TYPE__, C_TYPE__ },
- { &conf.hipass, &conf.lopass, NULL, NULL, NULL}, },
-{ "scale", CONF_SET,
- { C_TYPE_D, C_TYPE_LF, C_TYPE__, C_TYPE__, C_TYPE__ },
- { &conf.scale, NULL, NULL, NULL, NULL}, },
-{ "window", CONF_SET,
- { C_TYPE_S, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF },
- { window, &custom.a[0], &custom.a[1], &custom.a[2], &custom.a[3]}, },
-{ "fontFamily", CONF_SET,
- { C_TYPE_LN, C_TYPE__, C_TYPE__, C_TYPE__, C_TYPE__ },
- { font_fam, NULL, NULL, NULL, NULL}, },
-{ "fontSize", CONF_SET,
- { C_TYPE_D, C_TYPE__, C_TYPE__, C_TYPE__, C_TYPE__ },
- { &conf.font_size, NULL, NULL, NULL, NULL}, },
-{ "help", CONF_SET,
- { C_TYPE_LN, C_TYPE__, C_TYPE__, C_TYPE__, C_TYPE__ },
- { &help_cmd, NULL, NULL, NULL, NULL}, },
-
-/* color */
-{ "spectrogram", CONF_COL,
- { C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF },
- { &conf.col[0].r, &conf.col[0].g, &conf.col[0].b, &conf.col[0].a,
- &conf.col[0].w } },
-{ "threshold", CONF_COL,
- { C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF },
- { &conf.col[1].r, &conf.col[1].g, &conf.col[1].b, &conf.col[1].a,
- &conf.col[1].w } },
-{ "points", CONF_COL,
- { C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF },
- { &conf.col[2].r, &conf.col[2].g, &conf.col[2].b, &conf.col[2].a,
- &conf.col[2].w } },
-{ "lines", CONF_COL,
- { C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF },
- { &conf.col[3].r, &conf.col[3].g, &conf.col[3].b, &conf.col[3].a,
- &conf.col[3].w } },
-{ "eraser1", CONF_COL,
- { C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF },
- { &conf.col[4].r, &conf.col[4].g, &conf.col[4].b, &conf.col[4].a,
- &conf.col[4].w } },
-{ "eraser2", CONF_COL,
- { C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF },
- { &conf.col[5].r, &conf.col[5].g, &conf.col[5].b, &conf.col[5].a,
- &conf.col[5].w } },
-{ "crop", CONF_COL,
- { C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF, C_TYPE_LF },
- { &conf.col[6].r, &conf.col[6].g, &conf.col[6].b, &conf.col[6].a,
- &conf.col[6].w } },
-
ADDED src/config.hpp
Index: src/config.hpp
==================================================================
--- src/config.hpp
+++ src/config.hpp
@@ -0,0 +1,37 @@
+
+#include
+#include
+#include
+#include
+
+class Config {
+ protected:
+ struct {
+ int winlen = 256;
+ int hop = 64;
+ double lopass = 01.25;
+ double hipass = 10.00;
+ double threshold = 18.00;
+ double floor = 24.00;
+ bool log10 = false;
+ sf::Color winBG = sf::Color(0x60,0x64,0x68);
+ sf::Color specBG = sf::Color(0xFF,0xFF,0xFF);
+ sf::Color specFG = sf::Color(0x00,0x00,0x00);
+ sf::Color threshFG = sf::Color(0x58,0x74,0x98,0x48);
+ sf::Color pointFG = sf::Color(0x33,0x99,0xFF);
+ sf::Color pointBG = sf::Color(0x33,0x99,0xFF,0x48);
+ sf::Color linesFG = sf::Color(0xE8,0x68,0x50);
+ sf::Color cursorFG = sf::Color(0xFF,0x00,0x00,0xAA);
+ } conf;
+ struct {
+ bool overlay = true;
+ bool cursor = false;
+ bool eraser = false;
+ } toggle;
+ char *fname = NULL, *name = NULL;
+
+ public:
+ Config(int, char *const *);
+ ~Config();
+};
+
DELETED src/fex-gtk
Index: src/fex-gtk
==================================================================
--- src/fex-gtk
+++ src/fex-gtk
@@ -1,118 +0,0 @@
-#!/usr/bin/env python2
-#----------------------------------------------------------------------#
-# FEX - The Frequency Excursion Calculator
-#
-# Author: Jesse McClure, copyright 2013-2014
-# License: GPL3
-#
-# This program is free software: you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see
-# .
-#
-#----------------------------------------------------------------------#
-
-import sys
-import os
-import subprocess
-import pygtk
-import gtk
-
-def main(argv):
- if (len(argv) > 0) and (argv[0] == "--long"):
- opt_long = True
- del argv[0]
- else:
- opt_long = False
- if (len(argv) == 0):
- filelist = input_files()
- else:
- filelist = argv
- if (len(filelist) == 0):
- sys.exit(0)
- if (opt_long):
- data = "Song\tPath\tTime\tFEX\n"
- else:
- data = "Song\tFEX\n"
- for filename in filelist:
- song = os.path.splitext(os.path.basename(filename))[0]
- try:
- if (opt_long):
- FE = subprocess.check_output(["fex","--long",filename])
- else:
- FE = subprocess.check_output(["fex",filename])
- except subprocess.CalledProcessError as err:
- FE = "NA\n"
- data = data + song + "\t" + FE
- if (len(filelist) == 1):
- filename = ""
- else:
- filename = data_file()
- if (len(filename) == 0):
- label = gtk.Label(data)
- win = gtk.Dialog("Fex", None,
- gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
- win.vbox.pack_start(label)
- label.show()
- win.run()
- else:
- fptr = open(filename,"w")
- fptr.write(data)
-
-def input_files():
- win = gtk.FileChooserDialog("Open ...", None,
- gtk.FILE_CHOOSER_ACTION_OPEN,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OPEN, gtk.RESPONSE_OK))
- win.set_default_response(gtk.RESPONSE_OK)
- win.set_select_multiple(True)
- # wave filter
- filter = gtk.FileFilter()
- filter.set_name("Waves")
- filter.add_pattern("*.wav")
- filter.add_pattern("*.WAV")
- win.add_filter(filter)
- # alternative filter
- filter = gtk.FileFilter()
- filter.set_name("All files")
- filter.add_pattern("*")
- win.add_filter(filter)
- # get files
- response = win.run()
- if (response == gtk.RESPONSE_OK):
- filelist = win.get_filenames()
- else:
- filelist = []
- win.destroy()
- while gtk.events_pending():
- gtk.main_iteration(False)
- return filelist
-
-def data_file():
- win = gtk.FileChooserDialog("Save As ...", None,
- gtk.FILE_CHOOSER_ACTION_SAVE,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OPEN, gtk.RESPONSE_OK))
- win.set_default_response(gtk.RESPONSE_OK)
- win.set_do_overwrite_confirmation(True);
- response = win.run()
- if (response == gtk.RESPONSE_OK):
- filename = win.get_filename()
- else:
- filename = ""
- win.destroy()
- return filename
-
-if (__name__ == "__main__"):
- main(sys.argv[1:])
-
DELETED src/fex.c
Index: src/fex.c
==================================================================
--- src/fex.c
+++ src/fex.c
@@ -1,56 +0,0 @@
-/**********************************************************************\
-* FEX - The Frequency Excursion Calculator
-*
-* Author: Jesse McClure, copyright 2013-2014
-* License: GPL3
-*
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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
-* .
-*
-\**********************************************************************/
-
-#include "fex.h"
-
-int die(const char *msg, ...) {
- va_list arg;
- fprintf(stderr,"Fatal Error: ");
- va_start(arg, msg);
- vfprintf(stderr,msg,arg);
- va_end(arg);
- exit(1);
-}
-
-int main(int argc, const char **argv) {
- const char *fname = configure(argc,argv);
- Wave *wav = create_wave(fname);
- FFT *fft = create_fft(wav);
- create_spectro(fft, fname);
- free_wave(&wav);
-
- xlib_event_loop();
- if (spect->fex > 0 && conf.long_out)
- fprintf(stdout,"%.3lf\t%.3lf\t%.3lf\n",
- spect->pex, spect->tex, spect->fex);
- else if (spect->fex > 0)
- fprintf(stdout,"%.3lf\n", spect->fex);
- else if (conf.long_out)
- fprintf(stdout,"NA\tNA\tNA\n");
- else
- fprintf(stdout,"NA\n");
-
- free_spectro();
- free_fft(&fft);
- deconfigure();
- return 0;
-}
ADDED src/fex.cpp
Index: src/fex.cpp
==================================================================
--- src/fex.cpp
+++ src/fex.cpp
@@ -0,0 +1,8 @@
+
+#include "spectrogram.hpp"
+
+int main(int argc, char *const *argv) {
+ Spectrogram spec(argc, argv);
+ spec.mainLoop();
+ return EXIT_SUCCESS;
+}
DELETED src/fex.h
Index: src/fex.h
==================================================================
--- src/fex.h
+++ src/fex.h
@@ -1,132 +0,0 @@
-/**********************************************************************\
-* FEX - The Frequency Excursion Calculator
-*
-* Author: Jesse McClure, copyright 2013-2014
-* License: GPL3
-*
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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
-* .
-*
-\**********************************************************************/
-
-#ifndef __FEX_H__
-#define __FEX_H__
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define RGBA_SPECT 0x00
-#define RGBA_THRESH 0x01
-#define RGBA_POINTS 0x02
-#define RGBA_LINES 0x03
-#define RGBA_ERASE1 0x04
-#define RGBA_ERASE2 0x05
-#define RGBA_CROP 0x06
-#define RGBA_LAST 0x07
-
-
-#define set_color(x,n) { \
- cairo_set_source_rgba(x, conf.col[n].r, conf.col[n].g, \
- conf.col[n].b, conf.col[n].a); \
- cairo_set_line_width(x, conf.col[n].w); \
-}
-
-typedef struct Wave {
- double *d;
- int samples;
- int rate;
-} Wave;
-
-typedef struct FFT {
- double **amp;
- double *time;
- double *freq;
- double max, min;
- int nfreq, ntime;
- char **mask;
-} FFT;
-
-typedef struct WindowFunction {
- const char *type;
- double a[4];
-} WindowFunction;
-
-typedef struct Spectro {
- const char *fname;
- char *name;
- unsigned char *a_spec, *a_thresh;
- cairo_surface_t *m_spec, *m_thresh, *s_points;
- FFT *fft;
- int fft_x, fft_y, fft_w, fft_h, fft_lo, fft_hi;
- double pex, tex, fex;
-} Spectro;
-
-typedef struct RGBA {
- double r, g, b, a, w;
-} RGBA;
-
-typedef struct Config {
- double thresh, spect_floor;
- double hipass, lopass;
- int scale;
- int winlen, hop, font_size;
- WindowFunction *win;
- RGBA col[RGBA_LAST];
- cairo_font_face_t *font, *bfont;
- char **help_cmd;
- Bool long_out, layers;
-} Config;
-
-/* main.c */
-extern int die(const char *, ...);
-/* config.c */
-extern const char *configure(int, const char **);
-extern int deconfigure();
-/* fft.c */
-extern FFT *create_fft(Wave *);
-extern int free_fft(FFT **);
-/* spectro.c */
-extern int create_spectro(FFT *, const char *);
-extern int free_spectro();
-/* wave.c */
-extern Wave *create_wave(const char *);
-extern int free_wave(Wave **);
-/* xlib.c */
-extern int create_xlib();
-extern int free_xlib();
-extern cairo_t *xlib_context();
-extern int xlib_event_loop();
-
-/* global data */
-Config conf;
-Spectro *spect;
-
-#endif /* __FEX_H__ */
-
DELETED src/fft.c
Index: src/fft.c
==================================================================
--- src/fft.c
+++ src/fft.c
@@ -1,121 +0,0 @@
-/**********************************************************************\
-* FEX - The Frequency Excursion Calculator
-*
-* Author: Jesse McClure, copyright 2013-2014
-* License: GPL3
-*
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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
-* .
-*
-\**********************************************************************/
-
-#include "fex.h"
-
-#define FFTW_FLAGS FFTW_FORWARD, FFTW_ESTIMATE
-FFT *create_fft(Wave *wav) {
- /* allocate memory */
- FFT *fft = (FFT *) calloc(1,sizeof(FFT));
- fft->nfreq = conf.winlen/2 + 1;
- fft->ntime = wav->samples/conf.hop;
- fft->amp = (double **) calloc(fft->ntime, sizeof(double *));
- fft->time = (double *) calloc(fft->ntime, sizeof(double));
- fft->freq = (double *) calloc(fft->nfreq, sizeof(double));
- fft->mask = (char **) calloc(fft->ntime, sizeof(char *));
- /* calculate step sizes and fill time/freq arrays */
- double nyquist = (double) wav->rate / 2000.0;
- double df = nyquist / fft->nfreq;
- double dt = (double)wav->samples / (double)(wav->rate * fft->ntime);
- double f, t;
- int i, j;
- for (i = 0, f = 0.0; i < fft->nfreq; i++, f += df) fft->freq[i] = f;
- for (i = 0, t = 0.0; i < fft->ntime; i++, t += dt) fft->time[i] = t;
- /* prepare fftw */
- fftw_complex *in, * out;
- fftw_plan p;
- in = (fftw_complex *)fftw_malloc(conf.winlen * sizeof(fftw_complex));
- out = (fftw_complex *)fftw_malloc(conf.winlen * sizeof(fftw_complex));
- p = fftw_plan_dft_1d(conf.winlen, in, out, FFTW_FLAGS);
- /* create windowing function */
- double window[conf.winlen];
- double *a = conf.win->a;
- double wl = conf.winlen;
- for (i = 0; i < conf.winlen; i++)
- window[i] = a[0] - a[1] * cos(2 * M_PI * (i / (wl - 1.0))) +
- a[2] * cos(2 * M_PI * (i / (wl - 1.0))) -
- a[3] * cos(2 * M_PI * (i / (wl - 1.0)));
- /* loop over signal */
- int pos;
- for (pos = 0, j = 0; pos < wav->samples; pos += conf.hop, j++) {
- fft->amp[j] = (double *) malloc(fft->nfreq * sizeof(double));
- fft->mask[j] = (char *) calloc(fft->nfreq, sizeof(char));
- /* copy windowed chunk to dat */
- for (i = 0; i < conf.winlen; i++) {
- if (pos + i < wav->samples) {
- in[i][0] = wav->d[pos + i] * window[i];
- in[i][1] = 0.0;
- }
- else {
- in[i][0] = 0.0;
- in[i][1] = 0.0;
- goto doublebreak;
- }
- }
- /* calculate fft & fill amp matrix */
- fftw_execute(p);
- for (i = 0; i < fft->nfreq; i++)
- fft->amp[j][i] = sqrt(out[i][0] * out[i][0] +
- out[i][1] * out[i][1]);
- }
- doublebreak:
- fftw_destroy_plan(p);
- fftw_free(out);
- fftw_free(in);
- /* fill and zero unused bins */
- for ( ; j < fft->ntime; j++) {
- fft->amp[j] = (double *) calloc(fft->nfreq, sizeof(double));
- fft->mask[j] = (char *) calloc(fft->nfreq, sizeof(char));
- }
- /* band pass filter */
- for (i = 0; i < fft->ntime; i++) {
- for (j = 0; j < fft->nfreq && fft->freq[j] < conf.hipass; j++)
- fft->amp[i][j] = 0;
- for (j = fft->nfreq - 1; fft->freq[j] > conf.lopass; j--)
- fft->amp[i][j] = 0;
- }
- /* normalize, log transform, and scale to dB */
- fft->max = fft->min = 0.0;
- for (i = 0; i < fft->ntime; i++) for (j = 0; j < fft->nfreq; j++)
- if (fft->amp[i][j] > fft->max) fft->max = fft->amp[i][j];
- for (i = 0; i < fft->ntime; i++) for (j = 0; j < fft->nfreq; j++) {
- fft->amp[i][j] = 10.0 * log10(fft->amp[i][j] / fft->max);
- if (fft->amp[i][j] < fft->min && fft->amp[i][j] > -900)
- fft->min = fft->amp[i][j];
- }
- fft->max = 0.0;
- return fft;
-}
-
-int free_fft(FFT **fftp) {
- FFT *fft = *fftp;
- int i;
- for (i = 0; i < fft->ntime; i++) {
- free(fft->amp[i]);
- free(fft->mask[i]);
- }
- //free(fft->amp);
- //free(fft->time);
- free(fft->freq);
- free(fft);
- return 0;
-}
ADDED src/fft.cpp
Index: src/fft.cpp
==================================================================
--- src/fft.cpp
+++ src/fft.cpp
@@ -0,0 +1,222 @@
+
+#include "fft.hpp"
+
+// TODO configurable window_function
+// * Maybe these should just be defined from the command line.
+static double window_function[4] = { 0.5, 0.5, 0, 0 }; // hanning
+/*
+Hamming 0.54 0.46 0.00 0.00
+Hanning 0.50 0.50 0.00 0.00
+Blackman 0.42659 0.49656 0.076849 0.00
+Nuttall 0.355768 0.487396 0.144232 0.012604
+BlackNutt 0.3635819 0.4891775 0.1365995 0.0106411
+BlackHarris 0.35875 0.48829 0.14128 0.01168
+
+*/
+
+Fft::Fft(int argc, char *const *argv) : Config(argc, argv) {
+ song.loadFromFile(fname);
+ ntime = song.getSampleCount() / conf.hop;
+ nfreq = conf.winlen / 2 + 0.5;
+ time = (double *) malloc(ntime * sizeof(double));
+ freq = (double *) malloc(nfreq * sizeof(double));
+ amp = (double *) malloc(nfreq * ntime * sizeof(double));
+ erase = (unsigned short int *) calloc(nfreq * ntime, sizeof(unsigned short int *));
+ /* fill time and freq arrays */
+ double nyquist = (double) song.getSampleRate() / 2000.0;
+ double dt = song.getDuration().asSeconds() / (double) ntime;
+ double df = nyquist / (double) nfreq;
+ int i;
+ time[0] = freq[0] = 0.0;
+ for (i = 1; i < ntime; ++i) time[i] = time[i-1] + dt;
+ for (i = 1; i < nfreq; ++i) freq[i] = freq[i-1] + df;
+ /* preare fftw */
+ fftw_complex *in, *out;
+ fftw_plan plan;
+ in = (fftw_complex *) fftw_malloc(conf.winlen * sizeof(fftw_complex));
+ out = (fftw_complex *) fftw_malloc(conf.winlen * sizeof(fftw_complex));
+ plan = fftw_plan_dft_1d(conf.winlen, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
+ /* windowing function */
+ double *window = (double *) malloc(conf.winlen * sizeof(double));
+ int t, f, pos;
+ for (t = 0; t < conf.winlen; ++t)
+ window[t] = window_function[0] -
+ window_function[1] * cos(2 * M_PI * t / (conf.winlen - 1.0)) +
+ window_function[2] * cos(4 * M_PI * t / (conf.winlen - 1.0)) -
+ window_function[3] * cos(6 * M_PI * t / (conf.winlen - 1.0));
+ /* loop over signal */
+ const sf::Int16 *data = song.getSamples();
+ for (pos = 0, t = 0; pos < song.getSampleCount() && t < ntime; pos += conf.hop, ++t) {
+ /* copy windowed chunk to in */
+ for (i = 0; i < conf.winlen; ++i) {
+ if (pos + i < song.getSampleCount())
+ in[i][0] = data[pos + i] * window[i];
+ else
+ in[i][0] = 0.0;
+ in[i][1] = 0.0;
+ }
+ /* calculate fft and fill amp */
+ fftw_execute(plan);
+ for (f = 0; f < nfreq; ++f)
+ amp[nfreq * t + f] = sqrt(out[f][0] * out[f][0] + out[f][1] * out[f][1]);
+ }
+ /* zero unused bins */
+ for (; t < ntime; ++t) for (f = 0; f < nfreq; ++f)
+ amp[nfreq * t + f] = 0;
+ /* drestroy and free data */
+ fftw_destroy_plan(plan);
+ fftw_free(out);
+ fftw_free(in);
+ free(window);
+ /* psuedo bandpass filter */
+ int f_zero, f_count = 0;
+ for (f = 0; freq[f] < conf.lopass; ++f);
+ f_zero = f;
+ for (; freq[f] <= conf.hipass; ++f) f_count++;
+ for (f = 0; f < f_count; ++f) freq[f] = freq[f+f_zero];
+ freq = (double *) realloc(freq, f_count * sizeof(double));
+ double *new_amp = (double *) malloc(ntime * f_count * sizeof(double));
+ for (t = 0; t < ntime; ++t) for (f = 0; f < f_count; ++f)
+ new_amp[f_count * t + f] = amp[nfreq * t + f + f_zero];
+ nfreq = f_count;
+ free(amp);
+ amp = new_amp;
+ /* normalize, log transform and scale to dB */
+ double max = 0.0;
+ for (t = 0; t < ntime; ++t) for (f = 0; f < nfreq; ++f)
+ if (amp[nfreq * t + f] > max) max = amp[nfreq * t + f];
+ for (t = 0; t < ntime; ++t) for (f = 0; f < nfreq; ++f)
+ amp[nfreq * t + f] = 10.0 * log10(amp[nfreq * t + f] / max);
+ /* prepare point and line overlays */
+ lines.setPrimitiveType(sf::LinesStrip);
+ lines.resize(ntime);
+ points.setPrimitiveType(sf::Quads);
+ points.resize(ntime * 4);
+ for (t = 0; t < ntime; ++t) {
+ lines[t].color = conf.linesFG;
+ points[4*t].texCoords = sf::Vector2f(0,0);
+ points[4*t+1].texCoords = sf::Vector2f(64,0);
+ points[4*t+2].texCoords = sf::Vector2f(64,64);
+ points[4*t+3].texCoords = sf::Vector2f(0,64);
+ }
+ t1 = f1 = 0;
+ t2 = ntime; f2 = nfreq;
+ /* prepare sprites */
+ makeSpectrogram();
+ makeThreshold();
+ makeOverlay();
+}
+
+void Fft::setCrop(sf::Vector2f a, sf::Vector2f b) {
+ if (a.x == -1) { /* reset */
+ t1 = f1 = 0;
+ t2 = ntime; f2 = nfreq;
+ }
+ else {
+ a.y *= -1;
+ b.y *= -1;
+ t1 = (a.x < b.x ? a.x : b.x);
+ t2 = (a.x < b.x ? b.x : a.x);
+ f1 = (a.y < b.y ? a.y : b.y);
+ f2 = (a.y < b.y ? b.y : a.y);
+ }
+ makeThreshold();
+ makeOverlay();
+}
+
+void Fft::makeSpectrogram() {
+ int t, f;
+ sf::Image img;
+ img.create(ntime, nfreq);
+ double dd;
+ unsigned short int di;
+ for (f = 0; f < nfreq; ++f) for (t = 0; t < ntime; ++t) {
+ dd = 255 * (1 + amp[nfreq * t + f] / conf.floor);
+ di = (dd > 255 ? 255 : (dd < 0 ? 0 : dd));
+ img.setPixel(t, f, sf::Color(255, 255, 255, di));
+ }
+ texSpec.loadFromImage(img);
+ texSpec.setSmooth(true);
+ spec = sf::Sprite(texSpec);
+ spec.setScale(1.0,-1.0);
+}
+
+void Fft::makeOverlay() {
+// * Change function name to "recalculate"?
+ int t, f, fmax, n;;
+ double max, pt, pf;
+ pathLength = timeLength = 0.0;
+ for (t = t1, n = 0; t < t2; ++t) {
+ fmax = -1;
+ max = std::numeric_limits::lowest(); // TODO: is this negative? Should it be?
+ for (f = f1; f < f2; ++f) {
+ if (erase[nfreq * t + f]) continue;
+ if (amp[nfreq * t + f] < max) continue;
+ max = amp[nfreq * t + (fmax=f)];
+ }
+ if (max < -1.0 * conf.threshold) continue;
+ if (n) { /* increment lengths for fex calculation for all but first point */
+ if (conf.log10) pathLength += hypot(log10(freq[fmax])-log10(pf),time[t]-pt);
+ else pathLength += hypot(freq[fmax]-pf,time[t]-pt);
+ timeLength += time[t]-pt;
+ }
+ pf = freq[fmax]; pt = time[t];
+ lines[n].position = sf::Vector2f(t + 0.5, - fmax - 0.5);
+ points[4*n].position = sf::Vector2f(t, - fmax);
+ points[4*n+1].position = sf::Vector2f(t + 1, - fmax);
+ points[4*n+2].position = sf::Vector2f(t + 1, - fmax - 1);
+ points[4*n+3].position = sf::Vector2f(t, - fmax - 1);
+ ++n;
+ }
+ for (; n < ntime; ++n) {
+ /* set remaining lines to last point and points to off screen */
+ lines[n].position = lines[n-1].position;
+ points[4*n].position = sf::Vector2f(-2,0);
+ points[4*n+1].position = sf::Vector2f(-2,0);
+ points[4*n+2].position = sf::Vector2f(-2,0);
+ points[4*n+3].position = sf::Vector2f(-2,0);
+ }
+}
+
+void Fft::makeThreshold() {
+ int t, f;
+ sf::Image img;
+ img.create(ntime, nfreq);
+ for (f = f1; f < f2; ++f) for (t = t1; t < t2; ++t)
+ img.setPixel(t, f, sf::Color(255, 255, 255, (amp[nfreq * t + f] > - conf.threshold ? 255 : 0)));
+ texThresh.loadFromImage(img);
+ texThresh.setSmooth(true);
+ thresh = sf::Sprite(texThresh);
+ thresh.setScale(1.0,-1.0);
+}
+
+void Fft::eraseShift() {
+ int t, f;
+ unsigned short int *a;
+ for (f = 0; f < nfreq; ++f) for (t = 0; t < ntime; ++t) {
+ a = &erase[nfreq * t + f];
+ if (*a) *a |= (*a<<1);
+ }
+}
+
+void Fft::eraseUndo() {
+ int t, f;
+ unsigned short int *a;
+ for (f = 0; f < nfreq; ++f) for (t = 0; t < ntime; ++t) {
+ a = &erase[nfreq * t + f];
+ if (!(*a & 0xFF)) *a = (*a>>1);
+ }
+}
+
+void Fft::erasePoint(int x, int y) {
+ if (x < ntime && y < nfreq) erase[nfreq * x + y] |= 0x01;
+}
+
+Fft::~Fft() {
+ if (amp) free(amp); amp = NULL;
+ if (time) free(time); time = NULL;
+ if (freq) free(freq); freq = NULL;
+ if (erase) free(erase); erase = NULL;
+ ntime = nfreq = 0;
+}
+
ADDED src/fft.hpp
Index: src/fft.hpp
==================================================================
--- src/fft.hpp
+++ src/fft.hpp
@@ -0,0 +1,37 @@
+
+#include "config.hpp"
+#include
+#include
+#include
+
+class Fft : public Config {
+ private:
+ sf::Texture texSpec, texThresh;
+ sf::VertexArray points, lines;
+ double *freq = NULL, *time = NULL, *amp = NULL;
+ unsigned short int *erase = NULL;
+ int t1, t2, f1, f2;
+
+ protected:
+ sf::Sprite spec, thresh;
+ sf::SoundBuffer song;
+ int ntime, nfreq;
+ double pathLength, timeLength;
+
+ void makeSpectrogram();
+ void makeThreshold();
+ void makeOverlay();
+ void setCrop(sf::Vector2f, sf::Vector2f);
+ sf::FloatRect getCrop() { return sf::FloatRect(t1, f1, t2 - t1, f2 - f1); }
+ sf::VertexArray const &getPoints() const { return points; };
+ sf::VertexArray const &getLines() const { return lines; };
+
+ void eraseShift();
+ void erasePoint(int, int);
+ void eraseUndo();
+
+ public:
+ Fft(int, char *const *);
+ ~Fft();
+};
+
DELETED src/icon.xpm
Index: src/icon.xpm
==================================================================
--- src/icon.xpm
+++ src/icon.xpm
@@ -1,261 +0,0 @@
-/* XPM */
-char *icon[] = {
-/* columns rows colors chars-per-pixel */
-"64 64 191 2 ",
-" c #010001",
-". c #000E0F",
-"X c #060904",
-"o c #01071D",
-"O c #1B0018",
-"+ c #001412",
-"@ c #310400",
-"# c #3B0016",
-"$ c #15002D",
-"% c #120023",
-"& c #05063B",
-"* c #160039",
-"= c #001236",
-"- c #000C25",
-"; c #29003A",
-": c #290039",
-"> c #3C003D",
-", c #32003B",
-"< c #2D0028",
-"1 c #002827",
-"2 c #003E2E",
-"3 c #002A37",
-"4 c #003D32",
-"5 c #5A0000",
-"6 c #46001E",
-"7 c #5E001C",
-"8 c #450008",
-"9 c #6D0000",
-"0 c #7B0000",
-"q c #70001B",
-"w c #660016",
-"e c #42002D",
-"r c #470022",
-"t c #55002C",
-"y c #5A0028",
-"u c #470037",
-"i c #4B003B",
-"p c #4B0034",
-"a c #560039",
-"s c #510036",
-"d c #67002A",
-"f c #73002D",
-"g c #750025",
-"h c #6A0031",
-"j c #630031",
-"k c #720033",
-"l c #004134",
-"z c #004B3A",
-"x c #004637",
-"c c #010042",
-"v c #110043",
-"b c #13004A",
-"n c #1C004A",
-"m c #00124A",
-"M c #0C0051",
-"N c #000B5E",
-"B c #050458",
-"V c #170055",
-"C c #001A5E",
-"Z c #00145A",
-"A c #250046",
-"S c #24004D",
-"D c #2B0048",
-"F c #3B0044",
-"G c #350044",
-"H c #00334C",
-"J c #002954",
-"K c #003E54",
-"L c #00325A",
-"P c #002A48",
-"I c #001364",
-"U c #001C6B",
-"Y c #001A65",
-"T c #001E73",
-"R c #001E7A",
-"E c #000C64",
-"W c #00286A",
-"Q c #003369",
-"! c #003D6C",
-"~ c #003B63",
-"^ c #002476",
-"/ c #00267D",
-"( c #002D7E",
-") c #002C75",
-"_ c #003376",
-"` c #00317C",
-"' c #003A79",
-"] c #460041",
-"[ c #004C42",
-"{ c #004547",
-"} c #005343",
-"| c #005945",
-" . c #005E4B",
-".. c #004B58",
-"X. c #005954",
-"o. c #00525E",
-"O. c #00624E",
-"+. c #00694C",
-"@. c #00724C",
-"#. c #006651",
-"$. c #006C55",
-"%. c #006B5B",
-"&. c #00625C",
-"*. c #007257",
-"=. c #00745C",
-"-. c #007A5E",
-";. c #007856",
-":. c #004963",
-">. c #004569",
-",. c #005E63",
-"<. c #00546C",
-"1. c #005D6C",
-"2. c #005361",
-"3. c #004474",
-"4. c #004B74",
-"5. c #004279",
-"6. c #004D79",
-"7. c #005472",
-"8. c #005579",
-"9. c #005C73",
-"0. c #006B66",
-"q. c #00646B",
-"w. c #006C6D",
-"e. c #006362",
-"r. c #007561",
-"t. c #007C63",
-"y. c #00746C",
-"u. c #007C6A",
-"i. c #006576",
-"p. c #006C76",
-"a. c #007372",
-"s. c #007C73",
-"d. c #00747C",
-"f. c #007D7B",
-"g. c #850000",
-"h. c #940000",
-"j. c #9D0000",
-"k. c #8A0012",
-"l. c #850019",
-"z. c #92001A",
-"x. c #A30000",
-"c. c #A50800",
-"v. c #B60002",
-"b. c #BA0000",
-"n. c #B9000E",
-"m. c #BC0E00",
-"M. c #A30011",
-"N. c #A80019",
-"B. c #B50018",
-"V. c #820024",
-"C. c #8C0029",
-"Z. c #8E0024",
-"A. c #930024",
-"S. c #9F0029",
-"D. c #970027",
-"F. c #A40023",
-"G. c #C40000",
-"H. c #CA000E",
-"J. c #D00000",
-"K. c #DB0000",
-"L. c #D6000D",
-"P. c #C50012",
-"I. c #CA0012",
-"U. c #E30000",
-"Y. c #E50009",
-"T. c #EC0000",
-"R. c #00825E",
-"E. c #008265",
-"W. c #008C65",
-"Q. c #00856A",
-"!. c #008A6D",
-"~. c #00926C",
-"^. c #00946A",
-"/. c #008476",
-"(. c #008D71",
-"). c #00847C",
-"_. c #009274",
-"`. c #009578",
-"'. c #00997A",
-"]. c #009872",
-"[. c #002F87",
-"{. c #003582",
-"}. c #003A82",
-"|. c #003589",
-" X c #004383",
-".X c #004885",
-"XX c #005885",
-"oX c #006983",
-"OX c #007D83",
-"+X c #008187",
-"@X c None",
-/* pixels */
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XO.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X2.e.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XQ <.-.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X$ . !.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xt S !.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X .@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xe D Q.-.@X@X@X%.@X@X@X@X@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XK <.Q.r.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xt z.i.~.$.Q.@X`.@X@X@X@X@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X` }.-.t.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xb & ' !.t.=.@XQ.@X@X@X@X@X@X@X@X@X@X",
-"@X@X@XE.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X< V.-.(.@X@XQ.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X; _ w E.!.@X#.$.@X@X@X@X@X@X@X@X@X@X",
-"@X@XC ( @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xa N.` ~.#.@X!.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X# r.D.4.(.| t.#.@X@X@X@X@X@X@X@X@X@X",
-"@X@XU ^ O.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XG U ^ !.-.@X!.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xe *.N 3.!.-.!.r.$.@X@X@X@X@X@X@X@X@X",
-"@X@Xj I.y.!.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xd J I.i.Q.@X!.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XE.$ 6 E._.'._._.@X@X@X@X@X@X@X@X@X",
-"@X@Xu A.9.Q.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XO %.f [.E.Q.(.r.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XO.{ i E._.`.Q.`.-.@X@X@X@X@X@X@X@X",
-"@X@X@XI L Q._.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XQ s.T f t.!.(.Q.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xi.A E.!._.t._.E.@X@X@X@X@X@X@X@X",
-"@X@X@X7.; y.'.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xr.(.0.Y.r._.`.!.E.@X@X@X@X@X@X@X@X@X@X@X@XU.@X@XQ.# ' (.!.@X!.!.@X@X@X@X@X@X@X@X",
-"@X@X@X<.f w.`.O.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xv.@X#.u.b ;.!.!.!.E.@X@X@X@X@X@X@X@X@X@X@X@XJ.@X@X=.P }.Q.!.*.r.!.@X@X@X@X@X@X@X@X",
-"@X@X@X=.A.3 _.r.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X(.` o.!.!.Q.Q.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X..n.u.(.$. .Q.@X@X@X@X@X@X@X@X",
-"@X@X@X-.a B Q.Q.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XE.q./ E.!.t.-.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X0.S.R.(.;.} (.@X@X@X@X@X@X@X@X",
-"@X@X@XE.` F t.!.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XE.> t.u.=.#.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XX.^ R.Q.r.@X_.@X@X@X@X@X@X@X@X",
-"@X@X@Xt.w.n.,.(.$.#.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XQ.L.q.t.$.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X} H .Xt.Q.@X`.=.@X@X@X@X@X@X@X",
-"@X@X@X@XQ.c ..(.t.$.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XO.b :.E.$.=.@X$.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XX.}.t.!.$.E.E.@X@X@X@X@X@X@X",
-"@X@X@X@Xt..X1 !.!.=.@X@X@X@X@X@X@X@X@X@X@X@XK.@X@X@X@X@X` o Q.%._.@XQ.@X@X@X@X@X@X@X@X@XT.@X@X@X@X@Xr.Z.r.!.!.@X_.@X@X@X@X@X@X@X",
-"@X@X@X@X=.Q.V ~._.=.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xt.F y.r.`.@X(.@X@X@X@X@X@X@X@X@XG.@X@X@X@X@XQ.F.r.(._.@X`.@X@X@X@X@X@X@X",
-"@X@X@X@X@XW.S ]._.$.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XE.n 0.u.!.E.E.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XQ.F =.!._.#._.@X@X@X@X@X@X@X",
-"@X@X@X@X@XR.C.'._.O.@X@XO.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X!.l.l (.Q.`.@Xt.@X@X@X@X@X@X@X@X@X@X@X@X@X@XQ.& ! !.(.=._.@X@X@X@X@X@X@X",
-"@X@X@X@X@X| u f.(.O.} @X=.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X%.= 4 Q.!.!.t.E.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X../ t._.=.(.@XE.@X@X@X@X@X",
-"@X@X@X@X@X@X* y.(.O.E.@Xt.E.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X5.~ E._.E.(.t.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xq.N.t._.=.(.@XE.@X@X@X@X@X",
-"@X@X@X@X@X@X[ Z ~.#.'.@XQ.!.@X@X@X@X@X@X@Xx.@X@X@X@X@X@X@XE.Y W._.=._.t.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xu.I.! _.=.(.@XE.@X@X@X@X@X",
-"@X@X@X@X@X@Xw.V ^.$.`.@XE.$.@X@X@X@X@X@X@XG.@X@X@X@X@X@X@XQ.: Q.Q.E.!.!.@X@X@X@X@X@X@Xv.@X@X@X@X@X@X@Xt.^ Q W.E.~.O.t.@X@X@X@X@X",
-"@X@X@X@X@X@X+XF./.r.'.@XE.@X#.@X@X@X@X@X@Xb.@X@X@X@X@X@X@X!.M.s.=.(.t.(.@Xt.@X@X@X@X@XT.@X@X@X@X@X@X@Xr.5.y Q.!._.$.E.@X@X@X@X@X",
-"@X@X@X@X@X@XW.D.XXr.`.t.E.@Xr.@X@X@X@X@X@X@X@X@X@X@X@X@X@X*.7 7.=.(.@Xt.@X!.@X@X@X@X@Xb.@X@X@X@X@X@X@X@XE.k y.(.!. . .@X@X@X@X@X",
-"@X@X@X@X@X@X@Xn $ t._.!.t.@XQ.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X' o =.(.@X#.@X_.@X@X@X@X@X@X@X@X@X@X@X@X@X@XW.h w.!.E.@X@X@X@X@X@X@X",
-"@X@X@X@X@X@X@XL V.q.!._.E.@XQ.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xy.p :.(.@X@XE._.E.@X@X@X@X@X@X@X@X@X@X@X@X@XE.< Z !.-.@X@X@X@X@X@X@X",
-"@X@X@X@X@X@X@Xi.] 9.Q._.Q.$.t.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XQ.S 4.(.@X=.!._.E.@X@X@X@X@X@X@X@X@X@X@X@X@Xt.3.M !.-.| @X@X@X@X@X@X",
-"@X@X@X@X@X@X@Xy.s L y.!.Q.Q.O.@X@X@X@X@XU.@X@X@X@X@X@X@X@X@XE.h O !.!.(._.(.Q.@X@X@X@X@X@X@X@X@X@X@X@X@X=.oXD.(.=.#.@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X-.O A ( !.Q.(.| @X@X@X@X@XU.@X@X@X@X@X@X@X@X@XE.r i E._._.Q.(.Q.@X@X@Xb.@X@X@X@X@X@X@X@X@X@XQ.B.d.%.-.@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@XXXB., E.!.!.| @X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xt.6.F Q.!.!.| !.Q.@X@X@Xb.@X@X@X@X@X@X@X@X@X@X@.G o.=.E.@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X).D.P.e._.Q.| @X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xa.q 8.Q.Q.@XQ.Q.@X@X@Xh.@X@X@X@X@X@X@X@X@X@X@X>.% t.!.@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@XR.V > ' !.Q. . @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X+.= ' E.!.@X!.#.@X@X@X9 @X@X@X@X@X@X@X@X@X@X@Xd.v R.!.@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X` N : E.t.O. @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X8.k.t._.@XQ.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xd.h Q._.=.@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@Xr.X.j r.E.*. @X@X0 @X@X@X@X@X@X@X@X@X@X@X@X`.S.W._.@XQ.@X@X@X9 @X@X@X@X@X@X@X@X@X@X@X@X!.d p.!.Q.@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X} u.V.0.Q.Q.X @X@Xj.@X@X@X@X@X@X@X@X@X@X@X@XE.E t.(.@X!.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XW.: 7.(.=.@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X(.k <.!.].+ @X@Xb.@X@X@X@X@X@X@X@X@X@X@X@X@X* oX(.@X!.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X= - !.#.@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@XQ.Z U !.'.z + @Xg.@X@X@X@X@X@X@X@X@X@X@X@X@X2 X!.@X_.@X@X@Xj.@X@X@X@X@X@X@X@X@X@X@X@X@X2.8 !.z @X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@Xr.3.k !.'.t.1 @X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xe.g Q.@X_.@X@X@XJ.@X@X@X@X@X@X@X@X@X@X@X@X@Xd.O _.@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@Xu.N.u.'.'.2 @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X).B.t.@X(.@X@X@Xg.@X@X@X@X@X@X@X@X@X@X@X@X@X_.S ^.@X @X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X!.k 7.'._.l @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X%.F 0.@X!.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XE.I Q.@X@X @X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X'.* J `.!.l @Xh.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XA >.@XQ.@X@X5 @X@X@X@X@X@X@X@X@X@X@X@X@X@X;.r OX@X @X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@XE.4.M /.!.2 @XK.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X1 U =.Q.@X@X9 @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@ X@X @X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@Xi.A.a.!.4 @Xx.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xi.A.r.Q.@X@X0 @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X:.y X @X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@Xu.H.C ~.2 @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X/.H.3.Q.@X@Xg.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X+XI.m @X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X$.Z B ^.l @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X*.b [.y.@X@X0 @X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xw.D W @X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X XF.).l 9 @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X( I.&.@X@X9 @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X+.V N. @X ",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X!.I.|.x 9 @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XQ.I.U o @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xz M. @X ",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X^.b S z 0 @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X(.{.i o h.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xa.Y @X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X_.4.Y.5.c.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X_.7.H.: l.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X/.H & . @X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@Xa.C.[.m.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X-.i B u @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X=.&.R X @X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@Xe.U P.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X+.` A.l.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X[ h @X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X$.<.Y.~ @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xy.n.k.@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xz I.X @X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XK R @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XW.T @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X..u + @X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X) @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@XE.U @X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@Xc V.@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X9.Y @X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X",
-"@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X@X"
-};
DELETED src/spectro.c
Index: src/spectro.c
==================================================================
--- src/spectro.c
+++ src/spectro.c
@@ -1,213 +0,0 @@
-/**********************************************************************\
-* FEX - The Frequency Excursion Calculator
-*
-* Author: Jesse McClure, copyright 2013-2014
-* License: GPL3
-*
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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
-* .
-*
-\**********************************************************************/
-
-#include "fex.h"
-
-#define set_color(x,n) { \
- cairo_set_source_rgba(x, conf.col[n].r, conf.col[n].g, \
- conf.col[n].b, conf.col[n].a); \
- cairo_set_line_width(x, conf.col[n].w); \
-}
-
-int create_spectro(FFT *fft, const char *fname) {
- spect = (Spectro *) calloc(1, sizeof(Spectro));
- /* names */
- spect->fname = fname;
- char *c = strrchr(spect->fname,'/');
- if (c && (++c)) spect->name = strdup(c);
- else spect->name = strdup(fname);
- if ( (c=strrchr(spect->name,'.')) ) *c = '\0';
- /* fft */
- spect->fft = fft;
- spect->fft_w = fft->ntime;
- spect->fft_h = fft->nfreq;
- /* set bounds */
- int i;
- for (i = 0; i < spect->fft->nfreq &&
- spect->fft->freq[i] < conf.hipass; i++);
- spect->fft_lo = spect->fft_y = i;
- for (i++; i < spect->fft->nfreq &&
- spect->fft->freq[i] < conf.lopass; i++);
- spect->fft_hi = i;
- spect->fft_h = i - spect->fft_y;
- /* cairo_surfaces */
- spectro_spec();
- spectro_thresh();
- spectro_points();
- /* xlib */
- create_xlib();
- return 0;
-}
-
-int free_spectro() {
- cairo_surface_destroy(spect->m_spec);
- cairo_surface_destroy(spect->m_thresh);
- cairo_surface_destroy(spect->s_points);
- free_xlib();
- free(spect->name);
- free(spect);
- return 0;
-}
-
-int img_draw() {
- cairo_surface_t *img;
- img = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, spect->fft_w*conf.scale, spect->fft_h*conf.scale * 4);
- cairo_t *ctx;
- ctx = cairo_create(img);
- cairo_scale(ctx,conf.scale,-4.0 * conf.scale);
- cairo_translate(ctx, 0, -1.0 * spect->fft_h);
- cairo_set_source_rgba(ctx,1.0,1.0,1.0,1.0);
- cairo_rectangle(ctx,0,0,spect->fft_w,spect->fft_h);
- cairo_fill(ctx);
- set_color(ctx,RGBA_SPECT);
- cairo_mask_surface(ctx,spect->m_spec,0,0);
- cairo_surface_write_to_png(img,"/tmp/img1.png");
- cairo_destroy(ctx);
- cairo_surface_destroy(img);
- img = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, spect->fft_w*conf.scale, spect->fft_h*conf.scale * 4);
- ctx = cairo_create(img);
- cairo_scale(ctx,conf.scale,-4.0 * conf.scale);
- cairo_translate(ctx, 0, -1.0 * spect->fft_h);
- cairo_set_source_rgba(ctx, conf.col[RGBA_THRESH].r, conf.col[RGBA_THRESH].g,
- conf.col[RGBA_THRESH].b, 0.8);
- cairo_mask_surface(ctx,spect->m_thresh,0,0);
- cairo_surface_write_to_png(img,"/tmp/img2.png");
- cairo_destroy(ctx);
- cairo_surface_destroy(img);
- img = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, spect->fft_w*conf.scale, spect->fft_h*conf.scale * 4);
- ctx = cairo_create(img);
- cairo_scale(ctx, 1.0, -4.0);
- cairo_translate(ctx, 0, -1.0 * spect->fft_h * conf.scale);
- cairo_set_source_surface(ctx,spect->s_points, 0, 0);
- cairo_paint_with_alpha(ctx, 0.8);
- cairo_surface_write_to_png(img,"/tmp/img3.png");
- cairo_destroy(ctx);
- cairo_surface_destroy(img);
- return 0;
-}
-
-int spectro_draw() {
- cairo_t *c = xlib_context();
- cairo_set_source_rgba(c,1.0,1.0,1.0,1.0);
- cairo_rectangle(c,0,0,spect->fft_w,spect->fft_h);
- cairo_fill(c);
- set_color(c,RGBA_SPECT);
- cairo_mask_surface(c,spect->m_spec,0,0);
- if (conf.layers) {
- set_color(c,RGBA_THRESH);
- cairo_mask_surface(c,spect->m_thresh,0,0);
- cairo_scale(c,1.0/conf.scale,1.0/conf.scale);
- cairo_set_source_surface(c,spect->s_points,0,0);
- cairo_paint(c);
- }
- cairo_destroy(c);
- return 0;
-}
-
-int spectro_points() {
- if (spect->s_points) cairo_surface_destroy(spect->s_points);
- spect->s_points = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- spect->fft_w * conf.scale, spect->fft_h * conf.scale);
- cairo_t *p = cairo_create(spect->s_points);
- cairo_t *l = cairo_create(spect->s_points);
- set_color(p,RGBA_POINTS);
- set_color(l,RGBA_LINES);
- int i, j, f;
- double lt = spect->fft->time[0], lf = spect->fft->freq[0];
- spect->pex = 0.0;
- spect->tex = 0.0;
- /* loop through time bins */
- for (i = spect->fft_x; i < spect->fft_w + spect->fft_x; i++) {
- /* find maximum (non masked) frequency in time bin */
- for (f = 0, j = spect->fft_y; j < spect->fft_h+spect->fft_y; j++) {
- if (spect->fft->mask[i][j]) continue;
- if (spect->fft->amp[i][j] > spect->fft->amp[i][f] || !f)
- f = j;
- }
- /* add points and do calculations if f is above threshold */
- if (f > 0 && spect->fft->amp[i][f] > conf.thresh) {
- if (lt != spect->fft->time[0]) {
- spect->pex += sqrt(
- (spect->fft->freq[f] - lf) * (spect->fft->freq[f] - lf) +
- (spect->fft->time[i] - lt) * (spect->fft->time[i] - lt) );
- spect->tex += spect->fft->time[i] - lt;
- }
- lt = spect->fft->time[i];
- lf = spect->fft->freq[f];
- cairo_line_to(l,
- (i - spect->fft_x) * conf.scale + conf.scale / 2,
- (f - spect->fft_y) * conf.scale + conf.scale / 2);
- cairo_new_sub_path(p);
- cairo_arc(p,
- (i - spect->fft_x) * conf.scale + conf.scale / 2,
- (f - spect->fft_y) * conf.scale + conf.scale / 2,
- conf.col[RGBA_POINTS].w,0,2*M_PI);
- }
- spect->fex = spect->pex / spect->tex;
- }
- cairo_fill(p);
- cairo_stroke(l);
- cairo_destroy(p);
- cairo_destroy(l);
- return 0;
-}
-
-int spectro_spec() {
- if (spect->m_spec) cairo_surface_destroy(spect->m_spec);
- if (spect->a_spec) free(spect->a_spec);
- int i, j, stride;
- stride = cairo_format_stride_for_width(CAIRO_FORMAT_A8, spect->fft_w);
- spect->a_spec = (unsigned char *) calloc(stride,spect->fft_h);
- unsigned char *a = NULL;
- for (j = spect->fft_y; j < spect->fft_h + spect->fft_y; j++) {
- a = spect->a_spec + (j - spect->fft_y) * stride;
- for (i = spect->fft_x; i < spect->fft_w + spect->fft_x; i++, a++) {
- *a = 255 - (unsigned char) 255 * (
- ( (spect->fft->amp[i][j] - conf.spect_floor) >= 0) ?
- spect->fft->amp[i][j] / conf.spect_floor : 1);
- }
- }
- spect->m_spec = cairo_image_surface_create_for_data(spect->a_spec,
- CAIRO_FORMAT_A8, spect->fft_w, spect->fft_h, stride);
- return 0;
-}
-
-int spectro_thresh() {
- if (spect->m_thresh) cairo_surface_destroy(spect->m_thresh);
- if (spect->a_thresh) free(spect->a_thresh);
- int i, j, stride;
- stride = cairo_format_stride_for_width(CAIRO_FORMAT_A8, spect->fft_w);
- spect->a_thresh = (unsigned char *) calloc(stride, spect->fft_h);
- unsigned char *a = NULL;
- for (j = spect->fft_y; j < spect->fft_h + spect->fft_y; j++) {
- a = spect->a_thresh + (j - spect->fft_y) * stride;
- for (i = spect->fft_x; i < spect->fft_w + spect->fft_x; i++, a++) {
- if (spect->fft->mask[i][j]) *a = 0;
- else if (spect->fft->amp[i][j] > conf.thresh) *a = 255;
- else *a = 0;
- }
- }
- spect->m_thresh = cairo_image_surface_create_for_data(spect->a_thresh,
- CAIRO_FORMAT_A8, spect->fft_w, spect->fft_h, stride);
- return 0;
-}
-
ADDED src/spectrogram.cpp
Index: src/spectrogram.cpp
==================================================================
--- src/spectrogram.cpp
+++ src/spectrogram.cpp
@@ -0,0 +1,265 @@
+
+#include "spectrogram.hpp"
+#include
+
+Spectrogram::Spectrogram(int argc, char *const *argv) : Fft(argc, argv) {
+// if (getenv("FEX_FULLSCREEN"))
+ win.create(sf::VideoMode::getDesktopMode(), "Fex", sf::Style::Fullscreen);
+// else
+// win.create(sf::VideoMode(640,480), "Fex");
+ aspect = (ntime * win.getSize().y * conf.hop) / (float) (nfreq * win.getSize().x * conf.winlen);
+ view.reset(sf::FloatRect(0, -nfreq * (1 + aspect)/2.0, ntime, nfreq * aspect));
+ win.setView(view);
+ spec.setColor(conf.specFG);
+ sf::RenderTexture render_ball;
+ render_ball.setSmooth(true);
+ render_ball.create(64,64);
+ sf::CircleShape dot(32);
+ dot.setFillColor(conf.pointBG);
+ dot.setOutlineColor(conf.pointFG);
+ dot.setOutlineThickness(-8);
+ render_ball.draw(dot);
+ ball = render_ball.getTexture();
+ back.setSize(sf::Vector2f(ntime,-nfreq));
+ back.setFillColor(conf.specBG);
+ mouse.x = ntime / 2; mouse.y = - nfreq / 2;
+ crop1 = sf::Vector2f(-1, -1);
+ eraser.setSize(sf::Vector2f(4, 18));
+ eraser.setFillColor(sf::Color(255,200,0,200));
+ eraser.setPosition(0, 0);
+ eraser.setOrigin(2, 10);
+}
+
+Spectrogram::~Spectrogram() { }
+
+int Spectrogram::mainLoop() {
+ sf::Event ev;
+ while (win.isOpen() && win.waitEvent(ev)) {
+ evHandler(ev);
+ while (win.pollEvent(ev)) evHandler(ev);
+ drawMain();
+ win.display();
+ char out[256];
+ snprintf(out,255,"%s - (%0.3fs, %0.3fKHz) FE: %lf ",
+ name,
+ song.getDuration().asSeconds() * mouse.x / ntime,
+ conf.lopass - (conf.hipass - conf.lopass) * mouse.y / nfreq,
+ 1234.5
+ );
+ win.setTitle(sf::String(out));
+ }
+ printf("%lf\t%lf\t%lf\n", pathLength, timeLength, pathLength / timeLength);
+ return 0;
+}
+
+void Spectrogram::evHandler(sf::Event ev) {
+ switch (ev.type) {
+ case sf::Event::Closed: evClose(ev); break;
+ case sf::Event::KeyPressed: evKeyPress(ev); break;
+ case sf::Event::KeyReleased: evKeyRelease(ev); break;
+ case sf::Event::MouseMoved: evMouseMove(ev); break;
+ case sf::Event::MouseButtonPressed: evMouseButton(ev); break;
+ case sf::Event::MouseWheelScrolled: evMouseWheel(ev); break;
+ case sf::Event::Resized: evResize(ev); break;
+ }
+}
+
+void Spectrogram::drawMain() {
+ win.clear(conf.winBG);
+ win.draw(back);
+ win.draw(spec);
+ thresh.setColor(conf.threshFG);
+ if (toggle.overlay) {
+ win.draw(thresh);
+ win.draw(getPoints(), &ball);
+ win.draw(getLines());
+ if (toggle.cursor) {
+ if (crop1.x > 0) drawCursor(crop1.x, crop1.y);
+ drawCursor(mouse.x, mouse.y);
+ }
+ if (toggle.eraser)
+ win.draw(eraser);
+ }
+}
+
+void Spectrogram::drawCursor(float x, float y) {
+ sf::RectangleShape lineV(sf::Vector2f(1, nfreq));
+ lineV.setFillColor(conf.cursorFG);
+ lineV.setPosition(view.getViewport().left + x, -nfreq);
+ win.draw(lineV);
+ sf::RectangleShape lineH(sf::Vector2f(ntime, 1));
+ lineH.setFillColor(conf.cursorFG);
+ lineH.setPosition(0,view.getViewport().top + y);
+ win.draw(lineH);
+}
+
+void Spectrogram::listen(float speed) {
+ sf::Sound snd(song);
+ snd.play();
+ snd.setPitch(speed);
+ while(snd.getStatus() == 2) {
+ sf::RectangleShape line(sf::Vector2f(10, nfreq));
+ line.setFillColor(sf::Color(0,255,0,120));
+ line.setPosition(ntime * (snd.getPlayingOffset() / song.getDuration()), -nfreq);
+ drawMain();
+ win.draw(line);
+ win.display();
+ }
+}
+
+void Spectrogram::evClose(sf::Event ev) {
+}
+
+void Spectrogram::evKeyPress(sf::Event ev) {
+ if (ev.key.code == sf::Keyboard::LShift) toggle.cursor = !toggle.cursor;
+ if (ev.key.code == sf::Keyboard::RShift) toggle.cursor = !toggle.cursor;
+ if (ev.key.code == sf::Keyboard::LAlt) toggle.eraser = !toggle.eraser;
+ if (ev.key.code == sf::Keyboard::RAlt) toggle.eraser = !toggle.eraser;
+ if (ev.key.control) switch (ev.key.code) {
+ case sf::Keyboard::Space: toggle.overlay = !toggle.overlay; break;
+ case sf::Keyboard::Right: conf.floor -= 0.25; makeSpectrogram(); break;
+ case sf::Keyboard::Left: conf.floor += 0.25; makeSpectrogram(); break;
+ case sf::Keyboard::Up: conf.threshold -= 0.25; makeOverlay(); break;
+ case sf::Keyboard::Down: conf.threshold += 0.25; makeOverlay(); break;
+ case sf::Keyboard::Q: win.close(); break;
+ case sf::Keyboard::Num1: listen(1.0); break;
+ case sf::Keyboard::Num2: listen(0.5); break;
+ case sf::Keyboard::Num3: listen(0.333); break;
+ case sf::Keyboard::Num4: listen(0.25); break;
+ case sf::Keyboard::Num5: listen(0.2); break;
+ }
+ else if (ev.key.alt) switch (ev.key.code) {
+ case sf::Keyboard::Space: toggle.eraser = !toggle.eraser; break;
+ }
+ if (ev.key.shift) switch (ev.key.code) {
+ case sf::Keyboard::Space: toggle.cursor = !toggle.cursor; break;
+ }
+}
+
+void Spectrogram::evKeyRelease(sf::Event ev) {
+ if (ev.key.code == sf::Keyboard::LShift) toggle.cursor = !toggle.cursor;
+ if (ev.key.code == sf::Keyboard::RShift) toggle.cursor = !toggle.cursor;
+ if (ev.key.code == sf::Keyboard::LAlt) toggle.eraser = !toggle.eraser;
+ if (ev.key.code == sf::Keyboard::RAlt) toggle.eraser = !toggle.eraser;
+}
+
+void Spectrogram::evResize(sf::Event ev) {
+ aspect = (ntime * win.getSize().y * conf.hop) / (float) (nfreq * win.getSize().x * conf.winlen);
+}
+
+void Spectrogram::evMouseMove(sf::Event ev) {
+ sf::Vector2f prev = mouse;
+ mouse = win.mapPixelToCoords(sf::Vector2i(ev.mouseMove.x,ev.mouseMove.y));
+ if (toggle.overlay && toggle.cursor) {
+ //
+ }
+ else if (toggle.overlay && toggle.eraser) {
+ if (sf::Mouse::isButtonPressed(sf::Mouse::Left) && toggle.eraser) erase();
+ }
+ else {
+ if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) {
+ view.setSize(view.getSize().x + prev.x - mouse.x, view.getSize().y + prev.y - mouse.y);
+ view.move((prev.x - mouse.x)/2.0, (prev.y - mouse.y)/2.0);
+ }
+ if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
+ view.move(prev.x - mouse.x, prev.y - mouse.y);
+ }
+ win.setView(view);
+ }
+ mouse = win.mapPixelToCoords(sf::Vector2i(ev.mouseMove.x,ev.mouseMove.y));
+ float in_bounds = 1.0;
+ if (mouse.x < 0) in_bounds = mouse.x = 0.0;
+ else if (mouse.x > ntime) in_bounds = mouse.x = ntime;
+ if (mouse.y > 0) in_bounds = mouse.y = 0.0;
+ else if (mouse.y < - nfreq) in_bounds = mouse.y = - nfreq;
+ if (in_bounds == 1.0) eraser.setPosition(mouse);
+ else eraser.setPosition(sf::Vector2f(-ntime,nfreq));
+}
+
+void Spectrogram::erase() {
+ sf::FloatRect rect = eraser.getGlobalBounds();
+ sf::Transform t = eraser.getInverseTransform();
+ sf::Vector2f point;
+ int i, j;
+ for (i = rect.left - 0.5; i < rect.left + rect.width + 1; ++i) {
+ for (j = rect.top - 0.5; j < rect.top + rect.height + 1; ++j) {
+ point = t.transformPoint(i + 0.5, j - 0.5);
+ if (point.x > -0.25 && point.x < 4.25 && point.y > -0.25 && point.y < 18.25)
+ erasePoint(i, -j);
+ }
+ }
+ makeOverlay();
+}
+
+void Spectrogram::evMouseButton(sf::Event ev) {
+ sf::FloatRect rect;
+ if (toggle.overlay && toggle.cursor) switch (ev.mouseButton.button) {
+ /* set a crop window: requires 2 presses */
+ case sf::Mouse::Button::Left:
+ if (crop1.x < 0) crop1 = mouse;
+ else { setCrop(crop1, mouse); crop1.x = -1; }
+ break;
+ /* zoom to fit crop area to window */
+ case sf::Mouse::Button::Middle:
+ rect = getCrop();
+ rect.top -= rect.height * (1 + aspect) / 2.0;
+ rect.height *= aspect;
+ view.reset(rect);
+ win.setView(view);
+ break;
+ /* reset crop to full song */
+ case sf::Mouse::Button::Right:
+ crop1.x = -1;
+ setCrop(crop1, mouse);
+ break;
+ }
+ else if (toggle.overlay && toggle.eraser) switch (ev.mouseButton.button) {
+ case sf::Mouse::Button::Left: if (toggle.eraser) erase(); break;
+ }
+ else switch (ev.mouseButton.button) {
+ /* NOTE: left and right are handled in evMouseMove */
+ /* zoom to fit song to window */
+ case sf::Mouse::Button::Middle:
+ view.reset(sf::FloatRect(0, -nfreq * (1 + aspect)/2.0, ntime, nfreq * aspect));
+ win.setView(view);
+ break;
+ }
+}
+
+void Spectrogram::evMouseWheel(sf::Event ev) {
+ bool vert = (ev.mouseWheelScroll.wheel == 0);
+ float dx = ev.mouseWheelScroll.delta;
+ if (toggle.overlay && toggle.cursor) {
+ // TODO: anything here? Probably not.
+ }
+ if (toggle.overlay && toggle.eraser) {
+ /* rotate */
+ if (!vert) { eraser.rotate(-dx); return; }
+ /* or scale */
+ sf::Vector2f scale = eraser.getScale();
+ float r = eraser.getRotation();
+ if (r < 30 || r > 330 || (r > 150 && r < 210) )
+ scale.y += 0.008 * dx;
+ else if ( (r > 60 && r < 120) || (r > 240 && r < 300) )
+ scale.x += 0.008 * dx;
+ else {
+ scale.x += 0.004 * dx;
+ scale.y += 0.004 * dx;
+ }
+ if (scale.x < 0.5) scale.x = 0.5;
+ else if (scale.x > 5.0) scale.x = 5.0;
+ if (scale.y < 0.5) scale.y = 0.5;
+ else if (scale.y > 5.0) scale.y = 5.0;
+ eraser.setScale(scale);
+ }
+ /* No modifier wheel movements are for zooming: */
+ else if (vert) {
+ // TODO: make 0.0075 step size customizable?
+ float vx = view.getSize().x / ntime, vy = view.getSize().y / nfreq;
+ if (dx < 0 && vx > 1.20 && vy > 1.20) return;
+ if (dx > 0 && vx < 0.01 && vy > 0.01) return;
+ view.zoom(1.0 - 0.0075 * dx);
+ win.setView(view);
+ }
+}
+
ADDED src/spectrogram.hpp
Index: src/spectrogram.hpp
==================================================================
--- src/spectrogram.hpp
+++ src/spectrogram.hpp
@@ -0,0 +1,39 @@
+
+#include "fft.hpp"
+#include
+#include
+#include
+
+class Spectrogram : public Fft {
+ private:
+ sf::RenderWindow win;
+ sf::View view;
+ sf::Vector2f mouse, crop1;
+ sf::RectangleShape back;
+ sf::Texture ball;
+ sf::RectangleShape eraser;
+ bool mod_ctrl, mod_shift, mod_alt;
+ float aspect;
+
+ void drawMain();
+ void drawCursor(float, float);
+ void drawHud();
+ void erase();
+
+ void checkModKeys();
+ void evHandler(sf::Event);
+ void evClose(sf::Event);
+ void evKeyPress(sf::Event);
+ void evKeyRelease(sf::Event);
+ void evMouseButton(sf::Event);
+ void evMouseMove(sf::Event);
+ void evMouseWheel(sf::Event);
+ void evResize(sf::Event);
+ protected:
+ void listen(float=1.0);
+ public:
+ int mainLoop();
+ Spectrogram(int, char *const *);
+ ~Spectrogram();
+};
+
DELETED src/wave.c
Index: src/wave.c
==================================================================
--- src/wave.c
+++ src/wave.c
@@ -1,65 +0,0 @@
-/**********************************************************************\
-* FEX - The Frequency Excursion Calculator
-*
-* Author: Jesse McClure, copyright 2013-2014
-* License: GPL3
-*
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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
-* .
-*
-\**********************************************************************/
-
-#include "fex.h"
-
-
-Wave *create_wave(const char *fname) {
- Wave *w = (Wave *) calloc(1,sizeof(Wave));
- SF_INFO *winfo;
- SNDFILE *wfile = NULL;
- winfo = (SF_INFO *) calloc(1, sizeof(SF_INFO));
- wfile = sf_open(fname, SFM_READ, winfo);
- w->samples = winfo->frames;
- w->rate = winfo->samplerate;
- w->d = (double *) calloc(w->samples+1, sizeof(double));
- sf_count_t n;
- if (winfo->channels == 1) {
- n = sf_readf_double(wfile, w->d, w->samples);
- }
- else { /* average over channels */
- double *multi = calloc((w->samples+1)*winfo->channels, sizeof(double));
- n = sf_readf_double(wfile, multi, w->samples * winfo->channels);
- int i, nframe;
- double mix;
- for (nframe = 0; nframe < w->samples; nframe++) {
- mix = 0.0;
- for (i = 0; i < winfo->channels; i++)
- mix += multi[nframe * winfo->channels + i];
- w->d[nframe] = mix / winfo->channels;
- }
- free(multi);
- }
- if (n != w->samples)
- fprintf(stderr,"Error reading \"%s\"\n\t"
- "\t%d samples read of\n\t%d reported size\n",
- fname, (int) n, w->samples);
- sf_close(wfile);
- return w;
-}
-
-int free_wave(Wave **wp) {
- Wave *w = *wp;
- free(w->d);
- free(w);
- return 0;
-}
DELETED src/xlib.c
Index: src/xlib.c
==================================================================
--- src/xlib.c
+++ src/xlib.c
@@ -1,169 +0,0 @@
-/**********************************************************************\
-* FEX - The Frequency Excursion Calculator
-*
-* Author: Jesse McClure, copyright 2013-2014
-* License: GPL3
-*
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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
-* .
-*
-\**********************************************************************/
-
-#include "fex.h"
-
-#define MODE_NULL 0x00
-#define MODE_ERASE 0x01
-#define MODE_CROP 0x02
-
-#define EVENT_MASK ExposureMask | ButtonPressMask | KeyPressMask | \
- StructureNotifyMask
-
-/* spectro.c */
-extern int img_draw();
-extern int spectro_draw();
-extern int spectro_points();
-extern int spectro_spec();
-extern int spectro_thresh();
-
-static void buttonpress(XEvent *);
-static void clientmessage(XEvent *);
-static void configurenotify(XEvent *);
-static void expose(XEvent *);
-static void keypress(XEvent *);
-static void motionnotify(XEvent *);
-
-static int crop(int, int);
-static int erase(int, int);
-static int eraser_cursor(int, int);
-static int move(double, double);
-static int play(float);
-static int pt_line(double, double);
-static int screenshot();
-static int sp_floor(double);
-static int threshold(double);
-static int zoom(double);
-
-static Display *dpy;
-static int scr;
-static unsigned int ww, wh, mx, my;
-static GC gc;
-static Window root, win;
-static Pixmap buf; //, ibuf, sbuf;
-static Atom WM_DELETE_WINDOW;
-//static cairo_t *ictx, *sctx;
-static Bool running = True;
-static double xsc = 1.0, ysc = 1.0, xoff = 0.0, yoff = 0.0;
-static int mode = 0, ew = 31, eh = 64;
-static char e_col[2][8];
-static void (*handler[LASTEvent])(XEvent *) = {
- [ButtonPress] = buttonpress,
- [ClientMessage] = clientmessage,
- [ConfigureNotify] = configurenotify,
- [Expose] = expose,
- [KeyPress] = keypress,
- [MotionNotify] = motionnotify,
-};
-
-#include "xlib_toolwin.c"
-#include "xlib_actions.c"
-#include "xlib_events.c"
-
-int create_xlib() {
- if (!setlocale(LC_CTYPE,"")) die("unable to set locale");
- if (!XSupportsLocale()) die("unsupported locale");
- if (!XSetLocaleModifiers("")) die("unable to set locale modifiers");
- if ( !(dpy=XOpenDisplay(0x0)) ) die("unable to open display");
- scr = DefaultScreen(dpy);
- root = DefaultRootWindow(dpy);
- gc = DefaultGC(dpy,scr);
- ww = DisplayWidth(dpy,scr);
- wh = DisplayHeight(dpy,scr);
- /* create windows */
- buf = XCreatePixmap(dpy, root, ww, wh, DefaultDepth(dpy,scr));
- win = XCreateSimpleWindow(dpy,root,0,0,(ww*=0.85),(wh*=0.85),0,0, 0);
- XSelectInput(dpy, win, EVENT_MASK | SubstructureRedirectMask |
- PointerMotionMask);
- XStoreName(dpy, win, "FEX: Frequency Excursion Calculator");
- XClassHint *hint = XAllocClassHint();
- hint->res_name = "FEX";
- hint->res_class = "FEX";
- XSetClassHint(dpy, win, hint);
- WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
- XSetWMProtocols(dpy, win, &WM_DELETE_WINDOW, 1);
- #include "icon.xpm"
- Pixmap image, shape;
- XWMHints *hints;
- XpmCreatePixmapFromData(dpy, win, icon, &image, &shape, NULL);
- hints = XAllocWMHints();
- hints->flags = IconPixmapHint | IconMaskHint;
- hints->icon_pixmap = image;
- hints->icon_mask = shape;
- XSetWMHints(dpy, win, hints);
- XFree(hints);
- /* set up eraser / crop colors */
- sprintf(e_col[0],"#%02hhX%02hhX%02hhX",
- (unsigned char) conf.col[RGBA_ERASE1].r * 255,
- (unsigned char) conf.col[RGBA_ERASE1].g * 255,
- (unsigned char) conf.col[RGBA_ERASE1].b * 255);
- sprintf(e_col[1],"#%02hhX%02hhX%02hhX",
- (unsigned char) conf.col[RGBA_ERASE2].r * 255,
- (unsigned char) conf.col[RGBA_ERASE2].g * 255,
- (unsigned char) conf.col[RGBA_ERASE2].b * 255);
- char c_col[8];
- XColor c;
- sprintf(c_col,"#%02hhX%02hhX%02hhX",
- (unsigned char) conf.col[RGBA_CROP].r * 255,
- (unsigned char) conf.col[RGBA_CROP].g * 255,
- (unsigned char) conf.col[RGBA_CROP].b * 255);
- XAllocNamedColor(dpy,DefaultColormap(dpy,scr),c_col,&c,&c);
- XSetLineAttributes(dpy, gc, conf.col[RGBA_CROP].w, LineSolid,
- CapButt, JoinRound);
- XSetForeground(dpy, gc, c.pixel);
- toolwin_create();
- spectro_draw();
- XSetWindowBackgroundPixmap(dpy, win, buf);
- return 0;
-}
-
-int free_xlib() {
- XUndefineCursor(dpy, win);
- toolwin_destroy();
- XFlush(dpy);
- XCloseDisplay(dpy);
- return 0;
-}
-
-cairo_t *xlib_context() {
- cairo_surface_t *t = cairo_xlib_surface_create(dpy, buf,
- DefaultVisual(dpy,scr), ww, wh);
- cairo_t *c = cairo_create(t);
- cairo_surface_destroy(t);
- cairo_translate(c,0,wh * ysc);
- cairo_scale(c, (ww * xsc)/ (float) spect->fft_w,
- -1.0 * (wh * ysc) / (float) spect->fft_h);
- cairo_translate(c, xoff, yoff);
- return c;
-}
-
-int xlib_event_loop() {
- XMapWindow(dpy, win);
- XMapWindow(dpy, info->win);
- XEvent ev;
- while (running && !XNextEvent(dpy,&ev))
- if (ev.type < LASTEvent && handler[ev.type])
- handler[ev.type](&ev);
- return 0;
-}
-
-
DELETED src/xlib_actions.c
Index: src/xlib_actions.c
==================================================================
--- src/xlib_actions.c
+++ src/xlib_actions.c
@@ -1,288 +0,0 @@
-/**********************************************************************\
-* FEX - The Frequency Excursion Calculator
-*
-* Author: Jesse McClure, copyright 2013-2014
-* License: GPL3
-*
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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
-* .
-*
-\**********************************************************************/
-
-
-int crop(int x, int y) {
- int x1 = x, y1 = y, x2, y2, t;
- XCopyArea(dpy, win, buf, gc, 0, 0, ww, wh, 0, 0);
- XEvent e;
- XGrabPointer(dpy, win, True, PointerMotionMask | ButtonPressMask,
- GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
- while (e.type != ButtonPress) {
- XMaskEvent(dpy, PointerMotionMask | ButtonPressMask |
- KeyPressMask, &e);
- if (e.type == KeyPress) break;
- x2 = e.xmotion.x;
- y2 = e.xmotion.y;
- if (x2 > ww) x2 = ww;
- if (y2 > wh) y2 = wh;
- mx = spect->fft_w * x2/(ww*xsc) - 1.0 * xoff + spect->fft_x;
- my = spect->fft_h * (1.0-y2/(wh*ysc)) - 1.0 * yoff + spect->fft_y;
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- XDrawLine(dpy, win, gc, x2, 0, x2, wh);
- XDrawLine(dpy, win, gc, 0, y2, ww, y2);
- info_draw(info);
- if (e.type == ButtonPress) break;
- while(XCheckMaskEvent(dpy, PointerMotionMask, &e));
- }
- XUngrabPointer(dpy, CurrentTime);
- if (x2 < x1) { t = x1; x1 = x2; x2 = t; }
- if (y2 > y1) { t = y1; y1 = y2; y2 = t; }
- mode = MODE_NULL;
- info_draw(info);
- if (e.type == KeyPress) {
- spectro_draw();
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- return 0;
- }
- int oldy = spect->fft_y;
- spect->fft_x = spect->fft_w * x1/(ww*xsc) - 1.0*xoff + spect->fft_x;
- spect->fft_y = spect->fft_h*(1.0-y1/(wh*ysc))-1.0*yoff+spect->fft_y;
- spect->fft_w = spect->fft_w * x2/(ww*xsc) - 1.0*xoff - spect->fft_x;
- spect->fft_h = spect->fft_h*(1.0-y2/(wh*ysc))-1.0*yoff +
- oldy - spect->fft_y;
- spectro_spec();
- spectro_thresh();
- spectro_points();
- spectro_draw();
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- return 0;
-}
-
-int erase(int x, int y) {
- int x1, x2, y1, y2, i, j;
- double sew = spect->fft_w * ew / (ww * xsc);
- double seh = spect->fft_h * eh / (wh * ysc);
- if (x == -1 && y == -1) { /* UNDO LAST ERASE */
- for (i = 0; i < spect->fft->ntime; i++)
- for (j = 0; j < spect->fft->nfreq; j++)
- spect->fft->mask[i][j] = ( (spect->fft->mask[i][j] >> 7) ?
- (spect->fft->mask[i][j] >> 1) | 0x40 :
- (spect->fft->mask[i][j] >> 1) );
- spectro_points();
- spectro_draw();
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- return 0;
- } /* ELSE START NEW ERASE */
- XEvent e;
- XGrabPointer(dpy, win, True, PointerMotionMask | ButtonReleaseMask,
- GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
- /* rotate bits for 7 undo levels */
- for (i = 0; i < spect->fft->ntime; i++)
- for (j = 0; j < spect->fft->nfreq; j++)
- spect->fft->mask[i][j] = ( (spect->fft->mask[i][j] >> 7) ?
- (spect->fft->mask[i][j] << 1) | 0x40 :
- (spect->fft->mask[i][j] << 1) );
- while (e.type != ButtonRelease) {
- XMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask, &e);
- /* set erase bit mask */
- mx = spect->fft_w*e.xbutton.x/(ww*xsc) - 1.0*xoff + spect->fft_x;
- my = spect->fft_h*(1.0-e.xbutton.y/(wh*ysc)) -1.0*yoff+spect->fft_y;
- x1 = mx - sew / 2.0; y1 = my - seh / 2.0;
- x2 = mx + sew / 2.0; y2 = my + seh / 2.0;
- if (x1 < 0) x1 = 0;
- if (y1 < 0) y1 = 0;
- if (x2 >= spect->fft->ntime) x2 = spect->fft->ntime - 1;
- if (y2 >= spect->fft->nfreq) y2 = spect->fft->nfreq - 1;
- for (j = y1; j <= y2; j++)
- for (i = x1; i <= x2; i++)
- spect->fft->mask[i][j] |= 0x01;
- /* redraw */
- spectro_thresh();
- spectro_points();
- spectro_draw();
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- info_draw(info);
- if (e.type == ButtonRelease) break;
- while(XCheckMaskEvent(dpy, PointerMotionMask, &e));
- }
- XUngrabPointer(dpy, CurrentTime);
- return 0;
-}
-
-int eraser_cursor(int w, int h) {
- XUndefineCursor(dpy, win);
- if ( !(mode & MODE_ERASE) ) return 0;
- if ( (ew+=w) < 3 ) ew = 3;
- if ( (eh+=h) < 3 ) eh = 3;
- if ( ew > ww/4 ) ew = ww / 4;
- if ( eh > wh/2 ) eh = wh / 2;
- int i, stride = ew/ 8 + 1;
- char data[stride * eh];
- char mask[stride * eh];
- XColor bg, fg;
- XAllocNamedColor(dpy,DefaultColormap(dpy,scr),e_col[0],&bg,&bg);
- XAllocNamedColor(dpy,DefaultColormap(dpy,scr),e_col[1],&fg,&fg);
- memset(mask, 0xAA, stride * eh);
- memset(data, 0xAA, stride * eh);
- for (i = 0; i < eh; i+= 2) memset(&mask[stride * i], 0x55, stride);
- Pixmap cd = XCreateBitmapFromData(dpy, win, data, ew, eh);
- Pixmap cm = XCreateBitmapFromData(dpy, win, mask, ew, eh);
- Cursor c = XCreatePixmapCursor(dpy, cd, cm, &fg, &bg, ew/2, eh/2);
- XDefineCursor(dpy, win, c);
- XFreePixmap(dpy, cd);
- XFreePixmap(dpy, cm);
- XFlush(dpy);
- return 0;
-}
-
-int move(double x, double y) {
- xoff += x / xsc * spect->fft_w; yoff += y / ysc * spect->fft_h;
- if ( yoff > spect->fft_h * (1.0 - 1.0/ysc) )
- yoff = spect->fft_h * (1.0 - 1.0/ysc);
- if ( yoff < 0) yoff = 0;
- if ( xoff < spect->fft_w * (1.0/xsc - 1.0) )
- xoff = spect->fft_w * (1.0/xsc - 1.0);
- if ( xoff > 0) xoff = 0;
- if (x || y) { /* don't redraw for offset checks */
- spectro_draw();
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- }
- return 0;
-}
-
-int play(float speed) {
- /* calculate fft coordinates of current view window */
- int tw = spect->fft_w / xsc;
- int th = spect->fft_h / ysc;
- int tx = spect->fft_x - xoff;
- int ty = spect->fft_y - yoff + spect->fft_h - th;
- if (tx + tw >= spect->fft->ntime) tw = spect->fft->ntime - tx - 1;
- if (ty + th >= spect->fft->nfreq) th = spect->fft->nfreq - ty - 1;
- /* get time and frequency values of current view window */
- double _start = spect->fft->time[tx];
- double _end = spect->fft->time[tx+tw];
- double _low = spect->fft->freq[ty];
- double _hi = spect->fft->freq[ty+th];
- double _mid = (_hi+_low)/2.0;
- double _wid = (_hi-_low)/2.0;
- /* fork and play */
- if (!fork()==0) {
- close(ConnectionNumber(dpy));
- char start[12], end[12], mid[12], wid[12], sp[8];
- snprintf(sp,7,"%3f",speed);
- sprintf(start,"=%lf",_start); sprintf(end,"=%lf",_end);
- sprintf(mid,"%lfk",_mid); sprintf(wid,"%lfk",_wid);
- execl("/usr/bin/play", "play", "-q", spect->fname,
- "trim", start, end, "bandpass", mid, wid,
- "speed", sp, NULL);
- perror("Fex Play");
- exit(1);
- }
- /* draw cursor while playing */
- int i, step = 12;
- double dur = _end - _start;
- useconds_t usec = dur * 1000000.0 * step / (double) ww;
- step = speed * step + 0.5;
- for (i = 0; i < ww; i+=step) {
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- XDrawLine(dpy, win, gc, i, 0, i, wh);
- XDrawLine(dpy, win, gc, i+step, 0, i+step, wh);
- XFlush(dpy);
- usleep(usec);
- }
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- XFlush(dpy);
- return 0;
-}
-
-int pt_line(double p, double l) {
- conf.col[RGBA_POINTS].w += p;
- conf.col[RGBA_LINES].w += l;
- if (conf.col[RGBA_POINTS].w < 0) conf.col[RGBA_POINTS].w = 0.0;
- if (conf.col[RGBA_LINES].w < 0) conf.col[RGBA_LINES].w = 0.0;
- spectro_points();
- spectro_draw();
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- return 0;
-}
-
-int screenshot() {
- char fname[256];
- static int n = 0;
- snprintf(fname, 256, "%s-%d.png", spect->name, n++);
- cairo_surface_t *t = cairo_xlib_surface_create(dpy, buf,
- DefaultVisual(dpy,scr), ww, wh);
- cairo_surface_write_to_png(t, fname);
- cairo_surface_destroy(t);
- return 0;
-}
-
-int series_export() {
- static int n = 0;
- double *dat = malloc(spect->fft_w * sizeof(double));
- int i, j, f;
- /* find the peak frequency relative to max for each time bin */
- for (i = spect->fft_x; i < spect->fft_w + spect->fft_x; ++i) {
- f = 0;
- for (j = spect->fft_y; j < spect->fft_h+spect->fft_y; ++j) {
- if (spect->fft->mask[i][j]) continue;
- if (spect->fft->amp[i][j] > spect->fft->amp[i][f] || !f)
- f = j;
- }
- if (f > 0 && spect->fft->amp[i][f] > conf.thresh)
- dat[i - spect->fft_x] = spect->fft->freq[f];
- else
- dat[i - spect->fft_x] = 0.0;
- }
- char *fname = malloc(strlen(spect->name) + 10);
- sprintf(fname, "%s%d.freq", spect->name, n++);
- f = open(fname, O_WRONLY | O_CREAT, 0644);
- write(f, dat, spect->fft_w * sizeof(double));
- close(f);
- free(fname);
- free(dat);
- return 0;
-}
-
-int sp_floor(double f) {
- conf.spect_floor += f;
- spectro_spec();
- spectro_draw();
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- if (info->vis) info->draw(info);
- return 0;
-}
-
-int threshold(double f) {
- conf.thresh += f;
- spectro_thresh();
- spectro_points();
- spectro_draw();
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- if (info->vis) info->draw(info);
- return 0;
-}
-
-int zoom(double f) {
- double px = xsc, py = ysc;
- xsc += f; ysc += f;
- if (xsc < 1.0) xsc = 1.0;
- if (ysc < 1.0) ysc = 1.0;
- xoff += (spect->fft_w/xsc - spect->fft_w/px) / 2.0;
- yoff += (spect->fft_h/py - spect->fft_h/ysc) / 2.0;
- if (f < 0) move(0,0); /* check offsets for bounds */
- spectro_draw();
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- return 0;
-}
-
DELETED src/xlib_events.c
Index: src/xlib_events.c
==================================================================
--- src/xlib_events.c
+++ src/xlib_events.c
@@ -1,202 +0,0 @@
-/**********************************************************************\
-* FEX - The Frequency Excursion Calculator
-*
-* Author: Jesse McClure, copyright 2013-2014
-* License: GPL3
-*
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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
-* .
-*
-\**********************************************************************/
-
-
-#define CtrlMask ControlMask
-void buttonpress(XEvent *ev) {
- XButtonEvent *e = &ev->xbutton;
- if (e->window == info->win) info->button(info, e);
- else if (e->state == (ControlMask | ShiftMask)) {
- if (e->button == 4) threshold(0.1);
- else if (e->button == 5) threshold(-0.1);
- else if (e->button == 6) sp_floor(-0.1);
- else if (e->button == 7) sp_floor(0.1);
- }
- else if (e->state == ControlMask) {
- if (e->button == 4) zoom(0.025);
- else if (e->button == 5) zoom(-0.025);
- else if (e->button == 6) return;
- else if (e->button == 7) return;
- }
- else if (e->state == Mod1Mask) {
- if (e->button == 4) eraser_cursor(1,1);
- else if (e->button == 5) eraser_cursor(-1,-1);
- else if (e->button == 6) eraser_cursor(-1,1);
- else if (e->button == 7) eraser_cursor(1,-1);
- }
- else if (e->state == ShiftMask) {
- if (e->button == 4) pt_line(0.2,0);
- else if (e->button == 5) pt_line(-0.2,0);
- else if (e->button == 6) pt_line(0,-0.2);
- else if (e->button == 7) pt_line(0,0.2);
- }
- else if (e->button == 4) move(0,-0.02);
- else if (e->button == 5) move(0,0.02);
- else if (e->button == 6) move(0.02,0);
- else if (e->button == 7) move(-0.02,0);
- else if (mode == MODE_ERASE && e->button == 1) erase(e->x, e->y);
- else if (mode == MODE_ERASE && e->button == 3) erase(-1,-1);
- else if (mode == MODE_CROP && e->button == 1) crop(e->x, e->y);
- while(XCheckMaskEvent(dpy, ButtonPressMask, ev));
-}
-
-void clientmessage(XEvent *ev) {
- XClientMessageEvent *e = &ev->xclient;
- if ( (Atom)e->data.l[0] == WM_DELETE_WINDOW ) {
- if (e->window == info->win) {
- info->vis = False;
- XUnmapWindow(dpy, info->win);
- }
- else if (e->window == win) {
- running = False;
- }
- }
-}
-
-void configurenotify(XEvent *ev) {
- while (XCheckTypedEvent(dpy,ConfigureNotify, ev));
- XConfigureEvent *e = &ev->xconfigure;
- if (e->window == win) {
- /* The XServer is not storing the new/current values for width +
- * height. These must be retrieved directly.
- * Is this an X11 bug? */
- Window wig;
- int ig;
- unsigned int uig;
- XGetGeometry(dpy, win, &wig, &ig, &ig, &ww, &wh, &uig, &uig);
- //ww = e->width; wh = e->height;
- spectro_draw();
- XSetWindowBackgroundPixmap(dpy, win, buf);
- XClearWindow(dpy,win);
- }
-}
-
-void expose(XEvent *ev) {
- XExposeEvent *e = &ev->xexpose;
- if (e->window == info->win) info->draw(info);
- else {
- XSetWindowBackgroundPixmap(dpy, win, buf);
- XClearWindow(dpy,win);
- }
-}
-
-void keypress(XEvent *ev) {
- XKeyEvent *e = &ev->xkey;
- KeySym sym = XkbKeycodeToKeysym(dpy, (KeyCode)e->keycode, 0, 0);
- int mod = ((e->state & ~Mod2Mask) & ~LockMask);
- if (mod == (ControlMask | ShiftMask)) {
- if (sym == XK_q) {
- spect->fex = 0;
- running = False;
- }
- if (sym == XK_j || sym == XK_Down) threshold(-0.05);
- else if (sym == XK_k || sym == XK_Up) threshold(0.05);
- else if (sym == XK_h || sym == XK_Left) sp_floor(-0.05);
- else if (sym == XK_l || sym == XK_Right) sp_floor(0.05);
- else if (sym == XK_p) play(0.1666);
- }
- else if (mod == (Mod1Mask | ShiftMask)) {
- if (sym == XK_p) play(0.08333);
- }
- else if (mod == ControlMask) {
- if (sym == XK_q) running = False;
- else if (sym == XK_f) series_export();
- else if (sym == XK_s) screenshot();
- else if (sym == XK_i) img_draw();
- else if (sym == XK_j || sym == XK_Down) zoom(-0.025);
- else if (sym == XK_k || sym == XK_Up) zoom(0.025);
- else if (sym == XK_h || sym == XK_Left) return;
- else if (sym == XK_l || sym == XK_Right) return;
- else if (sym == XK_p) play(0.33);
- }
- else if (mod == Mod1Mask) {
- if (sym == XK_j || sym == XK_Down) eraser_cursor(-1,-1);
- else if (sym == XK_k || sym == XK_Up) eraser_cursor(1,1);
- else if (sym == XK_h || sym == XK_Left) eraser_cursor(-1,1);
- else if (sym == XK_l || sym == XK_Right) eraser_cursor(1,-1);
- else if (sym == XK_p) play(0.25);
- }
- else if (mod == ShiftMask) {
- if (sym == XK_j || sym == XK_Down) pt_line(-0.2,0);
- else if (sym == XK_k || sym == XK_Up) pt_line(0.2,0);
- else if (sym == XK_h || sym == XK_Left) pt_line(0,-0.2);
- else if (sym == XK_l || sym == XK_Right) pt_line(0,0.2);
- else if (sym == XK_p) play(0.5);
- }
- else if (sym == XK_j || sym == XK_Down) move(0,0.02);
- else if (sym == XK_k || sym == XK_Up) move(0,-0.02);
- else if (sym == XK_h || sym == XK_Left) move(0.02,0);
- else if (sym == XK_l || sym == XK_Right) move(-0.02,0);
- else if (sym == XK_F1) {
- if (fork() == 0) {
- close(ConnectionNumber(dpy));
- fclose(stderr);
- fclose(stdout);
- execvp(conf.help_cmd[0],(char * const *)conf.help_cmd);
- }
- }
- else if (sym == XK_F2) {
- if ( (info->vis = !info->vis) ) XMapRaised(dpy,info->win);
- else XUnmapWindow(dpy,info->win);
- XFlush(dpy);
- }
- else if (sym == XK_e) {
- //mode = MODE_ERASE & (mode ^= MODE_ERASE);
- mode = (mode & MODE_ERASE ? 0 : MODE_ERASE);
- eraser_cursor(0,0);
- info->draw(info);
- }
- else if (sym == XK_c) {
- //mode = MODE_CROP & (mode ^= MODE_CROP);
- mode = (mode & MODE_CROP ? 0 : MODE_CROP);
- if (!(mode & MODE_CROP)) XDefineCursor(dpy, win, None);
- else XDefineCursor(dpy, win, XCreateFontCursor(dpy, 34));
- info->draw(info);
- }
- else if (sym == XK_Escape) {
- mode = MODE_NULL;
- XDefineCursor(dpy, win, None);
- info->draw(info);
- }
- else if (sym == XK_p) play(1.0);
- else if (sym == XK_t) {
- conf.layers = !conf.layers;
- spectro_draw();
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- }
- else if (sym == XK_u && mode & (MODE_ERASE)) erase(-1,-1);
- while(XCheckMaskEvent(dpy, KeyPressMask, ev));
-}
-
-void motionnotify(XEvent *ev) {
- //static int px, py;
- int x = ev->xmotion.x, y = ev->xmotion.y;
- mx = spect->fft_w * x / (xsc * ww) - 1.0 * xoff + spect->fft_x;
- my = spect->fft_h * (1.0 - y / (ysc * wh)) - 1.0 * yoff + spect->fft_y;
- info->draw(info);
- if (mode == MODE_CROP) {
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- XDrawLine(dpy, win, gc, x, 0, x, wh);
- XDrawLine(dpy, win, gc, 0, y, ww, y);
- }
-}
-
DELETED src/xlib_toolwin.c
Index: src/xlib_toolwin.c
==================================================================
--- src/xlib_toolwin.c
+++ src/xlib_toolwin.c
@@ -1,265 +0,0 @@
-/**********************************************************************\
-* FEX - The Frequency Excursion Calculator
-*
-* Author: Jesse McClure, copyright 2013-2014
-* License: GPL3
-*
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation, either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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
-* .
-*
-\**********************************************************************/
-
-typedef struct ToolWin ToolWin;
-struct ToolWin {
- Window win;
- Pixmap buf;
- int w, h;
- char *name;
- cairo_t *ctx;
- Bool vis;
- int (*backing)(ToolWin *);
- int (*draw)(ToolWin *);
- int (*button)(ToolWin *, XButtonEvent *);
-};
-
-static int toolwin_backing(ToolWin *);
-//static int toolwin_button(ToolWin *, XButtonEvent *);
-static int toolwin_create();
-static int toolwin_destroy();
-static int toolwin_draw(ToolWin *);
-static int toolwin_win_create(ToolWin *);
-static int toolwin_win_destroy(ToolWin *);
-
-static ToolWin *info; //, *help;
-//static char *help_name = "FEX Help";
-static cairo_text_extents_t ext;
-
-
-//static int help_draw(ToolWin *tw) {
-// toolwin_backing(tw);
-// cairo_set_source_rgba(tw->ctx,0,0,0,1.0);
-// cairo_rectangle(tw->ctx, 10, 10, 460, 300);
-// cairo_stroke_preserve(tw->ctx);
-// cairo_set_source_rgba(tw->ctx,0.8,0.8,0.8,1.0);
-// cairo_fill(tw->ctx);
-//// cairo_surface_t *img = cairo_image_surface_create_from_png(
-//// "./help.png");
-//// cairo_set_source_surface(tw->ctx,img, 8, 8);
-//// cairo_paint(tw->ctx);
-//// cairo_surface_destroy(img);
-//
-// toolwin_draw(tw);
-//}
-
-#define MARGIN 4.0
-#define MAX_STRING 256
-#define A_LEFT 0x00
-#define A_CENTER 0x01
-#define A_RIGHT 0x02
-static int info_printf(ToolWin *tw, int align, char *fmt, ...) {
- char str[MAX_STRING];
- va_list arg;
- va_start(arg, fmt);
- vsprintf(str, fmt, arg);
- va_end(arg);
- cairo_text_extents(tw->ctx,str,&ext);
- double x = (align == A_RIGHT ? tw->w - ext.x_advance - MARGIN :
- (align == A_CENTER ? (tw->w - ext.x_advance) / 2.0 : MARGIN));
- cairo_rel_move_to(tw->ctx, x, conf.font_size);
- cairo_show_text(tw->ctx,str);
- cairo_rel_move_to(tw->ctx, -1.0 * ext.x_advance - x, conf.font_size / 3.0);
- return 0;
-}
-
-static int info_split_printf(ToolWin *tw, char *bold, char *fmt, ...) {
- char str[MAX_STRING];
- va_list arg;
- va_start(arg, fmt);
- vsprintf(str, fmt, arg);
- va_end(arg);
- cairo_set_font_face(tw->ctx, conf.bfont);
- cairo_text_extents(tw->ctx,bold,&ext);
- cairo_rel_move_to(tw->ctx, MARGIN, conf.font_size);
- cairo_show_text(tw->ctx,bold);
- cairo_rel_move_to(tw->ctx, -1.0 * ext.x_advance - MARGIN, 0);
- cairo_set_font_face(tw->ctx, conf.font);
- cairo_text_extents(tw->ctx,str,&ext);
- cairo_rel_move_to(tw->ctx, tw->w - ext.x_advance - MARGIN, 0);
- cairo_show_text(tw->ctx,str);
- cairo_rel_move_to(tw->ctx, MARGIN - tw->w, conf.font_size / 3.0);
- return 0;
-}
-
-static int info_draw(ToolWin *tw) {
- toolwin_backing(tw);
- /* info */
- cairo_set_source_rgba(tw->ctx,0,0,0,1.0);
- cairo_set_font_face(tw->ctx, conf.bfont);
- cairo_move_to(tw->ctx, 0, 8);
- info_printf(tw, A_CENTER, "%.3lf sec, %.2lf KHz",
- spect->fft->time[mx],spect->fft->freq[my]);
- cairo_rel_move_to(tw->ctx,0,12);
- info_split_printf(tw, "Threshold:", "%.2lf", -1.0 * conf.thresh);
- info_split_printf(tw, "Spectrogram Floor:", "%.2lf",
- -1.0 * conf.spect_floor);
- info_split_printf(tw, "Path Length:","%.2lf", spect->pex);
- info_split_printf(tw, "Path Duration:","%.3lf", spect->tex);
- info_split_printf(tw, "Frequency Excursion:","%.3lf", spect->fex);
- cairo_move_to(tw->ctx, 0, 145);
- /* modes */
- info_split_printf(tw, "Modes:","");
- cairo_set_font_face(tw->ctx, conf.bfont);
- /* erase */
- set_color(tw->ctx,RGBA_ERASE1)
- if (mode & MODE_ERASE) set_color(tw->ctx,RGBA_ERASE1)
- else cairo_set_source_rgba(tw->ctx,0.8,0.8,0.8,1.0);
- cairo_rectangle(tw->ctx, 10, 170, tw->w / 2.0 - 15, 20);
- cairo_fill_preserve(tw->ctx);
- cairo_set_source_rgba(tw->ctx,0,0,0,1.0);
- cairo_stroke(tw->ctx);
- cairo_text_extents(tw->ctx,"Erase",&ext);
- cairo_move_to(tw->ctx, tw->w / 4.0 - ext.width / 2.0, 185);
- cairo_set_source_rgba(tw->ctx,0,0,0,1.0);
- cairo_show_text(tw->ctx,"Erase");
- /* crop */
- if (mode & MODE_CROP) set_color(tw->ctx, RGBA_CROP)
- else cairo_set_source_rgba(tw->ctx,0.8,0.8,0.8,1.0);
- cairo_rectangle(tw->ctx, 5 + tw->w / 2.0, 170, tw->w / 2.0 - 15, 20);
- cairo_fill_preserve(tw->ctx);
- cairo_set_source_rgba(tw->ctx,0.0,0.0,0.0,1.0);
- cairo_stroke(tw->ctx);
- cairo_text_extents(tw->ctx,"Crop",&ext);
- cairo_move_to(tw->ctx, tw->w * 0.75 - ext.width / 2.0, 185);
- cairo_set_source_rgba(tw->ctx,0,0,0,1.0);
- cairo_show_text(tw->ctx,"Crop");
- /* draw */
- toolwin_draw(tw);
- return 0;
-}
-
-static int info_button(ToolWin *tw, XButtonEvent *e) {
- if (e->y < 170 || e->y > 190) return 0;
- if (e->x < 10 || e->x > tw->w - 10) return 0;
- if (e->x < tw->w / 2.0 - 5) { /* erase button */
- if (e->button == 1) {
- //mode = MODE_ERASE & (mode ^= MODE_ERASE);
- mode = (mode & MODE_ERASE ? 0 : MODE_ERASE);
- eraser_cursor(0,0);
- tw->draw(tw);
- }
- }
- else { /* crop button */
- if (e->button == 1) {
- //mode = MODE_CROP & (mode ^= MODE_CROP);
- mode = (mode & MODE_CROP ? 0 : MODE_CROP);
- if (!(mode & MODE_CROP)) XDefineCursor(dpy, win, None);
- else XDefineCursor(dpy, win, XCreateFontCursor(dpy, 34));
- tw->draw(tw);
- }
- else if (e->button == 3) { /* uncrop */
- mode |= MODE_CROP;
- tw->draw(tw);
- spect->fft_x = 0;
- spect->fft_y = spect->fft_lo;
- spect->fft_w = spect->fft->ntime;
- spect->fft_h = spect->fft_hi - spect->fft_lo;
- spectro_spec();
- spectro_thresh();
- spectro_points();
- spectro_draw();
- XCopyArea(dpy, buf, win, gc, 0, 0, ww, wh, 0, 0);
- mode &= ~MODE_CROP;
- tw->draw(tw);
- }
- }
- return 0;
-}
-
-int toolwin_backing(ToolWin *tw) {
- cairo_set_source_rgba(tw->ctx,0.6,0.6,0.6,1.0);
- cairo_rectangle(tw->ctx, 0, 0, tw->w,tw->h);
- cairo_fill(tw->ctx);
- return 0;
-}
-
-//int toolwin_button(ToolWin *tw, XButtonEvent *e) {
-// XRaiseWindow(dpy, tw->win);
-// return 0;
-//}
-
-int toolwin_create() {
- info = (ToolWin *) calloc(1, sizeof(ToolWin));
- //help = (ToolWin *) calloc(1, sizeof(ToolWin));
- info->w = 240; info->h = 200;
- info->name = spect->name;
- info->vis = True;
- info->draw = info_draw;
- info->button = info_button;
- //help->w = 480; help->h = 320;
- //help->name = help_name;
- //help->vis = False;
- //help->draw = help_draw;
- //help->button = toolwin_button;
- toolwin_win_create(info);
- //toolwin_win_create(help);
- return 0;
-}
-
-int toolwin_destroy() {
- toolwin_win_destroy(info);
- //toolwin_win_destroy(help);
- free(info);
- //free(help);
- return 0;
-}
-
-int toolwin_draw(ToolWin *tw) {
- XClearWindow(dpy,tw->win);
- XFlush(dpy);
- return 0;
-}
-
-int toolwin_win_create(ToolWin *tw) {
- tw->win = XCreateSimpleWindow(dpy, root, 20, 20, tw->w, tw->h, 0, 0, 0);
- tw->buf = XCreatePixmap(dpy, root, tw->w, tw->h, DefaultDepth(dpy,scr));
- cairo_surface_t *t = cairo_xlib_surface_create(dpy, tw->buf,
- DefaultVisual(dpy,scr), tw->w, tw->h);
- tw->ctx = cairo_create(t);
- cairo_surface_destroy(t);
- cairo_set_font_face(tw->ctx,conf.font);
- cairo_set_font_size(tw->ctx,conf.font_size);
- XSelectInput(dpy, tw->win, EVENT_MASK);
- XSetTransientForHint(dpy, tw->win, win);
- XSetWMProtocols(dpy, tw->win, &WM_DELETE_WINDOW, 1);
- XSizeHints *hints = XAllocSizeHints();
- hints->min_width = hints->max_width = tw->w;
- hints->min_height = hints->max_height = tw->h;
- hints->flags = PMinSize | PMaxSize;
- XSetWMNormalHints(dpy, tw->win, hints);
- XFree(hints);
- XStoreName(dpy, tw->win, tw->name);
- if (tw->backing) tw->backing(tw);
- else toolwin_backing(tw);
- XSetWindowBackgroundPixmap(dpy, tw->win, tw->buf);
- XFlush(dpy);
- return 0;
-}
-
-int toolwin_win_destroy(ToolWin *tw) {
- cairo_destroy(tw->ctx);
- XDestroyWindow(dpy, tw->win);
- XFreePixmap(dpy, tw->buf);
- return 0;
-}
-