diff options
author | Bent Bisballe Nyeng <deva@aasimon.org> | 2014-09-08 20:48:38 +0200 |
---|---|---|
committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2014-09-08 20:48:38 +0200 |
commit | 7776aa97fc1c69a8f28ba4bab7387fb96be9a6e4 (patch) | |
tree | 8e23cfbfe7e93bdfad4421ccb0ec8c280a0b43ed | |
parent | 56f5965ffa2538dfa482ae9460e9579b4a04f8fb (diff) |
Import dgedit from drumgizmo repository (split into its own project).
53 files changed, 5773 insertions, 0 deletions
@@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,370 @@ +Installation Instructions +************************* + +Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, +Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + HP-UX `make' updates targets which have the same time stamps as +their prerequisites, which makes it generally unusable when shipped +generated files such as `configure' are involved. Use GNU `make' +instead. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `<wchar.h>' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf limitation. Until the limitation is lifted, you can use +this workaround: + + CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..b9e2bc8 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,13 @@ +AUTOMAKE_OPTIONS = gnu +SUBDIRS = src icons tools +DISTDIRS = src icons tools + +EXTRA_DIST = \ + version.h \ + hugin/hugin.h \ + hugin/hugin.hpp \ + hugin/hugin.c \ + hugin/hugin_util.h \ + hugin/hugin_syslog.h \ + hugin/hugin_syslog.c + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..b7bec5b --- /dev/null +++ b/configure.ac @@ -0,0 +1,70 @@ +# Filename: configure.in + +AC_INIT([drumgizmo], m4_esyscmd([cat version.h | cut -d'"' -f2 | xargs echo -n]))dnl" + +AC_CONFIG_SRCDIR([src/dgedit.cc]) +AM_INIT_AUTOMAKE + +AC_PROG_CXX +#AM_PROG_CC_C_O + +AC_PROG_LIBTOOL +AM_PROG_LIBTOOL + +AM_CONFIG_HEADER(config.h) +AC_STDC_HEADERS + +need_jack=no + +dnl ====================== +dnl Init pkg-config +dnl ====================== +PKG_PROG_PKG_CONFIG(0.23) + +HUGIN_PARM="-DDISABLE_HUGIN" +AC_ARG_WITH(debug, [ --with-debug Build with debug support]) +if test x$with_debug == xyes; then + AC_MSG_WARN([*** Building with debug support!]) + CXXFLAGS="$CXXFLAGS -Wall -Werror -g" + HUGIN_PARM="" +fi +CXXFLAGS="$CXXFLAGS $HUGIN_PARM" + + +dnl ====================== +dnl Check for Qt +dnl ====================== +PKG_CHECK_MODULES(QT, QtCore QtGui QtXml >= 4.5) +AC_CHECK_PROGS(QT_MOC, [moc4 moc-qt4 moc], []) +AC_CHECK_PROGS(QT_RCC, [rcc4 rcc-qt4 rcc], []) +AC_CHECK_PROGS(QT_UIC, [uic4 uic-qt4 uic], []) +if (test "$QT_MOC" = ""); then + AC_MSG_ERROR([QT4 moc is required.]) +fi +if (test "$QT_RCC" = ""); then + AC_MSG_ERROR([QT4 rcc is required.]) +fi +if (test "$QT_UIC" = ""); then + AC_MSG_ERROR([QT4 uic is required.]) +fi + +dnl ====================== +dnl Check for libao +dnl ====================== +PKG_CHECK_MODULES(AO, ao >= 0.8.8) + +dnl ====================== +dnl Check for sndfile +dnl ====================== +PKG_CHECK_MODULES(SNDFILE, sndfile >= 1.0.20) + +AC_SUBST(CFLAGS) +AC_SUBST(CPPFLAGS) +AC_SUBST(CXXFLAGS) +AC_SUBST(LDFLAGS) + +AC_OUTPUT( + Makefile + tools/Makefile + src/Makefile + icons/Makefile) diff --git a/icons/Makefile.am b/icons/Makefile.am new file mode 100644 index 0000000..b838804 --- /dev/null +++ b/icons/Makefile.am @@ -0,0 +1,3 @@ +EXTRA_DIST = \ + file.png \ + master.png
\ No newline at end of file diff --git a/icons/file.png b/icons/file.png Binary files differnew file mode 100644 index 0000000..7b95ebf --- /dev/null +++ b/icons/file.png diff --git a/icons/master.png b/icons/master.png Binary files differnew file mode 100644 index 0000000..fe44ada --- /dev/null +++ b/icons/master.png diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..734152c --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,73 @@ +bin_PROGRAMS = dgedit + +dgedit_LDADD = $(SNDFILE_LIBS) $(QT_LIBS) $(AO_LIBS) \ + $(shell ../tools/MocList o ) qrc_dgedit.o + +dgedit_CXXFLAGS = $(SNDFILE_CXXFLAGS) $(QT_CFLAGS) $(AO_CFLAGS) +AM_CXXFLAGS = $(QT_CFLAGS) + +dgedit_SOURCES = \ + dgedit.cc \ + audioextractor.cc \ + canvas.cc \ + canvastool.cc \ + canvastoollisten.cc \ + canvastoolselections.cc \ + canvastoolthreshold.cc \ + canvaswidget.cc \ + filelist.cc \ + itemeditor.cc \ + mainwindow.cc \ + mipmap.cc \ + player.cc \ + samplesorter.cc \ + selection.cc \ + selectioneditor.cc \ + volumefader.cc \ + zoomslider.cc + +EXTRA_DIST = \ + audioextractor.h \ + canvas.h \ + canvastool.h \ + canvastoollisten.h \ + canvastoolselections.h \ + canvastoolthreshold.h \ + canvaswidget.h \ + filelist.h \ + itemeditor.h \ + mainwindow.h \ + mipmap.h \ + player.h \ + samplesorter.h \ + selection.h \ + selectioneditor.h \ + sleep.h \ + volumefader.h \ + zoomslider.h \ + dgedit.qrc + +dgedit_MOC = $(shell ../tools/MocList cc ) + +BUILT_SOURCES = $(dgedit_MOC) qrc_dgedit.cc + +CLEANFILES = $(BUILT_SOURCES) + +qrc_%.cc: %.qrc + rcc $< > $@ + +%.moc.cc: %.h + $(QT_MOC) -o $@ $< + +# +# ui files not used in this project... +#%.h: %.ui +# $(QT_UIC) -o $@ $< +# +#%.cc: %.ui +# $(QT_UIC) -o $@ -impl $*.h $< + +# command for creating .res file from .rc on Win32 +%.res: %.rc + rc $< + diff --git a/src/audioextractor.cc b/src/audioextractor.cc new file mode 100644 index 0000000..71e0b2a --- /dev/null +++ b/src/audioextractor.cc @@ -0,0 +1,283 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * audioextractor.cc + * + * Sat Nov 21 13:09:35 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "audioextractor.h" + +#include <QDomDocument> +#include <QFile> +#include <QDir> +#include <QApplication> + +#include <sndfile.h> + +#define INSTRUMENT_VERSION "2.0" + +typedef struct { + SNDFILE *fh; + float *data; +} audiodata_t; + +AudioExtractor::AudioExtractor(Selections &s, QObject *parent) + : QObject(parent), selections(s) +{ +} + +void AudioExtractor::exportSelections() +{ + emit setMaximumProgress(selections.ids().size() + 1/* for xml writing*/); + int progress = 0; + emit progressUpdate(progress++); + qApp->processEvents(); + + // Open all input audio files: + audiodata_t audiodata[audiofiles.size()]; + + int idx = 0; + AudioFileList::iterator j = audiofiles.begin(); + while(j != audiofiles.end()) { + QString file = j->first; + + SF_INFO sf_info; + audiodata[idx].fh = sf_open(file.toStdString().c_str(), SFM_READ, &sf_info); + if(!audiodata[idx].fh) { + printf("Load error '%s'\n", file.toStdString().c_str()); + return; + } + + audiodata[idx].data = NULL; + + j++; + idx++; + } + + idx = 1; + QVector<sel_id_t> sels = selections.ids(); + + // Sort selections by velocity + for(int v1 = 0; v1 < sels.size(); v1++) { + for(int v2 = 0; v2 < sels.size(); v2++) { + + Selection sel1 = selections.get(sels[v1]); + Selection sel2 = selections.get(sels[v2]); + + if(sel1.energy < sel2.energy) { + sel_id_t vtmp = sels[v1]; + sels[v1] = sels[v2]; + sels[v2] = vtmp; + } + } + } + + // Iterate and write audio files + QVector<sel_id_t>::iterator si = sels.begin(); + while(si != sels.end()) { + Selection sel = selections.get(*si); + size_t offset = sel.from; + size_t size = sel.to - sel.from; + size_t fadein = sel.fadein; + size_t fadeout = sel.fadeout; + + + // Read all input audio file chunks: + for(int i = 0; i < audiofiles.size(); i++) { + + // Clear out old buffer (if one exists) + if(audiodata[i].data) { + delete audiodata[i].data; + audiodata[i].data = NULL; + } + + SNDFILE *fh = audiodata[i].fh; + + sf_seek(fh, offset, SEEK_SET); + + float *data = new float[size]; + sf_read_float(fh, data, size); + + // Apply linear fadein + for(size_t fi = 0; fi < fadein; fi++) { + float val = ((float)fi / (float)fadein); + if(fi < size) data[fi] *= val; + } + + // Apply fadeout + for(size_t fo = 0; fo < fadeout; fo++) { + float val = 1.0 - ((float)fo / (float)fadeout); + if( (((size - fadeout) + fo) < size) && + (((size - fadeout) + fo) >= 0) ) { + data[(size - fadeout) + fo] *= val; + } + } + + audiodata[i].data = data; + } + + // Create output path: + QString path = exportpath + "/" + prefix + "/samples"; + QDir d; + d.mkpath(path); + + // Write all sample chunks to single output file: + QString file = path + "/" + QString::number(idx) + "-" + prefix + ".wav"; + + SF_INFO sf_info; + sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; + sf_info.samplerate = 44100; + sf_info.channels = audiofiles.size(); + + SNDFILE *ofh = sf_open(file.toStdString().c_str(), SFM_WRITE, &sf_info); + if(!ofh) { + printf("Open for write error...\n"); + return; + } + + for(size_t ob = 0; ob < size; ob++) { + float obuf[audiofiles.size()]; + for(int ai = 0; ai < audiofiles.size(); ai++) { + obuf[ai] = audiodata[ai].data[ob]; + } + sf_write_float(ofh, obuf, audiofiles.size()); + } + sf_close(ofh); + + idx++; + si++; + + emit progressUpdate(progress++); + qApp->processEvents(); + } + + // Close all input audio files: + for(int i = 0; i < audiofiles.size(); i++) { + if(audiodata[i].data) { + delete audiodata[i].data; + audiodata[i].data = NULL; + } + + sf_close(audiodata[i].fh); + } + + QDomDocument doc; + QDomProcessingInstruction header = + doc.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); + doc.appendChild(header); + + QDomElement instrument = doc.createElement("instrument"); + instrument.setAttribute("version", INSTRUMENT_VERSION); + instrument.setAttribute("name", prefix); + doc.appendChild(instrument); + + QDomElement samples = doc.createElement("samples"); + instrument.appendChild(samples); + + { + // Do the adding to the xml file one sample at the time. + int index = 0; + QVector<sel_id_t>::iterator si = sels.begin(); + while(si != sels.end()) { + index++; + + Selection i = selections.get(*si); + i.name = prefix + "-" + QString::number(index); + + QDomElement sample = doc.createElement("sample"); + sample.setAttribute("name", i.name); + sample.setAttribute("power", QString::number(i.energy)); + samples.appendChild(sample); + + selections.update(*si, i); + + int channelnum = 1; // Filechannel numbers are 1-based. + AudioFileList::iterator j = audiofiles.begin(); + while(j != audiofiles.end()) { + + QString file = j->first; + QString name = j->second; + + QDomElement audiofile = doc.createElement("audiofile"); + audiofile.setAttribute("file", "samples/" + + QString::number(index) + "-" + prefix + ".wav"); + audiofile.setAttribute("channel", name); + audiofile.setAttribute("filechannel", QString::number(channelnum)); + sample.appendChild(audiofile); + channelnum++; + j++; + } + + si++; + } + } + + QFile xmlfile(exportpath + "/" + prefix + "/" + prefix + ".xml"); + xmlfile.open(QIODevice::WriteOnly); + xmlfile.write(doc.toByteArray()); + xmlfile.close(); + + emit progressUpdate(progress++); + qApp->processEvents(); +} + +void AudioExtractor::addFile(QString file, QString name) +{ + QPair<QString, QString> pair; + pair.first = file; + pair.second = name; + audiofiles.push_back(pair); +} + +void AudioExtractor::removeFile(QString file, QString name) +{ + AudioFileList::iterator j = audiofiles.begin(); + while(j != audiofiles.end()) { + if(file == j->first/* && name == j->second*/) { + audiofiles.erase(j); + return; + } + j++; + } +} + +void AudioExtractor::setOutputPrefix(const QString &p) +{ + prefix = p; +} + +void AudioExtractor::setExportPath(const QString &path) +{ + exportpath = path; +} + +void AudioExtractor::changeName(QString file, QString name) +{ + AudioFileList::iterator j = audiofiles.begin(); + while(j != audiofiles.end()) { + if(file == j->first) { + j->second = name; + return; + } + j++; + } +} diff --git a/src/audioextractor.h b/src/audioextractor.h new file mode 100644 index 0000000..ae50d17 --- /dev/null +++ b/src/audioextractor.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * audioextractor.h + * + * Sat Nov 21 13:09:35 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_AUDIOEXTRACTOR_H__ +#define __DRUMGIZMO_AUDIOEXTRACTOR_H__ + +#include <QObject> +#include <QSet> +#include <QLinkedList> +#include <QString> +#include <QVector> + +#include "selection.h" +#include "samplesorter.h" + +typedef QLinkedList< QPair<QString, QString> > AudioFileList; + +class AudioExtractor : public QObject { +Q_OBJECT +public: + AudioExtractor(Selections &selections, QObject *parent); + +public slots: + void addFile(QString file, QString name); + void changeName(QString file, QString name); + void removeFile(QString file, QString name); + + void exportSelections(); + void setExportPath(const QString &path); + void setOutputPrefix(const QString &prefix); + +signals: + void progressUpdate(int value); + void setMaximumProgress(int value); + +private: + Selections &selections; + AudioFileList audiofiles; + QString exportpath; + QString prefix; +}; + +#endif/*__DRUMGIZMO_AUDIOEXTRACTOR_H__*/ diff --git a/src/canvas.cc b/src/canvas.cc new file mode 100644 index 0000000..7007b0b --- /dev/null +++ b/src/canvas.cc @@ -0,0 +1,285 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvas.cc + * + * Tue Nov 10 08:37:37 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "canvas.h" + +#include <sndfile.h> +#include <QMouseEvent> +#include <QPaintEvent> +#include <QPainter> +#include <QKeyEvent> + +#include <math.h> + +#define DEFYSCALE 200 + +Canvas::Canvas(QWidget *parent) + : QWidget(parent) +{ + setAttribute(Qt::WA_StaticContents); + setMouseTracking(true); + setFocusPolicy(Qt::ClickFocus); + + mipmap = NULL; + + data = NULL; + size = 0; + + xscale = 1.0; + yscale = 1.0; + xoffset = 0.0; + yoffset = 0.5; + + colBg = QColor(180, 200, 180); + colSec = QColor(160, 180, 160); + colWavMax = QColor(100, 100, 100); + colWavAvg = QColor(0, 0, 0); + colMax = QColor(127, 127, 255); + colHalf = QColor(180, 180, 255); + + setCursor(Qt::ArrowCursor); + + wav = QImage(width(), height(), QImage::Format_RGB32); +} + +Canvas::~Canvas() +{ + if(data) delete[] data; + if(mipmap) delete mipmap; +} + +void Canvas::load(QString file) +{ + if(data) { + delete[] data; + data = NULL; + size = 0; + } + + if(mipmap) { + delete mipmap; + mipmap = NULL; + } + + SF_INFO sf_info; + SNDFILE *fh = sf_open(file.toStdString().c_str(), SFM_READ, &sf_info); + if(!fh) { + printf("Load error...\n"); + return; + } + + size = sf_info.frames; + + printf("Size: %u\n", (unsigned int)sf_info.frames); + data = new float[size]; + + sf_read_float(fh, data, size); + + sf_close(fh); + + mipmap = new MipMap(data, size); + + updateWav(); + update(); +} + + +#define SCALEX ((xscale * (float)size/(float)width()) + 0.1) +#define OFFSETX (xoffset * (float)size) +float Canvas::mapX(float x) +{ + float val = (x - OFFSETX) / SCALEX; + return val; +} + +float Canvas::unmapX(float x) +{ + float val = x * SCALEX + OFFSETX; + return val; +} + +#define SCALEY (yscale * height()) +#define OFFSETY (((float)height() / 2.0) + ((yoffset * 2.0 - 1.0) * SCALEY)) +float Canvas::mapY(float y) +{ + float val = OFFSETY + (y * SCALEY); + return val; +} + +float Canvas::unmapY(float y) +{ + float val = (y - OFFSETY) / SCALEY; + return val; +} + +void Canvas::mouseMoveEvent(QMouseEvent *event) +{ + for(int i = 0; i < tools.size(); i++) { + if(tools[i]->mouseMoveEvent(event)) return; + } + + setCursor(Qt::ArrowCursor); +} + +void Canvas::mousePressEvent(QMouseEvent *event) +{ + for(int i = 0; i < tools.size(); i++) { + if(tools[i]->mousePressEvent(event)) return; + } +} + +void Canvas::mouseReleaseEvent(QMouseEvent *event) +{ + for(int i = 0; i < tools.size(); i++) { + if(tools[i]->mouseReleaseEvent(event)) return; + } +} + +void Canvas::resizeEvent(QResizeEvent *event) +{ + for(int i = 0; i < tools.size(); i++) { + tools[i]->resizeEvent(event); + } + + wav = QImage(width(), height(), QImage::Format_RGB32); + updateWav(); + update(); +} + +void Canvas::getWavValues(int last, int lx, float *vu, float *vl, + float *avgu, float *avgl) +{ + if(mipmap == NULL) return; + + MipMapValue val = mipmap->lookup(last, lx); + + *vu = val.max; + *vl = val.min; + *avgu = val.uavg; + *avgl = val.lavg; +} + +void Canvas::updateWav() +{ + QPainter painter(&wav); + + painter.setPen(colBg); + painter.setBrush(colBg); + painter.drawRect(0, 0, wav.width(), wav.height()); + + painter.setPen(colSec); + int step = 44100; + for(size_t i = 0; i < size; i += step) { + painter.drawLine(mapX(i), mapY(1.0), mapX(i), mapY(-1.0)); + } + + painter.setPen(colMax); + painter.drawLine(0, mapY(1.0), wav.width(), mapY(1.0)); + painter.drawLine(0, mapY(-1.0), wav.width(), mapY(-1.0)); + + painter.setPen(colHalf); + painter.drawLine(0, mapY(0.5), wav.width(), mapY(0.5)); + painter.drawLine(0, mapY(-0.5), wav.width(), mapY(-0.5)); + + if(data) { + int last = unmapX(0); + for(int x = 0; x < wav.width(); x++) { + int lx = unmapX(x); + if(lx > (int)size || lx < 0) break; + float vu = 0; + float vl = 0; + float avgu = 0; + float avgl = 0; + + getWavValues(last, lx, &vu, &vl, &avgu, &avgl); + + int c = mapY(0.0); + + painter.setPen(colWavMax); + painter.drawLine(x, c, x, mapY(vu)); + painter.drawLine(x, c, x, mapY(vl)); + + painter.setPen(colWavAvg); + painter.drawLine(x, c, x, mapY(avgu)); + painter.drawLine(x, c, x, mapY(avgl)); + + last = lx; + } + } +} + +void Canvas::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + + painter.drawImage(event->rect(),wav,event->rect()); + + for(int i = 0; i < tools.size(); i++) { + tools[i]->paintEvent(event, painter); + } +} + +void Canvas::keyReleaseEvent(QKeyEvent *event) +{ + for(int i = 0; i < tools.size(); i++) { + tools[i]->keyReleaseEvent(event); + } +} + +void Canvas::setXScale(float scale) +{ + scale = (pow(100.0,scale) / 100.0) - (pow(100.0, 0.0)/ 100.0); + if(scale < 0.0) scale = 0.0; + if(scale > 1.0) scale = 1.0; + xscale = scale; + updateWav(); + update(); +} + +void Canvas::setYScale(float scale) +{ + yscale = scale; + updateWav(); + update(); +} + +void Canvas::setXOffset(float offset) +{ + if(offset < 0.0) offset = 0.0; + if(offset > 1.0) offset = 1.0; + xoffset = offset; + updateWav(); + update(); +} + +void Canvas::setYOffset(float offset) +{ + if(offset < 0.0) offset = 0.0; + if(offset > 1.0) offset = 1.0; + yoffset = offset; + updateWav(); + update(); +} diff --git a/src/canvas.h b/src/canvas.h new file mode 100644 index 0000000..c83a726 --- /dev/null +++ b/src/canvas.h @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvas.h + * + * Tue Nov 10 08:37:37 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_CANVAS_H__ +#define __DRUMGIZMO_CANVAS_H__ + +#include <QWidget> +#include <QColor> +#include <QImage> + +#include "mipmap.h" +#include "canvastool.h" + +class Canvas : public QWidget { +Q_OBJECT +public: + Canvas(QWidget *parent); + ~Canvas(); + + void load(QString file); + + void addTool(CanvasTool *tool); + + float mapX(float x); + float unmapX(float x); + float mapY(float y); + float unmapY(float y); + +public slots: + void setXScale(float scale); + void setYScale(float scale); + void setXOffset(float scroll); + void setYOffset(float scroll); + +protected: + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void resizeEvent(QResizeEvent *event); + void paintEvent(QPaintEvent *event); + void keyReleaseEvent(QKeyEvent *event); + +private: + MipMap *mipmap; + + void updateWav(); + void getWavValues(int last, int lx, float *vu, float *vl, + float *avgu, float *avgl); + + QImage wav; + +public: + float *data; + size_t size; + + QVector<CanvasTool*> tools; + +private: + float xscale; + float yscale; + float xoffset; + float yoffset; + + QColor colBg; + QColor colSec; + QColor colMax; + QColor colHalf; + QColor colWavMax; + QColor colWavAvg; +}; + +#endif/*__DRUMGIZMO_CANVAS_H__*/ diff --git a/src/canvastool.cc b/src/canvastool.cc new file mode 100644 index 0000000..9d23d97 --- /dev/null +++ b/src/canvastool.cc @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastool.cc + * + * Thu Jul 28 23:01:36 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "canvastool.h" + +#include <stdio.h> + +bool CanvasTool::mouseMoveEvent(QMouseEvent *) +{ + return false; +} + +bool CanvasTool::mousePressEvent(QMouseEvent *) +{ + return false; +} + +bool CanvasTool::mouseReleaseEvent(QMouseEvent *) +{ + return false; +} + +void CanvasTool::resizeEvent(QResizeEvent *) +{ +} + +void CanvasTool::paintEvent(QPaintEvent *, QPainter &) +{ +} + +void CanvasTool::keyReleaseEvent(QKeyEvent *) +{ +} + +void CanvasTool::setActive(bool active) +{ + printf("setActive(%d)\n", active); + _active = active; + emit activateChanged(active); +} + +void CanvasTool::activate() +{ + setActive(true); +} + +void CanvasTool::disactivate() +{ + setActive(false); +} + +bool CanvasTool::isActive() +{ + return _active; +} diff --git a/src/canvastool.h b/src/canvastool.h new file mode 100644 index 0000000..56cfa84 --- /dev/null +++ b/src/canvastool.h @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastool.h + * + * Thu Jul 28 20:12:25 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_CANVASTOOL_H__ +#define __DRUMGIZMO_CANVASTOOL_H__ + +#include <QMouseEvent> +#include <QResizeEvent> +#include <QPaintEvent> +#include <QKeyEvent> +#include <QPainter> +#include <QString> + +class CanvasTool : public QObject { +Q_OBJECT +public: + virtual QString name() = 0; + virtual bool mouseMoveEvent(QMouseEvent *event); + virtual bool mousePressEvent(QMouseEvent *event); + virtual bool mouseReleaseEvent(QMouseEvent *event); + virtual void resizeEvent(QResizeEvent *event); + virtual void paintEvent(QPaintEvent *event, QPainter &painter); + virtual void keyReleaseEvent(QKeyEvent *event); + + bool isActive(); + +signals: + void activateChanged(bool activestate); + +public slots: + void setActive(bool active); + void activate(); + void disactivate(); + +private: + bool _active; +}; + +#endif/*__DRUMGIZMO_CANVASTOOL_H__*/ diff --git a/src/canvastoollisten.cc b/src/canvastoollisten.cc new file mode 100644 index 0000000..847c32d --- /dev/null +++ b/src/canvastoollisten.cc @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoollisten.cc + * + * Fri Jul 29 16:57:48 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "canvastoollisten.h" + +#include <QApplication> + +CanvasToolListen::CanvasToolListen(Canvas *c, Player &p) + : player(p) +{ + lastpos = pos = 0; + canvas = c ; +} + +bool CanvasToolListen::mousePressEvent(QMouseEvent *event) +{ + if(!isActive()) return false; + player.setPosition(canvas->unmapX(event->x())); + canvas->update(); + connect(&player, SIGNAL(positionUpdate(size_t)), this, SLOT(update(size_t))); + return true; +} + +bool CanvasToolListen::mouseReleaseEvent(QMouseEvent *event) +{ + if(!isActive()) return false; + player.stop(); + disconnect(&player, SIGNAL(positionUpdate(size_t)), + this, SLOT(update(size_t))); + lastpos = 0; + canvas->update(); + return true; +} + +void CanvasToolListen::paintEvent(QPaintEvent *event, QPainter &painter) +{ + if(!isActive()) return; + + if(player.pos < player.end) { + painter.setPen(QColor(0, 127, 127)); + painter.drawLine(canvas->mapX(pos), + event->rect().y(), + canvas->mapX(pos), + event->rect().y() + event->rect().height()); + } +} + +void CanvasToolListen::update(size_t pos) +{ + this->pos = pos; + size_t last = canvas->mapX(lastpos); + size_t x = canvas->mapX(player.pos); + QRect r(last, 0, + x - last + 2, canvas->height()); + + canvas->update(r); + lastpos = pos; +} diff --git a/src/canvastoollisten.h b/src/canvastoollisten.h new file mode 100644 index 0000000..bfb2d41 --- /dev/null +++ b/src/canvastoollisten.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoollisten.h + * + * Fri Jul 29 16:57:48 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_CANVASTOOLLISTEN_H__ +#define __DRUMGIZMO_CANVASTOOLLISTEN_H__ + +#include "canvastool.h" + +//#include <QTimer> + +#include "canvas.h" +#include "player.h" + +class CanvasToolListen : public CanvasTool { +Q_OBJECT +public: + CanvasToolListen(Canvas *canvas, Player &player); + + QString name() { return "Listen"; } + bool mousePressEvent(QMouseEvent *event); + bool mouseReleaseEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event, QPainter &painter); + + void playRange(unsigned int from, unsigned int to); + +public slots: + void update(size_t position); + +private: + Canvas *canvas; + + Player &player; + + size_t lastpos; + size_t pos; +}; + +#endif/*__DRUMGIZMO_CANVASTOOLLISTEN_H__*/ diff --git a/src/canvastoolselections.cc b/src/canvastoolselections.cc new file mode 100644 index 0000000..ad5e193 --- /dev/null +++ b/src/canvastoolselections.cc @@ -0,0 +1,319 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoolselections.cc + * + * Thu Jul 28 20:16:59 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "canvastoolselections.h" + +#include <math.h> +#include <stdio.h> + +#define mapX(x) canvas->mapX(x) +#define mapY(x) canvas->mapY(x) +#define unmapX(x) canvas->unmapX(x) +#define unmapY(x) canvas->unmapY(x) + +CanvasToolSelections::CanvasToolSelections(Canvas *c, Selections &s, + Selections &p) + : selections(s), selections_preview(p) +{ + threshold = 0.5; // Default from CanvasToolThreshold + hold = 100; + + canvas = c; + + selection_is_moving_left = false; + selection_is_moving_right = false; + + colSelBg = QColor(255, 0, 0, 60); + colSel = QColor(255, 0, 0, 160); + colActiveSelBg = QColor(255, 255, 0, 60); + colActiveSel = QColor(255, 255, 0, 160); + colPreviewSelBg = QColor(0, 0, 255, 60); + colPreviewSel = QColor(0, 0, 255, 160); +} + +bool CanvasToolSelections::mouseMoveEvent(QMouseEvent *event) +{ + sel_id_t active_selection = selections.active(); + Selection act_sel = selections.get(active_selection); + + if(selection_is_moving_left) { + float val = unmapX(event->x()); + if(val > act_sel.to) val = act_sel.to - 1; + act_sel.from = val; + selections.update(active_selection, act_sel); + canvas->update(); + return true; + } + + if(selection_is_moving_right) { + float val = unmapX(event->x()); + if(val < act_sel.from) val = act_sel.from + 1; + act_sel.to = val; + selections.update(active_selection, act_sel); + canvas->update(); + return true; + } + + if(event->button() != Qt::LeftButton) { + // Check if a selection is being dragged. + QVector<sel_id_t> ids = selections.ids(); + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + if(abs(event->x() - mapX(sel.from)) < 2 + || abs(event->x() - mapX(sel.to)) < 2) { + canvas->setCursor(Qt::SplitHCursor); + return true; + } + i++; + } + } + + return false; +} + +bool CanvasToolSelections::mousePressEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) { + // Check if a selection is being dragged. + QVector<sel_id_t> ids = selections.ids(); + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + if(abs(event->x() - mapX(sel.from)) < 2) { + selections.setActive(*i); + selection_is_moving_left = true; + return true; + } + + if(abs(event->x() - mapX(sel.to)) < 2) { + selections.setActive(*i); + selection_is_moving_right = true; + return true; + } + + i++; + } + + // Check if a selection is being selected. + i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + if(event->x() > mapX(sel.from) && + event->x() < mapX(sel.to)) { + selections.setActive(*i); + canvas->update(); + return true; + } + + i++; + } + + // Make new selection + int from = unmapX(event->x()); + Selection new_selection(from, from); + sel_id_t id = selections.add(new_selection); + selections.setActive(id); + selection_is_moving_right = true; + canvas->update(); + return true; + } + + return false; +} + +bool CanvasToolSelections::mouseReleaseEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) { + if(selection_is_moving_left || selection_is_moving_right) { + selection_is_moving_left = false; + selection_is_moving_right = false; + canvas->setCursor(Qt::ArrowCursor); + canvas->update(); + return true; + } + } + + return false; +} + +void CanvasToolSelections::paintEvent(QPaintEvent *event, QPainter &painter) +{ + int pos = unmapX(event->rect().x()); + int width = unmapX(event->rect().width()); + + { + QVector<sel_id_t> ids = selections.ids(); + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + int from = sel.from; + int to = sel.to; + int fadein = sel.fadein; + int fadeout = sel.fadeout; + if(from > pos + width || to + width < pos) { i++; continue; } + if(selections.active() == *i) { + painter.setBrush(colActiveSelBg); + painter.setPen(colActiveSel); + } else { + painter.setBrush(colSelBg); + painter.setPen(colSel); + } + painter.drawRect(mapX(from), mapY(-1.0), + mapX(to) - mapX(from), mapY(1.0) - mapY(-1.0)); + painter.drawLine(mapX(from), mapY(0.0), mapX(from + fadein), mapY(-1.0)); + painter.drawLine(mapX(from), mapY(0.0), mapX(from + fadein), mapY(1.0)); + painter.drawLine(mapX(to - fadeout), mapY(-1.0), mapX(to), mapY(0.0)); + painter.drawLine(mapX(to - fadeout), mapY(1.0), mapX(to), mapY(0.0)); + i++; + } + } + + if(show_preview) { + QVector<sel_id_t> ids = selections_preview.ids(); + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections_preview.get(*i); + int from = sel.from; + int to = sel.to; + int fadein = sel.fadein; + int fadeout = sel.fadeout; + if(from > pos + width || to + width < pos) { i++; continue; } + painter.setBrush(colPreviewSelBg); + painter.setPen(colPreviewSel); + + painter.drawRect(mapX(from), mapY(-1.0), + mapX(to) - mapX(from), mapY(1.0) - mapY(-1.0)); + painter.drawLine(mapX(from), mapY(0.0), mapX(from + fadein), mapY(-1.0)); + painter.drawLine(mapX(from), mapY(0.0), mapX(from + fadein), mapY(1.0)); + painter.drawLine(mapX(to - fadeout), mapY(-1.0), mapX(to), mapY(0.0)); + painter.drawLine(mapX(to - fadeout), mapY(1.0), mapX(to), mapY(0.0)); + i++; + } + } +} + +void CanvasToolSelections::keyReleaseEvent(QKeyEvent *event) +{ + if(selections.active() != SEL_NONE && event->key() == Qt::Key_Delete) { + selections.remove(selections.active()); + canvas->update(); + } +} + +void CanvasToolSelections::thresholdChanged(double t) +{ + threshold = t; +} + +void CanvasToolSelections::holdChanged(int h) +{ + hold = h; +} + +void CanvasToolSelections::noiseFloorChanged(int t) +{ + double div = 666.0 / 0.00003; + noise_floor = (double)t/div; +} + +void CanvasToolSelections::fadeoutChanged(int t) +{ + fadeout = (double)t/1000.0; +} + +void CanvasToolSelections::autoCreateSelections() +{ + doAutoCreateSelections(false); +} + +void CanvasToolSelections::autoCreateSelectionsPreview() +{ + doAutoCreateSelections(true); +} + +void CanvasToolSelections::doAutoCreateSelections(bool preview) +{ + float *data = canvas->data; + size_t size = canvas->size; + + if(preview) selections_preview.clear(); + + for(size_t i = 0; i < size; i++) { + if(fabs(data[i]) > fabs(threshold)) { + int from = i; + + if(data[from] > 0.0) { + while(data[from] > data[from-1] // Falling + && data[from-1] > 0.0 // Not crossing zero + ) { + from--; + } + } else if(data[from] < 0.0) { + while(data[from] < data[from-1] // Rising + && data[from-1] < 0.0 // Not crossing zero + ) { + from--; + } + } + + int to = i; + float runavg = fabs(data[from]); + while((runavg > noise_floor || + to < from + hold) && + to < (int)size) { + double p = 0.9; + runavg = runavg * p + fabs(data[to]) * (1 - p); + to++; + } + + Selection s(from, to, 2, ((to - from) / 3) * fadeout); + if(preview) { + selections_preview.add(s); + } else { + selections.add(s); + } + + i = to+1; + } + } + canvas->update(); +} + +void CanvasToolSelections::clearSelections() +{ + selections.clear(); + selection_is_moving_left = false; + selection_is_moving_right = false; + canvas->setCursor(Qt::ArrowCursor); + canvas->update(); +} + +void CanvasToolSelections::setShowPreview(bool s) +{ + show_preview = s; + canvas->update(); +} diff --git a/src/canvastoolselections.h b/src/canvastoolselections.h new file mode 100644 index 0000000..0557520 --- /dev/null +++ b/src/canvastoolselections.h @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoolselections.h + * + * Thu Jul 28 20:16:59 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_CANVASTOOLSELECTIONS_H__ +#define __DRUMGIZMO_CANVASTOOLSELECTIONS_H__ + +#include "canvastool.h" + +#include <QColor> + +#include "canvas.h" + +#include "selection.h" + +class CanvasToolSelections : public CanvasTool { +Q_OBJECT +public: + CanvasToolSelections(Canvas *canvas, Selections &selections, + Selections &selections_preview); + + QString name() { return "Selections"; } + bool mouseMoveEvent(QMouseEvent *event); + bool mousePressEvent(QMouseEvent *event); + bool mouseReleaseEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event, QPainter &painter); + void keyReleaseEvent(QKeyEvent *event); + + //Selections selections(); + +signals: + //void selectionsChanged(Selections selections); + //void activeSelectionChanged(sel_id_t id); + +public slots: + void autoCreateSelections(); + void autoCreateSelectionsPreview(); + void clearSelections(); + void thresholdChanged(double threshold); + void noiseFloorChanged(int t); + void holdChanged(int h); + void fadeoutChanged(int f); + void setShowPreview(bool show_preview); + +private: + void doAutoCreateSelections(bool preview); + + bool selection_is_moving_left; + bool selection_is_moving_right; + + Canvas *canvas; + + double threshold; + double noise_floor; + double fadeout; + int hold; + + QColor colSelBg; + QColor colSel; + QColor colActiveSelBg; + QColor colActiveSel; + QColor colPreviewSelBg; + QColor colPreviewSel; + + Selections &selections; + Selections &selections_preview; + + bool show_preview; +}; + +#endif/*__DRUMGIZMO_CANVASTOOLSELECTIONS_H__*/ diff --git a/src/canvastoolthreshold.cc b/src/canvastoolthreshold.cc new file mode 100644 index 0000000..a321ff2 --- /dev/null +++ b/src/canvastoolthreshold.cc @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoolthreshold.cc + * + * Fri Jul 29 16:27:00 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "canvastoolthreshold.h" + +#include <math.h> + +#define mapX(x) canvas->mapX(x) +#define mapY(x) canvas->mapY(x) +#define unmapX(x) canvas->unmapX(x) +#define unmapY(x) canvas->unmapY(x) + +CanvasToolThreshold::CanvasToolThreshold(Canvas *c) +{ + canvas = c; + threshold = 0.5; + threshold_is_moving = false; + + colThreshold = QColor(255, 127, 127); + colThresholdMoving = QColor(180, 0, 0); +} + +bool CanvasToolThreshold::mouseMoveEvent(QMouseEvent *event) +{ + if(!isActive()) return false; + + if(event->button() != Qt::LeftButton) { + if(abs(event->y() - mapY(threshold)) < 2 || + abs(event->y() - mapY(-threshold)) < 2 ) { + canvas->setCursor(Qt::SplitVCursor); + return true; + } + } + + if(threshold_is_moving) { + float val = unmapY(event->y()); + if(fabs(val) > 1.0) val = 1.0; + threshold = fabs(val); + canvas->update(); + + emit thresholdChanging(threshold); + + return true; + } + + return false; +} + +bool CanvasToolThreshold::mousePressEvent(QMouseEvent *event) +{ + if(!isActive()) return false; + + if(event->button() == Qt::LeftButton) { + + // Check if threshold is being dragged. + if(abs(event->y() - mapY(threshold)) < 2 || + abs(event->y() - mapY(-threshold)) < 2 ) { + threshold_is_moving = true; + canvas->update(); + return true; + } + } + + return false; +} + +bool CanvasToolThreshold::mouseReleaseEvent(QMouseEvent *event) +{ + if(!isActive()) return false; + + if(event->button() == Qt::LeftButton) { + if(threshold_is_moving) { + threshold_is_moving = false; + canvas->setCursor(Qt::ArrowCursor); + canvas->update(); + + emit thresholdChanged(threshold); + + return true; + } + } + + return false; +} + +void CanvasToolThreshold::paintEvent(QPaintEvent *event, QPainter &painter) +{ + if(!isActive()) return; + + if(threshold_is_moving) painter.setPen(colThresholdMoving); + else painter.setPen(colThreshold); + painter.drawLine(event->rect().x(), mapY(threshold), + event->rect().x() + event->rect().width(), mapY(threshold)); + painter.drawLine(event->rect().x(), mapY(-threshold), + event->rect().x() + event->rect().width(), mapY(-threshold)); +} + diff --git a/src/canvastoolthreshold.h b/src/canvastoolthreshold.h new file mode 100644 index 0000000..907e312 --- /dev/null +++ b/src/canvastoolthreshold.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvastoolthreshold.h + * + * Fri Jul 29 16:27:00 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_CANVASTOOLTHRESHOLD_H__ +#define __DRUMGIZMO_CANVASTOOLTHRESHOLD_H__ + +#include "canvastool.h" + +#include <QColor> + +#include "canvas.h" + +class CanvasToolThreshold : public CanvasTool { +Q_OBJECT +public: + CanvasToolThreshold(Canvas *canvas); + + QString name() { return "Threshold"; } + bool mouseMoveEvent(QMouseEvent *event); + bool mousePressEvent(QMouseEvent *event); + bool mouseReleaseEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event, QPainter &painter); + +signals: + void thresholdChanged(double threshold); + void thresholdChanging(double threshold); + +private: + float threshold; + bool threshold_is_moving; + + Canvas *canvas; + + QColor colThreshold; + QColor colThresholdMoving; +}; + +#endif/*__DRUMGIZMO_CANVASTOOLTHRESHOLD_H__*/ diff --git a/src/canvaswidget.cc b/src/canvaswidget.cc new file mode 100644 index 0000000..35b3684 --- /dev/null +++ b/src/canvaswidget.cc @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvaswidget.cc + * + * Fri Aug 1 19:31:32 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "canvaswidget.h" + +#include <QGridLayout> + +#define MAXVAL 10000000L +#define SINGLESTEP MAXVAL/100000 +#define PAGESTEP MAXVAL/10000 + +CanvasWidget::CanvasWidget(QWidget *parent) +{ + QGridLayout *g = new QGridLayout(this); + + canvas = new Canvas(this); + g->addWidget(canvas, 0, 0); + + yoffset = new QScrollBar(Qt::Vertical); + yoffset->setRange(0, MAXVAL); + yoffset->setPageStep(PAGESTEP); + yoffset->setSingleStep(SINGLESTEP); + connect(yoffset, SIGNAL(valueChanged(int)), this, SLOT(setYOffset(int))); + g->addWidget(yoffset, 0, 1); + + yscale = new ZoomSlider(Qt::Vertical); + yscale->setRange(0.9, 30); + yscale->setTickWidth(0.1); + connect(yscale, SIGNAL(valueChanged(float)), this, SLOT(setYScale(float))); + g->addWidget(yscale, 0, 2); + + xoffset = new QScrollBar(Qt::Horizontal); + xoffset->setRange(0, MAXVAL); + xoffset->setPageStep(PAGESTEP); + xoffset->setSingleStep(SINGLESTEP); + connect(xoffset, SIGNAL(valueChanged(int)), this, SLOT(setXOffset(int))); + g->addWidget(xoffset, 1, 0); + + xscale = new ZoomSlider(Qt::Horizontal); + xscale->setRange(1, 0.0001); + xscale->setTickWidth(0.0001); + connect(xscale, SIGNAL(valueChanged(float)), this, SLOT(setXScale(float))); + g->addWidget(xscale, 2, 0); + + setLayout(g); +} + +void CanvasWidget::setXScale(float val) +{ + canvas->setXScale(val); +} + +void CanvasWidget::setYScale(float val) +{ + canvas->setYScale(val); +} + +void CanvasWidget::setXOffset(int of) +{ + // range 0.0 - 1.0 + float val = (float)of/(float)MAXVAL; + canvas->setXOffset(val); +} + +void CanvasWidget::setYOffset(int of) +{ + // range 0.0 - 1.0 + float val = (float)(of * -1 + MAXVAL)/(float)MAXVAL; + canvas->setYOffset(val); +} diff --git a/src/canvaswidget.h b/src/canvaswidget.h new file mode 100644 index 0000000..1ae73da --- /dev/null +++ b/src/canvaswidget.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvaswidget.h + * + * Fri Aug 1 19:31:31 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_CANVASWIDGET_H__ +#define __DRUMGIZMO_CANVASWIDGET_H__ + +#include <QWidget> + +#include <QScrollBar> + +#include "canvas.h" +#include "zoomslider.h" + +class CanvasWidget : public QWidget { +Q_OBJECT +public: + CanvasWidget(QWidget *parent); + + Canvas *canvas; + + QScrollBar *yoffset; + ZoomSlider *yscale; + ZoomSlider *xscale; + QScrollBar *xoffset; + +public slots: + void setXScale(float); + void setYScale(float); + void setXOffset(int); + void setYOffset(int); + +}; + +#endif/*__DRUMGIZMO_CANVASWIDGET_H__*/ diff --git a/src/dgedit.cc b/src/dgedit.cc new file mode 100644 index 0000000..0417876 --- /dev/null +++ b/src/dgedit.cc @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * editor.cc + * + * Tue Nov 10 08:37:43 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include <QApplication> + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + MainWindow wnd; + wnd.show(); + + return app.exec(); +} diff --git a/src/dgedit.qrc b/src/dgedit.qrc new file mode 100644 index 0000000..d71c0a0 --- /dev/null +++ b/src/dgedit.qrc @@ -0,0 +1,7 @@ +<!DOCTYPE RCC> +<RCC version="1.0"> +<qresource> + <file>icons/master.png</file> + <file>icons/file.png</file> +</qresource> +</RCC> diff --git a/src/filelist.cc b/src/filelist.cc new file mode 100644 index 0000000..c4e5c4b --- /dev/null +++ b/src/filelist.cc @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * filelist.cc + * + * Mon Nov 30 15:35:52 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "filelist.h" + +#include <QFileDialog> +#include <QFileInfo> +#include <QMenu> + +#include "itemeditor.h" + +FileList::FileList() +{ + setContextMenuPolicy(Qt::CustomContextMenu); + + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(popupMenu(const QPoint &))); + + connect(this, SIGNAL(itemDoubleClicked(QListWidgetItem *)), + this, SLOT(selectionChanged(QListWidgetItem *))); + + createMenus(); +} + +void FileList::addFiles() +{ + QStringList files = QFileDialog::getOpenFileNames(this, tr("Open file"), + path, tr("Audio Files (*.wav)")); + QStringList::Iterator i = files.begin(); + while(i != files.end()) { + QString file = *i; + QFileInfo fi(file); + QString name = fi.baseName(); + path = fi.absolutePath(); + + QListWidgetItem *item = new QListWidgetItem(); + setItemFile(item, file); + setItemName(item, name); + setItemMaster(item, false); + addItem(item); + + emit fileAdded(file, name); + + i++; + } +} + +void FileList::setMasterFile(QListWidgetItem *i) +{ + QString filename = itemFile(i); + + for(int idx = 0; idx < count(); idx++) { + setItemMaster(item(idx), false); + } + + setItemMaster(i, true); + emit masterFileChanged(filename); +} + +void FileList::selectionChanged(QListWidgetItem *i) +{ + setMasterFile(i); +} + + +void FileList::createMenus() +{ + menu = new QMenu(); + + setMasterAction = new QAction("Set as Master (dbl-click)", this); + connect(setMasterAction, SIGNAL(triggered()), this, SLOT(setMaster())); + + editAction = new QAction("Edit name", this); + connect(editAction, SIGNAL(triggered()), this, SLOT(editName())); + + removeAction = new QAction("Remove", this); + connect(removeAction, SIGNAL(triggered()), this, SLOT(removeFile())); + + removeAllAction = new QAction("Remove all", this); + connect(removeAllAction, SIGNAL(triggered()), this, SLOT(removeAllFiles())); + + menu->addAction(setMasterAction); + menu->addAction(editAction); + menu->addAction(removeAction); + menu->addSeparator(); + menu->addAction(removeAllAction); + +} + +void FileList::popupMenu(const QPoint & pos) +{ + activeItem = itemAt(pos); + if(!activeItem) return; + menu->popup(mapToGlobal(pos)); +} + +void FileList::setMaster() +{ + setMasterFile(activeItem); +} + +void FileList::removeFile() +{ + QString file = itemFile(activeItem); + QString name = itemName(activeItem); + + printf("Removing: %s\n", file.toStdString().c_str()); + delete activeItem;//takeItem(row(activeItem)); + activeItem = NULL; + setCurrentRow(-1); + + emit fileRemoved(file, name); +} + +void FileList::removeAllFiles() +{ + activeItem = NULL; + + clear(); + + emit allFilesRemoved(); +} + +void FileList::editName() +{ + ItemEditor *e = new ItemEditor(activeItem, itemName(activeItem)); + connect(e, SIGNAL(updateItem(QListWidgetItem *, QString)), + this, SLOT(setItemName(QListWidgetItem *, QString))); +} + + +// Item utility functions. +QString FileList::itemFile(QListWidgetItem *i) +{ + return i->data(Qt::ToolTipRole).toString(); +} + +void FileList::setItemFile(QListWidgetItem *i, QString file) +{ + i->setData(Qt::ToolTipRole, file); + i->setData(Qt::DisplayRole, itemName(i) + "\t" + file); +} + +QString FileList::itemName(QListWidgetItem *i) +{ + return i->data(Qt::UserRole).toString(); +} + +void FileList::setItemName(QListWidgetItem *i, QString name) +{ + QString oldname = itemName(i); + + i->setData(Qt::UserRole, name); + i->setData(Qt::DisplayRole, name + "\t" + itemFile(i)); + + if(oldname != "" && oldname != name) emit nameChanged(itemFile(i), name); +} + +void FileList::setItemMaster(QListWidgetItem *i, bool master) +{ + if(master) i->setIcon(QPixmap(":icons/master.png")); + else i->setIcon(QPixmap(":icons/file.png")); +} diff --git a/src/filelist.h b/src/filelist.h new file mode 100644 index 0000000..2ca277c --- /dev/null +++ b/src/filelist.h @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * filelist.h + * + * Mon Nov 30 15:35:52 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_FILELIST_H__ +#define __DRUMGIZMO_FILELIST_H__ + +#include <QListWidget> +#include <QListWidgetItem> +#include <QAction> +#include <QMenu> + +class FileList : public QListWidget { +Q_OBJECT +public: + FileList(); + + QString path; +signals: + void masterFileChanged(QString filename); + void fileAdded(QString file, QString name); + void fileRemoved(QString file, QString name); + void allFilesRemoved(); + void nameChanged(QString file, QString name); + +public slots: + void addFiles(); + void popupMenu(const QPoint &pos); + +private slots: + void selectionChanged(QListWidgetItem *item); + void setMaster(); + void removeFile(); + void removeAllFiles(); + void editName(); + void setItemName(QListWidgetItem *i, QString name); + +private: + QString itemFile(QListWidgetItem *i); + QString itemName(QListWidgetItem *i); + void setItemFile(QListWidgetItem *i, QString file); + void setItemMaster(QListWidgetItem *i, bool master); + + void setMasterFile(QListWidgetItem *i); + void createMenus(); + + QMenu *menu; + QAction *setMasterAction; + QAction *editAction; + QAction *removeAction; + QAction *removeAllAction; + + QListWidgetItem *activeItem; +}; + +#endif/*__DRUMGIZMO_FILELIST_H__*/ diff --git a/src/itemeditor.cc b/src/itemeditor.cc new file mode 100644 index 0000000..1925048 --- /dev/null +++ b/src/itemeditor.cc @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * itemeditor.cc + * + * Tue Dec 1 11:01:40 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "itemeditor.h" + +ItemEditor::ItemEditor(QListWidgetItem *i, QString v) +{ + this->i = i; + setText(v); + show(); +} + +void ItemEditor::focusOutEvent(QFocusEvent *) +{ + emit updateItem(i, text()); + close(); +} diff --git a/src/itemeditor.h b/src/itemeditor.h new file mode 100644 index 0000000..b6b9e33 --- /dev/null +++ b/src/itemeditor.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * itemeditor.h + * + * Tue Dec 1 11:01:40 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_ITEMEDITOR_H__ +#define __DRUMGIZMO_ITEMEDITOR_H__ + +#include <QLineEdit> +#include <QString> +#include <QListWidgetItem> + +class ItemEditor : public QLineEdit { +Q_OBJECT +public: + ItemEditor(QListWidgetItem *i, QString v); + +protected: + void focusOutEvent(QFocusEvent *); + +signals: + void updateItem(QListWidgetItem *i, QString v); + +private: + QListWidgetItem *i; +}; + +#endif/*__DRUMGIZMO_ITEMEDITOR_H__*/ diff --git a/src/mainwindow.cc b/src/mainwindow.cc new file mode 100644 index 0000000..05562b6 --- /dev/null +++ b/src/mainwindow.cc @@ -0,0 +1,555 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * mainwindow.cc + * + * Tue Nov 10 10:21:04 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "mainwindow.h" + +#include <QHBoxLayout> +#include <QVBoxLayout> + +#include <QPushButton> +#include <QLabel> +#include <QStatusBar> +#include <QApplication> +#include <QDockWidget> +#include <QSettings> +#include <QToolBar> +#include <QAction> +#include <QMenuBar> +#include <QFileDialog> +#include <QIntValidator> +#include <QTabWidget> +#include <QProgressBar> +#include <QTime> +#include <QSpinBox> + +#include "sleep.h" +#include "canvastool.h" +#include "canvastoolthreshold.h" +#include "volumefader.h" +#include "selectioneditor.h" +#include "zoomslider.h" + + +#define MAXVAL 10000000L +/* +#define SINGLESTEP MAXVAL/100000 +#define PAGESTEP MAXVAL/10000 +*/ + +static void addTool(QToolBar *toolbar, Canvas *canvas, CanvasTool *tool) +{ + QAction *action = new QAction(tool->name(), toolbar); + action->setCheckable(true); + toolbar->addAction(action); + tool->connect(action, SIGNAL(toggled(bool)), tool, SLOT(setActive(bool))); + tool->setActive(false); + canvas->tools.push_back(tool); +} + +MainWindow::MainWindow() +{ + { + int start = 44100 * 60; + Selection p(start, start + 44100 * 60, 0, 0); // one minute selection + selections_preview.add(p); + } + + QWidget *central = new QWidget(); + QHBoxLayout *lh = new QHBoxLayout(); + QVBoxLayout *lv = new QVBoxLayout(); + central->setLayout(lv); + setCentralWidget(central); + + extractor = new AudioExtractor(selections, this); + //canvas = new Canvas(this); + canvaswidget = new CanvasWidget(this); + + QToolBar *toolbar = addToolBar("Tools"); + listen = new CanvasToolListen(canvaswidget->canvas, player); + addTool(toolbar, canvaswidget->canvas, listen); + threshold = new CanvasToolThreshold(canvaswidget->canvas); + canvaswidget->canvas->tools.push_back(threshold);//addTool(toolbar, canvaswidget->canvas, threshold); + tool_selections = new CanvasToolSelections(canvaswidget->canvas, selections, + selections_preview); + connect(threshold, SIGNAL(thresholdChanged(double)), + tool_selections, SLOT(thresholdChanged(double))); + connect(threshold, SIGNAL(thresholdChanging(double)), + tool_selections, SLOT(thresholdChanged(double))); + connect(&selections, SIGNAL(activeChanged(sel_id_t)), + canvaswidget->canvas, SLOT(update())); + connect(&selections, SIGNAL(updated(sel_id_t)), + canvaswidget->canvas, SLOT(update())); + addTool(toolbar, canvaswidget->canvas, tool_selections); + + QMenu *fileMenu = menuBar()->addMenu("&File"); + QAction *act_quit = new QAction("&Quit", this); + fileMenu->addAction(act_quit); + connect(act_quit, SIGNAL(triggered()), this, SLOT(close())); + + // QWidget *dock = new QWidget(); + /* + yoffset = new QScrollBar(Qt::Vertical); + yoffset->setRange(0, MAXVAL); + yoffset->setPageStep(PAGESTEP); + yoffset->setSingleStep(SINGLESTEP); + connect(yoffset, SIGNAL(valueChanged(int)), this, SLOT(setYOffset(int))); + + yscale = new ZoomSlider(Qt::Vertical); + yscale->setRange(0.9, 30); + yscale->setTickWidth(0.1); + connect(yscale, SIGNAL(valueChanged(float)), this, SLOT(setYScale(float))); + + xscale = new ZoomSlider(Qt::Horizontal); + xscale->setRange(1, 0.0001); + xscale->setTickWidth(0.0001); + connect(xscale, SIGNAL(valueChanged(float)), this, SLOT(setXScale(float))); + + xoffset = new QScrollBar(Qt::Horizontal); + xoffset->setRange(0, MAXVAL); + xoffset->setPageStep(PAGESTEP); + xoffset->setSingleStep(SINGLESTEP); + connect(xoffset, SIGNAL(valueChanged(int)), this, SLOT(setXOffset(int))); + */ + sorter = new SampleSorter(selections, selections_preview); + connect(&selections, SIGNAL(added(sel_id_t)), + sorter, SLOT(addSelection(sel_id_t))); + connect(&selections_preview, SIGNAL(added(sel_id_t)), + sorter, SLOT(addSelectionPreview(sel_id_t))); + connect(&selections, SIGNAL(updated(sel_id_t)), sorter, SLOT(relayout())); + connect(&selections_preview, SIGNAL(updated(sel_id_t)), + sorter, SLOT(relayout())); + connect(&selections, SIGNAL(removed(sel_id_t)), sorter, SLOT(relayout())); + connect(&selections_preview, SIGNAL(removed(sel_id_t)), + sorter, SLOT(relayout())); + connect(&selections, SIGNAL(activeChanged(sel_id_t)), + sorter, SLOT(relayout())); + + QPushButton *btn_playsamples = new QPushButton("Play samples"); + connect(btn_playsamples, SIGNAL(clicked()), this, SLOT(playSamples())); + + sb_playsamples = new QScrollBar(Qt::Horizontal); + sb_playsamples->setRange(100, 4000); // ms + + + lh->addWidget(canvaswidget); + //lh->addWidget(yscale); + //lh->addWidget(yoffset); + lv->addLayout(lh, 100); + //lv->addWidget(xscale, 100); + //lv->addWidget(xoffset, 100); + lv->addWidget(sorter, 15); + lv->addWidget(btn_playsamples); + lv->addWidget(sb_playsamples); + + + QDockWidget *dockWidget = new QDockWidget(tr("Dock Widget"), this); + dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + + dockWidget->setWidget(new QWidget()); + dockWidget->widget()->setLayout(new QVBoxLayout()); + +// dockWidget->widget()->layout()->addWidget(new QLabel("Presets:")); +// presets = new QComboBox(); +// connect(presets, SIGNAL(currentIndexChanged(int)), +// this, SLOT(setPreset(int))); +// dockWidget->widget()->layout()->addWidget(presets); + + tabs = new QTabWidget(this); + tabs->addTab(createFilesTab(), "Files"); + generateTabId = tabs->addTab(createGenerateTab(), "Generate"); + tabs->addTab(createEditTab(), "Edit"); + tabs->addTab(createExportTab(), "Export"); + connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); + tabChanged(tabs->currentIndex()); + + dockWidget->widget()->layout()->addWidget(tabs); + + VolumeFader *vol = new VolumeFader(); + connect(vol, SIGNAL(volumeChangedDb(double)), + &player, SLOT(setGainDB(double))); + connect(&player, SIGNAL(peakUpdate(double)), + vol, SLOT(updatePeakPower(double))); +// connect(&player, SIGNAL(peakUpdateDB(double)), +// vol, SLOT(updatePeakDb(double))); + + vol->setVolumeDb(0); + dockWidget->widget()->layout()->addWidget(vol); + + addDockWidget(Qt::LeftDockWidgetArea, dockWidget); + + canvaswidget->yscale->setValue(0.9); + canvaswidget->yoffset->setValue(MAXVAL/2); + canvaswidget->xscale->setValue(0); + canvaswidget->xoffset->setValue(0); + + loadSettings(); + +/* + QSettings settings("presets.ini", QSettings::IniFormat); + QStringList list = settings.childGroups(); + for(int i = 0; i != list.size(); i++) { + QString presetname = list.at(i); + Preset p; + settings.beginGroup(presetname); + p.prefix = settings.value("prefix", "unknown").toString(); + p.attacklength = settings.value("attacklength", 0).toInt(); + p.falloff = settings.value("falloff", 0).toInt(); + p.fadelength = settings.value("fadelength", 0).toInt(); + settings.endGroup(); + QVariant v; + v.setValue(p); + presets->addItem(presetname, v); + } +*/ + + statusBar()->showMessage("Ready"); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::tabChanged(int tabid) +{ + tool_selections->setShowPreview(tabid == generateTabId); + sorter->setShowPreview(tabid == generateTabId); + tool_selections->autoCreateSelectionsPreview(); + threshold->setActive(tabid == generateTabId); +} + +QWidget *MainWindow::createFilesTab() +{ + QWidget *w = new QWidget(); + QVBoxLayout *l = new QVBoxLayout(); + w->setLayout(l); + + l->addWidget(new QLabel("Files: (double-click to set as master)")); + QPushButton *loadbtn = new QPushButton(); + loadbtn->setText("Add files..."); + l->addWidget(loadbtn); + + filelist = new FileList(); + connect(filelist, SIGNAL(masterFileChanged(QString)), + this, SLOT(loadFile(QString))); + connect(loadbtn, SIGNAL(clicked()), filelist, SLOT(addFiles())); + connect(filelist, SIGNAL(fileAdded(QString, QString)), + extractor, SLOT(addFile(QString, QString))); + connect(filelist, SIGNAL(fileRemoved(QString, QString)), + extractor, SLOT(removeFile(QString, QString))); + connect(filelist, SIGNAL(nameChanged(QString, QString)), + extractor, SLOT(changeName(QString, QString))); + l->addWidget(filelist); + + return w; +} + +QWidget *MainWindow::createEditTab() +{ + SelectionEditor *se = new SelectionEditor(selections); + + connect(&selections, SIGNAL(added(sel_id_t)), se, SLOT(added(sel_id_t))); + connect(&selections, SIGNAL(updated(sel_id_t)), se, SLOT(updated(sel_id_t))); + connect(&selections, SIGNAL(removed(sel_id_t)), se, SLOT(removed(sel_id_t))); + connect(&selections, SIGNAL(activeChanged(sel_id_t)), + se, SLOT(activeChanged(sel_id_t))); + + return se; +} + +QSlider *createAttribute(QWidget *parent, QString name, + int range_from, int range_to) +{ + QSlider *slider; + + QGridLayout *l = new QGridLayout(); + + l->addWidget(new QLabel(name), 0, 0, 1, 2); + + QSpinBox *spin = new QSpinBox(); + spin->setRange(range_from, range_to); + l->addWidget(spin, 1, 0, 1, 1); + + slider = new QSlider(Qt::Horizontal); + slider->setRange(range_from, range_to); + l->addWidget(slider, 1, 1, 1,1); + + QObject::connect(spin, SIGNAL(valueChanged(int)), + slider, SLOT(setValue(int))); + QObject::connect(slider, SIGNAL(valueChanged(int)), + spin, SLOT(setValue(int))); + + ((QBoxLayout *)parent->layout())->addLayout(l); + + return slider; +} + +QWidget *MainWindow::createGenerateTab() +{ + QWidget *w = new QWidget(); + QVBoxLayout *l = new QVBoxLayout(); + w->setLayout(l); + + QHBoxLayout *btns = new QHBoxLayout(); + + QPushButton *autosel = new QPushButton(); + autosel->setText("Generate"); + connect(autosel, SIGNAL(clicked()), + tool_selections, SLOT(clearSelections())); + connect(autosel, SIGNAL(clicked()), + tool_selections, SLOT(autoCreateSelections())); + + connect(threshold, SIGNAL(thresholdChanged(double)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + connect(threshold, SIGNAL(thresholdChanging(double)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + + QPushButton *clearsel = new QPushButton(); + clearsel->setText("Clear"); + connect(clearsel, SIGNAL(clicked()), + tool_selections, SLOT(clearSelections())); + + btns->addWidget(autosel); + btns->addWidget(clearsel); + + l->addLayout(btns); + + slider_attacklength = createAttribute(w, "Attack length:", 10, 1000); + connect(slider_attacklength, SIGNAL(valueChanged(int)), + sorter, SLOT(setAttackLength(int))); + connect(slider_attacklength, SIGNAL(valueChanged(int)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + slider_attacklength->setValue(300); + + slider_hold = createAttribute(w, "Minimum size (samples):", 0, 200000); + connect(slider_hold, SIGNAL(valueChanged(int)), + tool_selections, SLOT(holdChanged(int))); + connect(slider_hold, SIGNAL(valueChanged(int)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + slider_hold->setValue(100); + + slider_falloff = createAttribute(w, "Falloff:", 10, 5000); + connect(slider_falloff, SIGNAL(valueChanged(int)), + tool_selections, SLOT(noiseFloorChanged(int))); + connect(slider_falloff, SIGNAL(valueChanged(int)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + slider_falloff->setValue(300); + + slider_fadelength = createAttribute(w, "Fadelength:", 0, 2000); + connect(slider_fadelength, SIGNAL(valueChanged(int)), + tool_selections, SLOT(fadeoutChanged(int))); + connect(slider_fadelength, SIGNAL(valueChanged(int)), + tool_selections, SLOT(autoCreateSelectionsPreview())); + slider_fadelength->setValue(666); + + l->addStretch(); + + return w; +} + +QWidget *MainWindow::createExportTab() +{ + QWidget *w = new QWidget(); + QVBoxLayout *l = new QVBoxLayout(); + w->setLayout(l); + + l->addWidget(new QLabel("Prefix:")); + prefix = new QLineEdit(); + connect(prefix, SIGNAL(textChanged(const QString &)), + extractor, SLOT(setOutputPrefix(const QString &))); + l->addWidget(prefix); + + l->addWidget(new QLabel("Export path:")); + QHBoxLayout *lo_exportp = new QHBoxLayout(); + lineed_exportp = new QLineEdit(); + connect(lineed_exportp, SIGNAL(textChanged(const QString &)), + extractor, SLOT(setExportPath(const QString &))); + lo_exportp->addWidget(lineed_exportp); + QPushButton *btn_browse = new QPushButton("..."); + connect(btn_browse, SIGNAL(clicked()), this, SLOT(browse())); + lo_exportp->addWidget(btn_browse); + + l->addLayout(lo_exportp); + + QPushButton *exportsel = new QPushButton(); + exportsel->setText("Export"); + connect(exportsel, SIGNAL(clicked()), this, SLOT(doExport())); + l->addWidget(exportsel); + + QProgressBar *bar = new QProgressBar(); + connect(extractor, SIGNAL(progressUpdate(int)), bar, SLOT(setValue(int))); + connect(extractor, SIGNAL(setMaximumProgress(int)), + bar, SLOT(setMaximum(int))); + l->addWidget(bar); + + l->addStretch(); + + return w; +} + +void MainWindow::playSamples() +{ + Selections *sels = &selections; + if(tabs->currentIndex() == generateTabId) sels = &selections_preview; + + QVector<sel_id_t> ids = sels->ids(); + for(int v1 = 0; v1 < ids.size(); v1++) { + for(int v2 = 0; v2 < ids.size(); v2++) { + + Selection sel1 = sels->get(ids[v1]); + Selection sel2 = sels->get(ids[v2]); + + if(sel1.energy < sel2.energy) { + sel_id_t vtmp = ids[v1]; + ids[v1] = ids[v2]; + ids[v2] = vtmp; + } + } + } + + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = sels->get(*i); + + unsigned int length = sb_playsamples->value() * 44100 / 1000; + + unsigned int sample_length = sel.to - sel.from; + + unsigned int to = sel.to; + + if(sample_length > length) to = sel.from + length; + + sels->setActive(*i); + + connect(&player, SIGNAL(positionUpdate(size_t)), + listen, SLOT(update(size_t))); + + player.playSelection(sel, to - sel.from); + QTime t; + t.start(); + while(t.elapsed() < sb_playsamples->value()) { + qApp->processEvents(); + q_usleep(25 * 1000); + } + player.stop(); + + disconnect(&player, SIGNAL(positionUpdate(size_t)), + listen, SLOT(update(size_t))); + i++; + } +} + +void MainWindow::closeEvent(QCloseEvent *) +{ + saveSettings(); + QApplication::quit(); +} + +void MainWindow::loadSettings() +{ + QSettings settings; + + settings.beginGroup("MainWindow"); + lineed_exportp->setText(settings.value("exportpath", "").toString()); + resize(settings.value("size", QSize(700, 800)).toSize()); + move(settings.value("pos", QPoint(0, 0)).toPoint()); + settings.endGroup(); +} + +void MainWindow::saveSettings() +{ + QSettings settings; + + settings.beginGroup("MainWindow"); + settings.setValue("exportpath", lineed_exportp->text()); + settings.setValue("size", size()); + settings.setValue("pos", pos()); + settings.endGroup(); +} +/* +void MainWindow::setXScale(float val) +{ + canvaswidget->canvas->setXScale(val); +} + +void MainWindow::setYScale(float val) +{ + canvaswidget->canvas->setYScale(val); +} + +void MainWindow::setXOffset(int of) +{ + // range 0.0 - 1.0 + float val = (float)of/(float)MAXVAL; + canvaswidget->canvas->setXOffset(val); +} + +void MainWindow::setYOffset(int of) +{ + // range 0.0 - 1.0 + float val = (float)(of * -1 + MAXVAL)/(float)MAXVAL; + canvaswidget->canvas->setYOffset(val); +} +*/ +void MainWindow::doExport() +{ + extractor->exportSelections(); +} + +void MainWindow::loadFile(QString filename) +{ + setCursor(Qt::WaitCursor); + statusBar()->showMessage("Loading..."); + qApp->processEvents(); + + sorter->setWavData(NULL, 0); + player.setPcmData(NULL, 0); + + canvaswidget->canvas->load(filename); + + sorter->setWavData(canvaswidget->canvas->data, canvaswidget->canvas->size); + player.setPcmData(canvaswidget->canvas->data, canvaswidget->canvas->size); + + statusBar()->showMessage("Ready"); + setCursor(Qt::ArrowCursor); +} + +void MainWindow::setPreset(int index) +{ + /* + QVariant v = presets->itemData(index); + Preset p = v.value<Preset>(); + slider_attacklength->setValue(p.attacklength); + slider_falloff->setValue(p.falloff); + slider_fadelength->setValue(p.fadelength); + prefix->setText(p.prefix); + */ +} + +void MainWindow::browse() { + QString path = QFileDialog::getExistingDirectory(this, "Select export path", + lineed_exportp->text()); + lineed_exportp->setText(path); +} diff --git a/src/mainwindow.h b/src/mainwindow.h new file mode 100644 index 0000000..69a4c5e --- /dev/null +++ b/src/mainwindow.h @@ -0,0 +1,124 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * mainwindow.h + * + * Tue Nov 10 10:21:03 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_MAINWINDOW_H__ +#define __DRUMGIZMO_MAINWINDOW_H__ + +#include <QMainWindow> +#include <QScrollBar> +#include <QComboBox> +#include <QSlider> +#include <QLineEdit> +#include <QCloseEvent> +#include <QTabWidget> + +#include "canvas.h" +#include "audioextractor.h" +#include "samplesorter.h" +#include "filelist.h" +#include "canvastoolselections.h" +#include "canvastoolthreshold.h" +#include "canvastoollisten.h" +#include "selection.h" +#include "player.h" +#include "zoomslider.h" +#include "canvaswidget.h" + +class Preset { +public: + QString prefix; + int attacklength; + int falloff; + int fadelength; +}; +Q_DECLARE_METATYPE(Preset) + +class MainWindow : public QMainWindow { +Q_OBJECT +public: + MainWindow(); + ~MainWindow(); + +public slots: + /* + void setXScale(float); + void setYScale(float); + void setXOffset(int); + void setYOffset(int); + */ + void doExport(); + void loadFile(QString filename); + void playSamples(); + void setPreset(int); + void browse(); + void tabChanged(int tabid); + +protected: + void closeEvent(QCloseEvent*); + +private: + void loadSettings(); + void saveSettings(); + + QWidget *createFilesTab(); + QWidget *createEditTab(); + QWidget *createGenerateTab(); + QWidget *createExportTab(); + + int generateTabId; + + SampleSorter *sorter; + CanvasToolSelections *tool_selections; + CanvasToolThreshold *threshold; + CanvasToolListen *listen; + AudioExtractor *extractor; + FileList *filelist; + + //Canvas *canvas; + //QScrollBar *yoffset; + //ZoomSlider *yscale; + //ZoomSlider *xscale; + //QScrollBar *xoffset; + CanvasWidget *canvaswidget; + + QScrollBar *sb_playsamples; + QComboBox *presets; + QSlider *slider_attacklength; + QSlider *slider_hold; + QSlider *slider_falloff; + QSlider *slider_fadelength; + QLineEdit *prefix; + QLineEdit *lineed_exportp; + + QTabWidget *tabs; + + // Session state information: + Selections selections; + Selections selections_preview; + Player player; +}; + +#endif/*__DRUMGIZMO_MAINWINDOW_H__*/ diff --git a/src/mipmap.cc b/src/mipmap.cc new file mode 100644 index 0000000..09b15b6 --- /dev/null +++ b/src/mipmap.cc @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * mipmap.cc + * + * Fri Sep 3 16:39:46 CEST 2010 + * Copyright 2010 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "mipmap.h" + +MipMap::MipMap(float *data, size_t size) +{ + this->data = data; + this->size = size; + this->zoom = 1; +} + +MipMapValue MipMap::data_lookup(size_t begin, size_t end) +{ + MipMapValue val; + + size_t numlavg = 0; + size_t numuavg = 0; + for(size_t i = begin; i <= end; i++) { + if(i > size || i < 0) break; + if(data[i] > val.max) val.max = data[i]; + if(data[i] < val.min) val.min = data[i]; + + if(data[i] > 0) { val.uavg += data[i]; numuavg++; } + if(data[i] < 0) { val.lavg += data[i]; numlavg++; } + } + + if(numlavg) val.lavg /= (float) numlavg; + if(numuavg) val.uavg /= (float) numuavg; + + return val; +} + +MipMapValue MipMap::mipmap_lookup(size_t begin, size_t end) +{ + MipMapValue val; + + size_t numlavg = 0; + size_t numuavg = 0; + for(size_t i = begin; i <= end; i++) { + if(i > size || i < 0) break; + if(data[i] > val.max) val.max = data[i]; + if(data[i] < val.min) val.min = data[i]; + + if(data[i] > 0) { val.uavg += data[i]; numuavg++; } + if(data[i] < 0) { val.lavg += data[i]; numlavg++; } + } + + if(numlavg) val.lavg /= (float) numlavg; + if(numuavg) val.uavg /= (float) numuavg; + + return val; +} + +#define ABS(x) (x>0?x:-x) + +MipMapValue MipMap::lookup(size_t begin, size_t end) +{ + return data_lookup(begin, end); + /* + + size_t zoom_factor = ABS(end - begin); + + if(zoom_factor < zoom / 2) { + if(zoom == 1) { // Lookup in original data. + return data_lookup(begin, end); + } + + return mipmap_lookup(begin, end); + } + + if(lowerlevel) return lowerlevel->lookup(begin,end); + + return MipMapValue(); + */ +} diff --git a/src/mipmap.h b/src/mipmap.h new file mode 100644 index 0000000..550d6ae --- /dev/null +++ b/src/mipmap.h @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * mipmap.h + * + * Fri Sep 3 16:39:45 CEST 2010 + * Copyright 2010 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_MIPMAP_H__ +#define __DRUMGIZMO_MIPMAP_H__ + +#include <QMap> +#include <stddef.h> + +class MipMapValue { +public: + MipMapValue() { max = min = uavg = lavg = 0.0; } + float max; + float min; + float uavg; + float lavg; +}; + +class MipMap { +public: + MipMap(float *data, size_t size); + + MipMapValue lookup(size_t begin, size_t end); + +private: + float *data; + size_t size; + + MipMapValue *values; + + size_t zoom; + + MipMapValue data_lookup(size_t begin, size_t end); + MipMapValue mipmap_lookup(size_t begin, size_t end); + + MipMap *lowerlevel; +}; + +#endif/*__DRUMGIZMO_MIPMAP_H__*/ diff --git a/src/player.cc b/src/player.cc new file mode 100644 index 0000000..3a2bfd2 --- /dev/null +++ b/src/player.cc @@ -0,0 +1,190 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * player.cc + * + * Tue Apr 15 10:34:18 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "player.h" + +#include <math.h> + +#define BUFSZ 512 + +Player::Player() +{ + peak = 0; + pos = 0; + gain_scalar = 1.0; + pcm_data = NULL; + pcm_size = 0; + end = 0; + new_selection = false; + + connect(&report_timer, SIGNAL(timeout()), this, SLOT(reportTimeout())); + report_timer.start(50); // Update 25 times per second + + start(); +} + +Player::~Player() +{ + running = false; // Signal player thread to stop + wait(); // Wait for player thread to stop. +} + +#define _MIN(a, b) (a<b?a:b) +void Player::run() +{ + Selection sel; + + ao_initialize(); + + ao_sample_format sf; + memset(&sf, 0, sizeof(sf)); + sf.bits = 16; + sf.rate = 44100; + sf.channels = 1; + sf.byte_format = AO_FMT_NATIVE; + + dev = ao_open_live(ao_default_driver_id(), &sf, 0); + + running = true; + + short s[BUFSZ]; + while(running) { + + { // Check for new Selection. + QMutexLocker lock(&mutex); + if(new_selection) { + sel = selection; + pos = sel.from; + end = sel_end; + new_selection = false; + } + } + + for(size_t i = 0; i < BUFSZ; i++) { + double sample = 0.0; + size_t p = i + pos; + if(p < sel.to && p < end && p < pcm_size) { + double fade = 1; + if(p < (sel.from + sel.fadein)) { + // Apply linear fade-in + double fp = (double)((int)p - (int)sel.from); + fade = fp / (double)sel.fadeout; + } + + if(p > (sel.to - sel.fadeout)) { + // Apply linear fade-out + double fp = (double)(((int)sel.to - (int)sel.fadeout) - (int)p); + fade = 1 + (fp / (double)sel.fadeout); + } + + sample = pcm_data[p] * fade * gain_scalar; + } + if(fabs(sample) > peak) { + peak = fabs(sample); + } + s[i] = _MIN(sample * SHRT_MAX, SHRT_MAX); + } + + ao_play(dev, (char*)s, BUFSZ * sizeof(short)); + + pos += BUFSZ; + } + + ao_close(dev); + ao_shutdown(); +} + +bool Player::playSelectionDone() +{ + return pos >= sel_end || pos >= selection.to; +} + +void Player::playSelection(Selection s, int len) +{ + { // Enqueue new Selection for player consumation + QMutexLocker lock(&mutex); + + selection = s; + + if(len > 0) sel_end = len; + else sel_end = selection.to - selection.from; + + sel_end += selection.from; + + new_selection = true; + } + + // Wait until player actually consumed the new Selection. + while(new_selection) { + msleep(1); + } +} + +void Player::setGainScalar(double g) +{ + gain_scalar = g; +} + +void Player::setGainDB(double gain_db) +{ + setGainScalar(pow(10, gain_db/ 20.0)); +} + +void Player::reportTimeout() +{ + emit peakUpdate(peak); + emit peakUpdateDB(20 * log10(peak)); + peak = 0.0; + + emit positionUpdate(pos); + peak = 0.0; +} + +void Player::setPcmData(float *data, size_t size) +{ + pcm_data = data; + pcm_size = size; +} + +void Player::setPosition(size_t position) +{ + Selection s; + s.from = position; + s.to = pcm_size; + s.fadein = 0; + s.fadeout = 0; + playSelection(s); +} + +void Player::stop() +{ + Selection s; + s.from = 0; + s.to = 0; + s.fadein = 0; + s.fadeout = 0; + playSelection(s, pos); +} diff --git a/src/player.h b/src/player.h new file mode 100644 index 0000000..60b2ccb --- /dev/null +++ b/src/player.h @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * player.h + * + * Tue Apr 15 10:34:18 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_PLAYER_H__ +#define __DRUMGIZMO_PLAYER_H__ + +#include <QThread> +#include <QTimer> +#include <QMutex> + +#include <ao/ao.h> + +#include "selection.h" + +class Player : public QThread { +Q_OBJECT +public: + Player(); + ~Player(); + + void run(); + + // TODO: Make these private. + // These two need to be public in order for the ugly hack in + // CanvasToolListen::playRange to work... + // volatile bool playing; + volatile size_t pos; + volatile size_t end; + +public slots: + /** + * Assign PCM data to the player. + */ + void setPcmData(float *data, size_t num_samples); + + /** + * Set gain scalar. + * This value is multiplied with each sample before it is played. + */ + void setGainScalar(double gain_scalar); + + /** + * Set gain is dB. + * Convenience method for setGainScalar. It simple recalculates the dB value + * to a scalar and sets the gain scalar accordingly. + */ + void setGainDB(double gain_db); + + /** + * Set player position as sample offset. + */ + void setPosition(size_t position); + + /** + * Play range based on selection including fade-in/out. + * @param length Stop playing after length samples. -1 means play all. + */ + void playSelection(Selection selection, int length = -1); + + /** + * Return true if last selection is done playing. + */ + bool playSelectionDone(); + + /** + * Stop playing + */ + void stop(); + +signals: + /** + * The absolute maximum of samples seen since last update. + */ + void peakUpdate(double peak); + + /** + * The absolute maximum of samples seen since last update in dB. + */ + void peakUpdateDB(double peak_db); + + /** + * The sample position of the player. + */ + void positionUpdate(size_t position); + +private slots: + void reportTimeout(); + +private: + ao_device *dev; + + float *pcm_data; + size_t pcm_size; + + QTimer report_timer; + + double gain_scalar; + double peak; + + bool running; + + QMutex mutex; + volatile bool new_selection; + size_t sel_end; + Selection selection; +}; + +#endif/*__DRUMGIZMO_PLAYER_H__*/ diff --git a/src/samplesorter.cc b/src/samplesorter.cc new file mode 100644 index 0000000..00139e2 --- /dev/null +++ b/src/samplesorter.cc @@ -0,0 +1,271 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * samplesorter.cc + * + * Mon Nov 30 07:45:58 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "samplesorter.h" + +#include <QPainter> +#include <QPaintEvent> + +#include <stdio.h> + +#include <math.h> +#ifndef MAXFLOAT +#define MAXFLOAT (3.40282347e+38F) +#endif + +SampleSorter::SampleSorter(Selections &s, Selections &p) + : selections(s), selections_preview(p) +{ + setMouseTracking(true); + + data = NULL; + size = 0; + attlen = 666; // Magical constants needs biblical proportions... + + sel_moving = SEL_NONE; +} + +void SampleSorter::setShowPreview(bool s) +{ + show_preview = s; + update(); +} + +void SampleSorter::setWavData(const float *data, size_t size) +{ + this->data = data; + this->size = size; + relayout(); +} + +int SampleSorter::attackLength() +{ + return attlen; +} + +void SampleSorter::setAttackLength(int len) +{ + attlen = len; + relayout(); +} + +void SampleSorter::addSelection(sel_id_t id) +{ + Selection s = selections.get(id); + + double energy = 0.0; + for(size_t idx = s.from; + (idx < (size_t)s.from + (size_t)attackLength()) && + (idx < (size_t)s.to) && (idx < size); + idx++) { + energy += data[idx] * data[idx]; + } + + s.energy = energy; + selections.update(id, s); + + relayout(); +} + +void SampleSorter::addSelectionPreview(sel_id_t id) +{ + Selection s = selections_preview.get(id); + + double energy = 0.0; + for(size_t idx = s.from; + (idx < (size_t)s.from + (size_t)attackLength()) && + (idx < (size_t)s.to) && (idx < size); + idx++) { + energy += data[idx] * data[idx]; + } + + s.energy = energy; + selections_preview.update(id, s); + + relayout(); +} + +void SampleSorter::relayout() +{ + min = MAXFLOAT; + max = 0.0; + + { + QVector<sel_id_t> ids = selections.ids(); + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + + if(sel.energy < min) min = sel.energy; + if(sel.energy > max) max = sel.energy; + + i++; + } + } + + if(show_preview) { + QVector<sel_id_t> ids = selections_preview.ids(); + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections_preview.get(*i); + + if(sel.energy < min) min = sel.energy; + if(sel.energy > max) max = sel.energy; + + i++; + } + } + + update(); +} + +#define MAP(p) (height()-(int)(p*((float)height()/(float)width()))) + +#define unmapX(x) ((double)x/(double)(width()-1)) +#define unmapY(x) x +#define mapX(x) (((double)x)*(width()-1)) +#define mapY(x) x + +#define C_RADIUS 2 +static void drawCircle(QPainter &p, int x, int y) +{ + p.drawEllipse(x - C_RADIUS, y - C_RADIUS, 2 * C_RADIUS, 2 * C_RADIUS); +} + +void SampleSorter::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + + QColor colBg = QColor(180, 200, 180, 160); + QColor colFg = QColor(160, 180, 160, 160); + QColor colPt = QColor(255, 100, 100, 160); + QColor colPtPreview = QColor(0, 0, 255, 160); + QColor colPtSel = QColor(255, 255, 100, 160); + + painter.setPen(colBg); + painter.setBrush(colBg); + painter.drawRect(event->rect()); + + painter.setPen(colFg); + painter.drawLine(0,height(),width(),0); + + { + QVector<sel_id_t> ids = selections.ids(); + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + if(*i == selections.active()) painter.setPen(colPtSel); + else painter.setPen(colPt); + float x = sel.energy / max; + x = sqrt(x); + x *= (float)width(); + drawCircle(painter, x, MAP(x)); + i++; + } + } + + if(show_preview) { + QVector<sel_id_t> ids = selections_preview.ids(); + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections_preview.get(*i); + painter.setPen(colPtPreview); + float x = sel.energy / max; + x = sqrt(x); + x *= (float)width(); + drawCircle(painter, x, MAP(x)); + i++; + } + } + + +} + +sel_id_t SampleSorter::getSelectionByCoordinate(int px, int py) +{ + // Hit radius is slithly larger than the circles themselves. + int hit_r = C_RADIUS + 1; + + QVector<sel_id_t> ids = selections.ids(); + QVector<sel_id_t>::iterator i = ids.begin(); + while(i != ids.end()) { + Selection sel = selections.get(*i); + float x = (sel.energy/max); + x = sqrt(x); + x *= (float)width(); + if(px < (x + hit_r) && px > (x - hit_r) && + py < (MAP(x) + hit_r) && py > (MAP(x) - hit_r)) { + return *i; + } + i++; + } + + return SEL_NONE; +} + +void SampleSorter::mouseMoveEvent(QMouseEvent *event) +{ + if(sel_moving != SEL_NONE) { + Selection sel = selections.get(sel_moving); + if(sel_moving != SEL_NONE) { + double power = unmapX(event->x()); + power *= power; + power *= max; + sel.energy = power; + selections.update(sel_moving, sel); + } + + update(); + return; + } else { + sel_id_t psel = getSelectionByCoordinate(event->x(), event->y()); + if(psel != SEL_NONE) { + setCursor(Qt::UpArrowCursor); + } else { + setCursor(Qt::ArrowCursor); + } + } +} + +void SampleSorter::mousePressEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) { + sel_id_t psel = getSelectionByCoordinate(event->x(), event->y()); + sel_moving = psel; + selections.setActive(psel); + if(psel != SEL_NONE) { + setCursor(Qt::UpArrowCursor); + } + } +} + +void SampleSorter::mouseReleaseEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) { + sel_moving = SEL_NONE; + setCursor(Qt::ArrowCursor); + } +} diff --git a/src/samplesorter.h b/src/samplesorter.h new file mode 100644 index 0000000..ada7fd8 --- /dev/null +++ b/src/samplesorter.h @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * samplesorter.h + * + * Mon Nov 30 07:45:58 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_SAMPLESORTER_H__ +#define __DRUMGIZMO_SAMPLESORTER_H__ + +#include <QWidget> +#include <QVector> +#include "selection.h" + +class SampleSorter : public QWidget { +Q_OBJECT +public: + SampleSorter(Selections &selections, Selections &selections_preview); + +public slots: + void setWavData(const float *data, size_t size); + void setAttackLength(int len); + int attackLength(); + + void addSelection(sel_id_t id); + void addSelectionPreview(sel_id_t id); + + void relayout(); + + void setShowPreview(bool show_preview); + +protected: + void paintEvent(QPaintEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +private: + sel_id_t getSelectionByCoordinate(int x, int y); + + Selections &selections; + Selections &selections_preview; + + bool show_preview; + + float min; + float max; + int attlen; + + // Wav data + const float *data; + size_t size; + + Selection sel; + + sel_id_t sel_moving; +}; + +#endif/*__DRUMGIZMO_SAMPLESORTER_H__*/ diff --git a/src/selection.cc b/src/selection.cc new file mode 100644 index 0000000..c0300a4 --- /dev/null +++ b/src/selection.cc @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * selection.cc + * + * Mon Apr 14 10:13:21 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "selection.h" + +Selections::Selections() + : QObject(NULL) +{ + nextid = 0; + act = SEL_NONE; +} + +sel_id_t Selections::add(Selection selection) +{ + sel_id_t id = nextid++; + sels[id] = selection; + added(id); + return id; +} + +Selection Selections::get(sel_id_t id) +{ + if(sels.find(id) == sels.end()) { + Selection s(0,0,0,0); + return s; + } + return sels[id]; +} + +QVector<sel_id_t> Selections::ids() +{ + QVector<sel_id_t> v; + + QMap<sel_id_t, Selection>::iterator i = sels.begin(); + while(i != sels.end()) { + v.push_back(i.key()); + i++; + } + + return v; +} + +void Selections::update(sel_id_t id, Selection selection) +{ + if(sels.find(id) != sels.end()) { + sels[id] = selection; + emit updated(id); + } +} + +void Selections::remove(sel_id_t id) +{ + if(sels.find(id) != sels.end()) { + sels.erase(sels.find(id)); + if(id == act) setActive(SEL_NONE); + emit removed(id); + } +} + +void Selections::clear() +{ + QVector<sel_id_t> _ids = ids(); + QVector<sel_id_t>::iterator i = _ids.begin(); + while(i != _ids.end()) { + remove(*i); + i++; + } +} + +void Selections::setActive(sel_id_t id) +{ + if(sels.find(id) != sels.end()) { + act = id; + } else { + act = SEL_NONE; + } + emit activeChanged(act); +} + +sel_id_t Selections::active() +{ + return act; +} diff --git a/src/selection.h b/src/selection.h new file mode 100644 index 0000000..c6c7ecc --- /dev/null +++ b/src/selection.h @@ -0,0 +1,135 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * selection.h + * + * Sat Nov 21 13:20:46 CET 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_SELECTION_H__ +#define __DRUMGIZMO_SELECTION_H__ + +#include <QObject> + +#include <QMap> +#include <QVector> + +class Selection { +public: + Selection(int from = 0, int to = 0, int fadein = 0, int fadeout = 0) { + this->from = from; + this->to = to; + this->fadein = fadein; + this->fadeout = fadeout; + } + size_t from; + size_t to; + size_t fadein; + size_t fadeout; + + double energy; + + QString name; +}; + +typedef int sel_id_t; +#define SEL_NONE -1 + +class Selections : public QObject { +Q_OBJECT +public: + Selections(); + + /** + * Add a new selection object. The new id is returned. + * Adding a new selections will emit an added signal with the new id. + */ + sel_id_t add(Selection selection); + + /** + * Get a stack copy of a specific selection object, by id. + * NOTE: If id does not exist an empty selection (from = to = 0) is + * returned. + */ + Selection get(sel_id_t id); + + /** + * Return vector (unsorted) of all ids in the object. + */ + QVector<sel_id_t> ids(); + + /** + * Set active selection (to be rendered yellow) + */ + void setActive(sel_id_t id); + + /** + * Get active selection id. + */ + sel_id_t active(); + +public slots: + /** + * Update a selection by id. + * Updating a selection will emit a updated signal. + */ + void update(sel_id_t id, Selection selection); + + /** + * Delete a selection by id. + * Deleting a selection will emit a deleted signal. + */ + void remove(sel_id_t id); + + /** + * Delete all selections + */ + void clear(); + +signals: + /** + * This signal is emitted when a new selection has been added. + */ + void added(sel_id_t id); + + /** + * This signal is emitted when an existing selection has been updated. + */ + void updated(sel_id_t id); + + /** + * This signal is emitted when a selection has been removed. + */ + void removed(sel_id_t id); + + /** + * The active selection changed. + */ + void activeChanged(sel_id_t id); + +private: + QMap<sel_id_t, Selection> sels; + sel_id_t nextid; + sel_id_t act; +}; + + +#endif/*__DRUMGIZMO_SELECTION_H__*/ diff --git a/src/selectioneditor.cc b/src/selectioneditor.cc new file mode 100644 index 0000000..e8db104 --- /dev/null +++ b/src/selectioneditor.cc @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * selectioneditor.cc + * + * Thu Apr 17 17:25:18 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "selectioneditor.h" + +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QLabel> + +QLineEdit *createWidget(QString name, QWidget *parent) +{ + QHBoxLayout *l = new QHBoxLayout(); + + l->addWidget(new QLabel(name)); + + QLineEdit *edt = new QLineEdit(); + QObject::connect(edt, SIGNAL(editingFinished()), + parent, SLOT(updateSelection())); + + l->addWidget(edt); + + ((QHBoxLayout *)parent->layout())->addLayout(l); + + return edt; +} + +SelectionEditor::SelectionEditor(Selections &s) + : selections(s) +{ + cur = SEL_NONE; + + setLayout(new QVBoxLayout()); + + from = createWidget("From:", this); + to = createWidget("To:", this); + fadein = createWidget("FadeIn:", this); + fadeout = createWidget("FadeOut:", this); + energy = createWidget("Energy:", this); + name = createWidget("Name:", this); +} + +void SelectionEditor::updateSelection() +{ + Selection sel; + + sel.from = from->text().toInt(); + sel.to = to->text().toInt(); + sel.fadein = fadein->text().toInt(); + sel.fadeout = fadeout->text().toInt(); + sel.energy = energy->text().toDouble(); + sel.name = name->text(); + + selections.update(cur, sel); +} + +void SelectionEditor::update() +{ + Selection sel = selections.get(cur); + from->setText(QString::number(sel.from)); + to->setText(QString::number(sel.to)); + fadein->setText(QString::number(sel.fadein)); + fadeout->setText(QString::number(sel.fadeout)); + energy->setText(QString::number(sel.energy)); + name->setText(sel.name); +} + +void SelectionEditor::added(sel_id_t id) +{ + // Nothing to do here... +} + +void SelectionEditor::updated(sel_id_t id) +{ + if(cur == id) { + update(); + } +} + +void SelectionEditor::removed(sel_id_t id) +{ + if(cur == id) { + cur = SEL_NONE; + update(); + } +} + +void SelectionEditor::activeChanged(sel_id_t id) +{ + cur = id; + update(); +} diff --git a/src/selectioneditor.h b/src/selectioneditor.h new file mode 100644 index 0000000..55d8e33 --- /dev/null +++ b/src/selectioneditor.h @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * selectioneditor.h + * + * Thu Apr 17 17:25:17 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_SELECTIONEDITOR_H__ +#define __DRUMGIZMO_SELECTIONEDITOR_H__ + +#include <QWidget> + +#include <QLineEdit> +#include "selection.h" + +class SelectionEditor : public QWidget { +Q_OBJECT +public: + SelectionEditor(Selections &selections); + +public slots: + void added(sel_id_t id); + void updated(sel_id_t id); + void removed(sel_id_t id); + void activeChanged(sel_id_t id); + +private slots: + void update(); + void updateSelection(); + +private: + Selections &selections; + + sel_id_t cur; + + QLineEdit *from; + QLineEdit *to; + QLineEdit *fadein; + QLineEdit *fadeout; + QLineEdit *energy; + QLineEdit *name; +}; + +#endif/*__DRUMGIZMO_SELECTIONEDITOR_H__*/ diff --git a/src/sleep.h b/src/sleep.h new file mode 100644 index 0000000..107b7a8 --- /dev/null +++ b/src/sleep.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * sleep.h + * + * Sun Apr 20 18:54:58 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_SLEEP_H__ +#define __DRUMGIZMO_SLEEP_H__ + +#include <QThread> + +class __Sleeper : public QThread { +public: + void msleep(unsigned long msecs) { QThread::msleep(msecs); } + void sleep(unsigned long secs) { QThread::sleep(secs); } + void usleep(unsigned long usecs) { QThread::usleep(usecs); } +}; + +inline void q_msleep(unsigned long msecs) +{ + __Sleeper s; + s.msleep(msecs); +} + +inline void q_sleep(unsigned long secs) +{ + __Sleeper s; + s.sleep(secs); +} + +inline void q_usleep(unsigned long usecs) +{ + __Sleeper s; + s.usleep(usecs); +} + +#endif/*__DRUMGIZMO_SLEEP_H__*/ diff --git a/src/volumefader.cc b/src/volumefader.cc new file mode 100644 index 0000000..08bab80 --- /dev/null +++ b/src/volumefader.cc @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * volumefader.cc + * + * Tue Apr 15 15:46:00 CEST 2014 + * Copyright 2014 Jonas Suhr Christensen + * jsc@umbraculum.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "volumefader.h" + +#include <QSlider> +#include <QVBoxLayout> + +#include <math.h> + +#define SCALAR 10 +#define P 0.5 + +VolumeFader::VolumeFader() +{ + peak = 0; + volslider = new QSlider(); + volslider->setRange(-60 * SCALAR , 10 * SCALAR); + volslider->setOrientation(Qt::Horizontal); + + volumepeak = new QLabel(); + + volume = new QLabel(); + + connect(volslider, SIGNAL(valueChanged(int)), this, SLOT(handleValueChanged())); + + QVBoxLayout* lo = new QVBoxLayout(); + lo->addWidget(volslider); + + lo->addWidget(volumepeak); + lo->addWidget(volume); + + setLayout(lo); +} + +VolumeFader::~VolumeFader() +{ + +} + +void VolumeFader::updatePeakDb(double db) +{ +// updatePeakPower(pow(10, db/20)); +} + +void VolumeFader::updatePeakPower(double newpeak) +{ + peak = (newpeak * (1.0-P) + peak * P); + volumepeak->setText("Peak " + QString::number(peak, 'f', 5)); + handleValueChanged(); +} + +void VolumeFader::setVolumeDb(double db) +{ + volslider->setValue(db*SCALAR); + handleValueChanged(); +} + +void VolumeFader::setVolumePower(double power) +{ + double db = 20 * log10(power); + setVolumeDb(db); + handleValueChanged(); +} + +void VolumeFader::handleValueChanged() +{ + double db = ((double)volslider->value())/((double)SCALAR); + double power = pow(10, db/20); + emit volumeChangedDb(db); + emit volumeChangedPower(power); + + volume->setText("Gain " + QString::number(volslider->value()/SCALAR) + " dB"); +} diff --git a/src/volumefader.h b/src/volumefader.h new file mode 100644 index 0000000..7209956 --- /dev/null +++ b/src/volumefader.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * volumefader.h + * + * Tue Apr 15 15:46:00 CEST 2014 + * Copyright 2014 Jonas Suhr Christensen + * jsc@umbraculum.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_VOLUMEFADER_H__ +#define __DRUMGIZMO_VOLUMEFADER_H__ + +#include <QWidget> +#include <QSlider> +#include <QLabel> + +#include <stdio.h> + +class VolumeFader : public QWidget { +Q_OBJECT +public: + VolumeFader(); + ~VolumeFader(); + + void volumeDb(); + void volumePower(); + +public slots: + void updatePeakDb(double vol); + void updatePeakPower(double vol); + void setVolumeDb(double vol); + void setVolumePower(double vol); + +private slots: + void handleValueChanged(); + +signals: + void volumeChangedDb(double vol); + void volumeChangedPower(double vol); + +private: + QSlider *volslider; + QLabel *volumepeak; + QLabel *volume; + double peak; +}; + +#endif/*__DRUMGIZMO_VOLUMEFADER_H__*/ diff --git a/src/zoomslider.cc b/src/zoomslider.cc new file mode 100644 index 0000000..0a2abb1 --- /dev/null +++ b/src/zoomslider.cc @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * zoomslider.cc + * + * Fri May 2 21:23:26 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the 45Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "zoomslider.h" + +#include <QPainter> + +ZoomSlider::ZoomSlider(Qt::Orientation orientation) + : QSlider(orientation) +{ + inverted = false; + from = 0; + to = 1; + tick_width = 0.1; + + connect(this, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int))); +} + +void ZoomSlider::paintEvent(QPaintEvent *ev) +{ + /* + QPainter p(this); + p.drawLine(0, 0, width(), height()); + */ + QSlider::paintEvent(ev); +} + +void ZoomSlider::setRange(float from, float to) +{ + this->inverted = false; + this->from = from; + this->to = to; + + int i_from = from / tick_width; + int i_to = to / tick_width; + + if(i_from > i_to) { + this->inverted = true; + int tmp; + tmp = i_from; + i_from = i_to; + i_to = tmp; + } + + QSlider::setRange(i_from, i_to); +} + +float ZoomSlider::fromSlider(int value) +{ + float val = (float)value * tick_width; + + if(inverted) { + val *= -1; + val = val - to + from; + + if(value == QSlider::minimum()) val = from; + if(value == QSlider::maximum()) val = to; + } else { + if(value == QSlider::minimum()) val = from; + if(value == QSlider::maximum()) val = to; + } + + return val; +} + +void ZoomSlider::sliderValueChanged(int value) +{ + emit valueChanged(fromSlider(value)); +} + +void ZoomSlider::setTickWidth(float tick_width) +{ + this->tick_width = tick_width; + setRange(from, to); // Update slider value span. +} + +void ZoomSlider::setValue(float value) +{ + int i_value = value * tick_width; + if(inverted) { + i_value *= -1; + i_value += from; + } + QSlider::setValue(i_value); +} diff --git a/src/zoomslider.h b/src/zoomslider.h new file mode 100644 index 0000000..60b6772 --- /dev/null +++ b/src/zoomslider.h @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * zoomslider.h + * + * Fri May 2 21:23:26 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_ZOOMSLIDER_H__ +#define __DRUMGIZMO_ZOOMSLIDER_H__ + +#include <QSlider> +#include <QObject> + +class ZoomSlider : public QSlider { +Q_OBJECT +public: + ZoomSlider(Qt::Orientation orientation); + + /** + * Range of the slider. 'from' may be lesser than 'to' which will invert the + * slider. + */ + void setRange(float from, float to); + + /** + * Set the distance between emitting of valueChanged signals. + * Example: from:=0, to:=1 and width:=0.5 will emit valueChanged signals on + * 0.0, 0.5 and 1.0 (ie. the slider will have 3 actual values) + * NOTE: If 'width' is greater than the span of [from; to] only the 'from' + * and 'to' values can be selected on the slider. + */ + void setTickWidth(float width); + + void setValue(float value); + +signals: + void valueChanged(float value); + +private slots: + void sliderValueChanged(int value); + +protected: + void paintEvent(QPaintEvent *ev); + +private: + float fromSlider(int value); + + bool inverted; + float from; + float to; + float tick_width; +}; + +#endif/*__DRUMGIZMO_ZOOMSLIDER_H__*/ diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 0000000..dc25608 --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,3 @@ +EXTRA_DIST = \ + MocList \ + add_file
\ No newline at end of file diff --git a/tools/MocList b/tools/MocList new file mode 100755 index 0000000..639b668 --- /dev/null +++ b/tools/MocList @@ -0,0 +1,9 @@ +# -*- mode: shell-script; sh-shell: bash; sh-indentation: 2 -*- +if [ "$1" = "cc" ]; then + grep "Q_OBJECT" *.h | cut -d: -f1 | sed -e 's/^//g;s/\.h/\.moc.cc/g'| xargs echo; +elif [ "$1" = "o" ]; then + grep "Q_OBJECT" *.h | cut -d: -f1 | sed -e 's/^//g;s/\.h/\.moc.o/g'| xargs echo; +elif [ "$1" = "h" ]; then + grep "Q_OBJECT" *.h | cut -d: -f1 | cut -d'/' -f3 | xargs echo; +fi + diff --git a/tools/add_file b/tools/add_file new file mode 100755 index 0000000..d63b4ab --- /dev/null +++ b/tools/add_file @@ -0,0 +1,76 @@ +#!/bin/bash +PROJECT="DrumGizmo" + +function allfile() { + echo "/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */" > $1; + echo "/***************************************************************************" >> $1; + echo " * $1" >> $1; + echo " *" >> $1 ; + echo " * `date`" >> $1; + echo -n " * Copyright " >> $1 + echo -n `date +%Y | xargs` >> $1 + if [ "$USER" == "nemo" ]; + then + echo " Jonas Suhr Christensen" >> $1; + echo " * jsc@umbraculum.org" >> $1; + fi + if [ "$USER" == "deva" ]; + then + echo " Bent Bisballe Nyeng" >> $1; + echo " * deva@aasimon.org" >> $1; + fi + if [ "$USER" == "senator" ]; + then + echo " Lars Bisballe Jensen" >> $1; + echo " * elsenator@gmail.com" >> $1; + fi + echo " ****************************************************************************/" >> $1; + echo "" >> $1; + echo "/*" >> $1; + echo " * This file is part of $PROJECT." >> $1; + echo " *" >> $1; + echo " * $PROJECT is free software; you can redistribute it and/or modify" >> $1; + echo " * it under the terms of the GNU General Public License as published by" >> $1; + echo " * the Free Software Foundation; either version 2 of the License, or" >> $1; + echo " * (at your option) any later version." >> $1; + echo " *" >> $1; + echo " * $PROJECT is distributed in the hope that it will be useful," >> $1; + echo " * but WITHOUT ANY WARRANTY; without even the implied warranty of" >> $1; + echo " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" >> $1; + echo " * GNU General Public License for more details." >> $1; + echo " *" >> $1; + echo " * You should have received a copy of the GNU General Public License" >> $1; + echo " * along with $PROJECT; if not, write to the Free Software" >> $1; + echo " * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA." >> $1; + echo " */" >> $1; +} + +function ccfile() { + local hf=`echo -n $1 | cut -d'.' -f1`.h; + hfile $hf; + + allfile $1; + echo -n '#include "' >> $1; + echo -n $hf >> $1; + echo '"' >> $1; + echo '' >> $1; +} + +function hfile() { + allfile $1; + local hn=`echo $1 | tr 'a-z.' 'A-Z_'` + local pr=`echo $PROJECT | tr 'a-z.' 'A-Z_'` + echo "#ifndef __${pr}_${hn}__" >> $1; + echo "#define __${pr}_${hn}__" >> $1; + echo "#endif/*__${pr}_${hn}__*/" >> $1; +} + +if [ "$#" = "1" ]; then +if [ "CC" = `echo $1 | cut -d'.' -f2 | tr 'a-z' 'A-Z'` ]; then + ccfile $1; +fi; +if [ "H" = `echo $1 | cut -d'.' -f2 | tr 'a-z' 'A-Z'` ]; then + hfile $1; +fi; +else echo "Usage: $0 filename"; +fi; diff --git a/version.h b/version.h new file mode 100644 index 0000000..b2a00aa --- /dev/null +++ b/version.h @@ -0,0 +1 @@ +#define VERSION "0.9.5" |