diff --git a/.classpath b/.classpath deleted file mode 100644 index d57ec02..0000000 --- a/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.cproject b/.cproject deleted file mode 100644 index fd116cf..0000000 --- a/.cproject +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.project b/.project deleted file mode 100644 index 6d0125f..0000000 --- a/.project +++ /dev/null @@ -1,108 +0,0 @@ - - - frozenbubble - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - ?children? - ?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|?name?=entry\\\\\\\|\\\|\|| - - - ?name? - - - - org.eclipse.cdt.make.core.append_environment - true - - - org.eclipse.cdt.make.core.buildArguments - - - - org.eclipse.cdt.make.core.buildCommand - ndk-build - - - org.eclipse.cdt.make.core.cleanBuildTarget - clean - - - org.eclipse.cdt.make.core.contents - org.eclipse.cdt.make.core.activeConfigSettings - - - org.eclipse.cdt.make.core.enableAutoBuild - false - - - org.eclipse.cdt.make.core.enableCleanBuild - true - - - org.eclipse.cdt.make.core.enableFullBuild - true - - - org.eclipse.cdt.make.core.stopOnError - true - - - org.eclipse.cdt.make.core.useDefaultBuildCmd - true - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - - - 1363370493138 - - 26 - - org.eclipse.ui.ide.multiFilter - 1.0-name-matches-false-false-.svn - - - - diff --git a/AndroidManifest.xml b/AndroidManifest.xml deleted file mode 100644 index 19c5c3e..0000000 --- a/AndroidManifest.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/wiki/BuildInstructions.wiki b/BuildInstructions.md similarity index 84% rename from wiki/BuildInstructions.wiki rename to BuildInstructions.md index 08b8cd2..5860814 100644 --- a/wiki/BuildInstructions.wiki +++ b/BuildInstructions.md @@ -1,11 +1,8 @@ -#summary Frozen Bubble for Android Build Instructions. -#labels Phase-Implementation,Featured - -= Introduction = +# Introduction # This Wiki entry details how to build Frozen Bubble for Android from the source code. -= Details = +# Details # To build the Frozen Bubble for Android application, you must first download the archive of the Android SDK ADT bundle. The ADT (Android Development Tools) bundle comes with Eclipse - Eclipse is the IDE. SDK stands for software development kit (the tools to build Android applications from source code), and IDE stands for integrated development environment (a graphical user interface that simplifies software development). @@ -15,7 +12,7 @@ Click the button on the side that says "Download the SDK ADT Bundle for Windows" After you extract the SDK, you need to run the SDK manager, which is a program that is placed in the root of the extracted SDK folder. After you launch the SDK manager, you should see something like this: -http://imgur.com/peufLFg.jpg +![http://imgur.com/peufLFg.jpg](http://imgur.com/peufLFg.jpg) At a minimum, you must select to install the Android 1.6 (API 4) SDK Platform. This is the API level for Frozen Bubble, which means that an Android device must have version 1.6 or later of Android to play the game. @@ -25,9 +22,9 @@ http://developer.android.com/tools/sdk/ndk/index.html Once you have extracted the NDK, launch Eclipse - it is located in the Eclipse folder of the extracted SDK folder. You will have to add the path to the NDK to the environment, by selecting "Window → Preferences" in Eclipse. -Select "NDK" under "Android" in the list on the left. *Note that the build path for the NDK isn't allowed to contain any spaces or the program won't compile*: +Select "NDK" under "Android" in the list on the left. **Note that the build path for the NDK isn't allowed to contain any spaces or the program won't compile**: -http://imgur.com/fzNmvqa.jpg +![http://imgur.com/fzNmvqa.jpg](http://imgur.com/fzNmvqa.jpg) Next, you will have to get the source code for Frozen Bubble. I recommend using Tortoise SVN (again, I hope you are using Windows) as it is by far the easiest source control tool to work with. @@ -39,9 +36,9 @@ http://frozenbubbleandroid.googlecode.com/svn Right-click the topmost level in the dropdown list on the left, then select "Export". Export everything into an empty folder on your computer: -http://imgur.com/9qW7ZI8.jpg +![http://imgur.com/9qW7ZI8.jpg](http://imgur.com/9qW7ZI8.jpg) -*It has been noted that on the project source page, the instructions for checking out the code anonymously do not work, because this project does not have a trunk folder.* +**It has been noted that on the project source page, the instructions for checking out the code anonymously do not work, because this project does not have a trunk folder.** https://code.google.com/p/frozenbubbleandroid/source/checkout @@ -57,6 +54,6 @@ After the files are copied to your computer, you can import the project into Ecl Browse to the folder you placed the source files in with Tortoise SVN, and check "Copy projects into workspace": -http://imgur.com/hi7Ic3o.jpg +![http://imgur.com/hi7Ic3o.jpg](http://imgur.com/hi7Ic3o.jpg) Now, you should be able to build the project in Eclipse. \ No newline at end of file diff --git a/COPYING b/COPYING deleted file mode 100644 index d159169..0000000 --- a/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) 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 -this service 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 make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. 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. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -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 -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the 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 a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE 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. - - 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 -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision 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, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This 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. diff --git a/wiki/GameMusic.wiki b/GameMusic.md similarity index 59% rename from wiki/GameMusic.wiki rename to GameMusic.md index f3acb4d..aa4792e 100644 --- a/wiki/GameMusic.wiki +++ b/GameMusic.md @@ -1,17 +1,14 @@ -#summary Game Music Playlist -#labels Featured,Phase-Support +# Music Copyright Notice # -= Music Copyright Notice = - -All the music used in this game is available free for download from the [http://modarchive.org/ Mod Archive]. Each song is in its original module format with the information intact with regards to each song's title and author. Each song is the copyright of its respective author, and is not for commercial use unless permission or licensing is granted by the author. You may distribute this music freely without requiring explicit permission from the original artist as long as: +All the music used in this game is available free for download from the [Mod Archive](http://modarchive.org/). Each song is in its original module format with the information intact with regards to each song's title and author. Each song is the copyright of its respective author, and is not for commercial use unless permission or licensing is granted by the author. You may distribute this music freely without requiring explicit permission from the original artist as long as: * The songs are not altered in any way. * Clear credit is given to the artists for their respective works. * No fee is charged for distribution. -The music is licensed under the [http://modarchive.org/index.php?terms-upload Mod Archive distribution license]. +The music is licensed under the [Mod Archive distribution license](http://modarchive.org/index.php?terms-upload). -= Frozen Bubble Playlist = +# Frozen Bubble Playlist # _After the Rain_ by Unknown Artist diff --git a/ProjectHome.md b/ProjectHome.md new file mode 100644 index 0000000..263326c --- /dev/null +++ b/ProjectHome.md @@ -0,0 +1 @@ +The Android port of the Frozen Bubble game. Knock the bubbles down by making clusters of three or more bubbles in the same color. \ No newline at end of file diff --git a/README b/README deleted file mode 100644 index 5b11353..0000000 --- a/README +++ /dev/null @@ -1,26 +0,0 @@ -The Android port of the Frozen Bubble game. Developed with SDK v21.1.0, using -API level 4 (version 1.6 - Donut). - -The code is based on the Java version of Frozen Bubble created by Glenn Sanson. -The original Frozen Bubble was created by Guillaume Cottenceau (programming), -Alexis Younes and Amaury Amblard-Ladurantie (artwork) and Matthias Le Bidan -(soundtrack). - -The Android port was initially created by Pawel Aleksander Fedorynski, with -additional development provided by Eric Fortin. - -This code is distributed under the GNU General Public License. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License version 2 or 3, as published by the -Free Software Foundation. - -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, write to: -Free Software Foundation, Inc. -675 Mass Ave -Cambridge, MA 02139, USA \ No newline at end of file diff --git a/andmodplug_PlayerThread.h b/andmodplug_PlayerThread.h deleted file mode 100644 index 963bd0d..0000000 --- a/andmodplug_PlayerThread.h +++ /dev/null @@ -1,225 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class com_peculiargames_andmodplug_PlayerThread */ - -#ifndef _Included_com_peculiargames_andmodplug_PlayerThread -#define _Included_com_peculiargames_andmodplug_PlayerThread -#ifdef __cplusplus -extern "C" { -#endif -#undef com_peculiargames_andmodplug_PlayerThread_MIN_PRIORITY -#define com_peculiargames_andmodplug_PlayerThread_MIN_PRIORITY 1L -#undef com_peculiargames_andmodplug_PlayerThread_NORM_PRIORITY -#define com_peculiargames_andmodplug_PlayerThread_NORM_PRIORITY 5L -#undef com_peculiargames_andmodplug_PlayerThread_MAX_PRIORITY -#define com_peculiargames_andmodplug_PlayerThread_MAX_PRIORITY 10L -#undef com_peculiargames_andmodplug_PlayerThread_PATTERN_CHANGE_IMMEDIATE -#define com_peculiargames_andmodplug_PlayerThread_PATTERN_CHANGE_IMMEDIATE 1L -#undef com_peculiargames_andmodplug_PlayerThread_PATTERN_CHANGE_AFTER_CURRENT -#define com_peculiargames_andmodplug_PlayerThread_PATTERN_CHANGE_AFTER_CURRENT 2L -#undef com_peculiargames_andmodplug_PlayerThread_PATTERN_CHANGE_AFTER_GROUP -#define com_peculiargames_andmodplug_PlayerThread_PATTERN_CHANGE_AFTER_GROUP 3L -#undef com_peculiargames_andmodplug_PlayerThread_BUFFERSIZE -#define com_peculiargames_andmodplug_PlayerThread_BUFFERSIZE 20000L -#undef com_peculiargames_andmodplug_PlayerThread_NUM_RATES -#define com_peculiargames_andmodplug_PlayerThread_NUM_RATES 5L -#undef com_peculiargames_andmodplug_PlayerThread_EVENT_PLAYER_STARTED -#define com_peculiargames_andmodplug_PlayerThread_EVENT_PLAYER_STARTED 1L -#undef com_peculiargames_andmodplug_PlayerThread_EVENT_PATTERN_CHANGE -#define com_peculiargames_andmodplug_PlayerThread_EVENT_PATTERN_CHANGE 2L -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_Init - * Signature: (I)Z - */ -JNIEXPORT jboolean JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1Init - (JNIEnv *, jclass, jint); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_JLoad - * Signature: ([BI)Z - */ -JNIEXPORT jboolean JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1JLoad - (JNIEnv *, jobject, jbyteArray, jint); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_JGetName - * Signature: ()Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1JGetName - (JNIEnv *, jobject); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_JNumChannels - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1JNumChannels - (JNIEnv *, jobject); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_JGetSoundData - * Signature: ([SI)I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1JGetSoundData - (JNIEnv *, jobject, jshortArray, jint); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_JUnload - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1JUnload - (JNIEnv *, jclass); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_CloseDown - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1CloseDown - (JNIEnv *, jclass); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetNativeTempo - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetNativeTempo - (JNIEnv *, jclass); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_ChangeTempo - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1ChangeTempo - (JNIEnv *, jclass, jint); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_SetTempo - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetTempo - (JNIEnv *, jclass, jint); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_ChangePattern - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1ChangePattern - (JNIEnv *, jclass, jint); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_RepeatPattern - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1RepeatPattern - (JNIEnv *, jclass, jint); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_CheckPatternChange - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1CheckPatternChange - (JNIEnv *, jclass); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_SetPatternLoopMode - * Signature: (Z)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetPatternLoopMode - (JNIEnv *, jclass, jboolean); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_SetCurrentPattern - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetCurrentPattern - (JNIEnv *, jobject, jint); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_SetNextPattern - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetNextPattern - (JNIEnv *, jobject, jint); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetCurrentPos - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetCurrentPos - (JNIEnv *, jobject); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetMaxPos - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetMaxPos - (JNIEnv *, jobject); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetCurrentOrder - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetCurrentOrder - (JNIEnv *, jobject); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetCurrentPattern - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetCurrentPattern - (JNIEnv *, jobject); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetCurrentRow - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetCurrentRow - (JNIEnv *, jobject); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_SetPatternLoopRange - * Signature: (III)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetPatternLoopRange - (JNIEnv *, jclass, jint, jint, jint); - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_LogOutput - * Signature: (Z)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1LogOutput - (JNIEnv *, jclass, jboolean); - - /* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_SetLoopCount - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetLoopCount - (JNIEnv *, jclass, jint); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/app_frozen_bubble-web.png b/app_frozen_bubble-web.png deleted file mode 100644 index 1fe69e7..0000000 Binary files a/app_frozen_bubble-web.png and /dev/null differ diff --git a/assets/levels.txt b/assets/levels.txt deleted file mode 100644 index 7eb0100..0000000 --- a/assets/levels.txt +++ /dev/null @@ -1,1099 +0,0 @@ -6 6 4 4 2 2 3 3 - 6 6 4 4 2 2 3 -2 2 3 3 6 6 4 4 - 2 3 3 6 6 4 4 -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- 7 7 7 7 7 7 - - - 1 1 1 1 1 - -- - 2 2 2 2 - - - - - - 2 - - - -- - - 2 2 - - - - - - - 5 - - - -- - - 5 5 - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - 7 - - 7 - - - - - 7 1 7 - - -- - - 1 2 - - - - - - 1 2 1 - - -- - - 2 5 - - - - - - 3 5 3 - - -- - - 5 3 - - - - - - - 3 - - - -- - - - - - - - - - - - - - - - - -- - - 0 0 - - - - - - 5 0 1 - - -- - 3 5 1 6 - - - - 4 3 - 6 7 - -- 7 4 - - 7 4 - - 6 7 - - - 4 3 -1 6 - - - - 3 5 - 1 - - - - - 5 -- - - - - - - - - - - - - - - - - -- - 0 0 0 0 - - - - 0 1 1 1 0 - -- 0 1 0 0 1 0 - - - 0 1 1 1 0 - -- - 0 0 0 0 - - - - - 7 - 7 - - -- - 7 7 7 7 - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- 4 4 4 6 6 6 - - 4 - - - - - 6 -- 4 - - - - 6 - - 4 2 3 1 2 3 6 -- 3 1 2 3 1 2 - - - - - - - - - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- 4 4 4 6 6 6 - - 4 - - - - - 6 -- 4 - - - - 6 - - 4 2 3 1 2 3 6 -- 3 1 2 3 1 2 - - - 2 3 1 2 3 - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- 0 0 - - 2 2 - - - 5 - - - 3 - -- 0 - - - 6 - - - - 3 - - - 0 - -- 4 - - - 5 - - - - 2 - - - 3 - -- 2 - - - 1 - - - - 3 - - - 4 - -- - - - - - - - - - - - - - - - - -3 - - - - - - 3 - 6 3 2 4 6 3 2 -4 - - - - - - 4 - 2 4 6 3 2 4 6 -- - - 6 - - - - - - - - 3 - - - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- 2 - 1 - 1 - 2 - 1 2 - 2 1 - 1 -1 - 1 - 2 - 2 - - 2 1 - 1 2 - 2 -- 2 - 2 - 2 - 2 - 1 2 - 2 1 - 1 -1 - 1 - 2 - 1 - - 2 2 - 1 1 - 2 -- 2 - 1 - 1 - 1 - - - - - - - - - -- 7 7 - - 5 5 - - 1 - - - - - 4 -2 1 - - - - 4 3 - 2 - - - - - 3 -1 2 - - - - 3 4 - 1 - - - - - 4 -7 1 - - - - 4 5 - 7 7 - - - 5 5 -- - - - - - - - - - - - - - - - - -7 7 - - - - 5 5 - 1 5 - - - 7 4 -2 1 - - - - 4 3 - 2 - - - - - 3 -1 5 - - - - 7 4 - 1 - - - - - 4 -7 1 - - - - 4 5 - 7 5 - - - 7 5 -- - - - - - - - - - - - - - - - - -- - - 0 0 - - - - - - 5 0 1 - - -- - 3 5 1 6 - - - - 4 3 2 6 2 - -- 7 4 7 2 2 4 - - 6 7 7 3 3 4 3 -1 6 1 1 1 3 3 5 - 1 1 - - - - 5 -- - - - - - - - - - - - - - - - - -- - 0 - - 0 - - - - 3 3 - 3 3 - -- 0 2 0 0 2 0 - - - 3 3 - 3 3 - -- - 0 - - 0 - - - - - - - - - - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - - 1 1 - - - - - - 2 2 2 - - -- - 3 3 3 3 - - - - 4 4 4 4 4 - -- 5 5 5 5 5 5 - - - - - 6 - - - -- - - 7 7 - - - - - - - 0 - - - -- - - - - - - - - - - - - - - - - -- - - 2 5 - - - - - 4 3 - - - - -6 7 - 5 2 - - - - - - - - 3 4 - -- - - 2 5 - 7 6 - - 4 3 - - - - -6 7 - 5 2 - - - - - - - - 3 4 - -- - - - - - 7 6 - - - - - - - - - -- - - 5 5 - - - - - - - 3 - - - -- - - 1 - - - - - - - - 7 - - - -- - - 2 - - - - - - - - 4 - - - -- - - 5 - - - - - - - - 3 - - - -- - - - - - - - - - - - - - - - - -- - - 0 1 - - - - - - 0 2 7 7 - -- - - 0 1 7 - - - - 0 0 0 0 - - -- 0 0 0 1 1 - - - 0 0 0 1 1 1 - -- 0 0 1 1 1 - - - - 0 0 0 7 7 - -- - 7 7 - - - - - - - - - - - - - -- 1 - - - - - - - 1 - - - - - - -- 2 3 4 7 6 5 - - - - - - - - 1 -- - - - - - 1 - - - 2 3 4 7 6 - -- 1 - - - - - - - 1 - - - - - - -- 2 3 4 7 6 5 - - - - - - - - - - -- 6 - - - - - - - 5 - - - - - - -2 3 4 7 6 5 2 3 - - - - - - - 4 -- - - - - - 7 - - - 4 3 2 5 6 - -- 7 - - - - - - - 6 - - - - - - -5 2 3 4 7 6 5 - - - - - - - - - - -3 2 1 0 0 1 2 3 - 3 2 1 0 1 2 3 -4 3 2 1 1 2 3 4 - 4 3 2 1 2 3 4 -5 4 3 2 2 3 4 5 - 5 4 3 2 3 4 5 -6 5 4 3 3 4 5 6 - 6 5 4 3 4 5 6 -7 6 5 4 4 5 6 7 - - - - - - - - - -- - - 5 5 - - - - - - - 3 - - - -- - - 2 4 - - - - - - - 6 - - - -- - - 2 4 - - - - - 2 - 5 - 4 - -1 0 1 0 1 0 1 0 - 3 - 3 - 2 - 6 -- - - - - - - - - - - - - - - - - -- - - - 1 - - - - 7 4 3 5 - - - -6 - - 1 - - - - - - - - 5 3 4 7 -6 - - - 1 - - 6 - 7 4 3 5 - - - -- - - 1 - - - 6 - - - - 5 3 4 7 -- - - - - - - - - - - - - - - - - -- - - - 7 3 6 - - - - 3 7 3 6 3 -- - 5 7 3 6 3 - - - 6 7 3 6 7 - -- 7 7 3 6 1 - - - 3 7 3 6 3 - - -5 6 2 7 1 - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -5 - - - - - - 5 - 5 - 6 6 6 - 5 -- 5 4 - - 4 5 - - - 3 - - - 3 - -- 6 0 - - 0 6 - - - 3 - - - 3 - -- - 4 - - 4 - - - - - 6 6 6 - - -- - - - - - - - - - - - - - - - - -- 7 0 - - 0 7 - - 7 - 0 - 0 - 7 -7 1 - 0 0 - 1 7 - 7 1 2 0 2 1 7 -7 6 3 2 2 3 6 7 - 7 - 3 2 3 - 7 -- 7 7 3 3 7 7 - - - - - 3 - - - -- - - - - - - - - - - - - - - - - -- 3 - 1 - 7 - 6 - 5 - 7 - 7 - 6 -6 - 0 - 5 - 3 - - - 2 - 1 - 5 - -- 4 - 3 - 4 - - - 2 - 3 - 2 - - -- - 4 - 6 - - - - - - - 5 - - - -- - - - - - - - - - - - - - - - - -- - - - 1 - - - - - - - - 3 - - -6 1 3 1 2 1 4 1 - - - - - 6 - - -- - - 4 1 - - - - - - 1 - 3 - - -- - - 2 1 - - - - - - - - 4 - - -- - - 6 1 - - - - - - - 6 - - - - -- - - 5 4 - - - - - - 4 1 0 - - -- - - 2 3 - - - - - 1 4 - 2 2 - -- 3 1 2 5 1 4 - - - 4 2 - 0 4 - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - - - 1 - - - - - - - 1 - - - -- 2 - - 1 - 5 - - 5 - - 1 - - 0 -- 6 - - 1 - 4 - - - 0 - 1 - 5 - -- - 5 5 0 1 - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - - 6 3 - - - - - - 3 2 6 - - -- - 2 6 3 2 - - - - 6 3 2 6 3 - -- 3 2 6 3 2 6 - - 2 6 3 2 6 3 2 -6 3 2 6 3 2 6 3 - - - - - - - - -- - - - - - - - - - - - - - - - - -6 6 6 6 6 6 6 6 - 4 - - - - - - -- 3 2 5 7 6 4 3 - - 5 - - - - - -- - 7 6 4 3 2 5 - - - 4 - - - - -- - - 3 2 5 7 6 - - - - - - - - -- - - - - - - - - - - - - - - - - -1 - 7 - - 6 - 2 - 6 - 1 - 6 1 3 -- 4 - 7 2 - 7 - - 2 7 - - - 4 - -6 - 3 5 0 2 - 7 - 1 - - - - - 1 -- 1 4 5 7 5 1 - - - - - - - - - -- - - - - - - - - - - - - - - - - -6 6 6 - - 6 6 6 - - - 6 - 6 - - -- - 2 3 3 2 - - - - 3 - 5 - 3 - -- - 5 3 3 5 - - - - - 6 1 6 - - -- 4 2 - - 2 4 - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - - 5 5 - - - - - - 5 - - - - -- 3 4 6 6 - - 5 - 3 3 4 6 5 - 5 -3 2 3 6 6 5 5 - - 3 3 4 6 5 - 5 -- 3 4 6 6 - - 5 - - - 5 - - - - -- - - 5 5 - - - - - - - - - - - - -1 - - - - - - 1 - 1 - 2 2 2 - 1 -- 1 2 3 3 2 1 - - 6 2 3 - 3 2 6 -6 2 3 - - 3 2 6 - 6 2 3 - 3 2 6 -3 3 3 7 7 3 3 3 - 0 5 0 2 0 5 0 -- - - - - - - - - - - - - - - - - -- - 7 7 7 - - - - - 7 2 2 7 - - -- 7 5 5 5 7 - - - 7 7 7 7 7 7 - -- - 6 - 6 - - - - - 6 - - 6 - - -- 6 4 4 - 6 4 4 - - - - - - - - -- - - - - - - - - - - - - - - - - -- 3 3 - 3 3 3 - - 3 7 5 4 6 5 3 -1 3 3 3 - 3 3 1 - 2 1 2 1 2 1 2 -1 3 3 - 3 3 3 1 - 3 5 6 4 5 7 3 -2 3 3 3 - 3 3 2 - 1 1 2 2 2 1 1 -- - - - - - - - - - - - - - - - - -- 6 5 - - - - - - 3 1 3 - - - - -- 5 6 - - - - - - - - 5 3 - - - -- - 6 1 6 - - - - - - 3 5 - - - -- - - - 3 6 - - - - - - 5 6 5 - -- - - - 6 3 - - - - - - - - - - - -6 3 7 4 5 1 6 3 - 5 1 6 3 7 4 5 -6 3 7 4 5 1 6 3 - - - - - - - - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - - - - - 4 4 - - - 7 7 7 4 4 -- - - - - - 4 4 - - 1 - - - 7 - -- 1 1 - - 7 - - - 3 3 3 - 7 - - -3 - 2 3 3 3 - 3 - - 2 - 3 - 3 3 -- 2 - - - - - - - - - - - - - - - -- - 4 - - - - - - - 7 4 - - - - -- - 7 4 - - - - - - 4 7 4 - - - -1 1 1 1 1 1 1 - - 1 2 1 2 1 1 - -2 2 2 2 2 2 2 2 - - - - - - - - -- - - - - - - - - - - - - - - - - -0 - - - - - - 6 - 6 1 4 3 7 5 0 -0 - - - - - - 6 - 6 1 4 3 7 5 0 -0 - - - - - - 6 - 6 1 4 3 7 5 0 -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -3 3 4 6 6 4 3 3 - 0 3 4 6 4 3 1 -5 1 3 4 4 3 0 1 - 0 1 3 4 3 1 0 -2 1 6 3 3 0 0 1 - 0 3 4 3 6 1 5 -6 1 2 6 4 0 0 2 - - - - - - - - -- - - - - - - - - - - - - - - - - -6 6 - - - - 4 4 - 4 0 - - - 3 6 -0 6 - - - - 4 2 - 7 - - - - - 7 -4 4 - - - - 5 6 - 6 4 7 7 5 6 4 -- 7 6 4 6 4 7 - - - 0 - 7 - 7 - -- - - - - - - - - - - - - - - - - -- 5 - - - - 4 - - - 5 - - - 4 - -- - 5 6 6 4 - - - - - 2 - 2 - - -0 0 6 - - 6 1 1 - - - 2 - 2 - - -- - 7 6 6 3 - - - - 7 - - - 3 - -- 7 - - - - 3 - - - - - - - - - - -- 6 - - - - 2 - - 1 7 1 1 1 3 1 -- - 4 1 1 4 - - - - 1 3 1 7 1 - -- - - 2 6 - - - - - - 1 5 1 - - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -7 7 7 7 7 7 7 7 - 7 - - - - - 7 -7 - - 2 0 5 2 2 - 7 - - - 0 3 6 -7 - - - - - 4 0 - 5 5 - - - - - -4 3 6 2 - - - - - 0 2 0 4 - - - -- - - - - - - - - - - - - - - - - -- - 1 - - 1 - - - - 4 - - 5 - - -- 7 - - 1 1 1 - - 6 - - - - 7 - -1 1 1 1 - 4 - - - - - 5 - - - - -- - 0 - - - - - - - 3 - - - - - -- 1 - - - - - - - - - - - - - - - -- 7 7 - - 7 7 - - 6 - 4 - 4 - 6 -5 - - 3 3 - - 5 - 6 - - - - - 6 -- 7 - - - - 7 - - - 4 - - - 4 - -- - 3 - - 3 - - - - - 2 - 2 - - -- - - 5 5 - - - - - - - - - - - - -- 0 0 - - 0 0 - - 7 4 6 6 6 4 3 -5 6 6 6 2 6 6 3 - 7 4 6 6 6 4 3 -- 0 0 - - 0 0 - - - - - - - - - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - - - - 7 7 7 - - - - - 2 7 7 -- 0 7 7 7 - 7 7 - 6 7 7 7 - - - -6 - - - 7 7 7 7 - 6 - - - - - - -4 2 2 2 4 - 3 - - 4 4 4 4 3 3 3 -- - - - - - - - - - - - - - - - - -4 - - 7 - 6 - 7 - 7 6 7 - - 7 4 -- - 7 - - 7 - - - - 0 0 0 0 0 3 -- - 0 2 2 0 6 4 - - - 0 0 0 1 3 -- - - 0 0 - 3 4 - - - - 6 - 5 6 -- - - - - - 1 0 - - - - - - - - - -- 5 - - - - 5 - - 0 - - 0 - - 0 -0 0 0 2 2 0 0 0 - 0 - - 0 - - 0 -- 7 - 3 - - 7 - - - - 3 6 - - - -- - - 6 - - - - - - 3 6 - - - - -- 3 - - - - - - - - - - - - - - - -- - - 6 5 - - - - - - 2 6 3 - - -- - 5 4 7 1 - - - - 6 2 2 3 4 - -- - 3 7 3 6 - - - - - 1 3 2 - - -- - - 4 5 - - - - - - - 4 - - - -- - - - - - - - - - - - - - - - - -7 7 - 2 2 - 6 6 - 6 - - 6 - - 3 -2 - - 1 - - 2 - - 5 - - 3 - - 2 -1 - - 2 - - 1 - - 5 - - 2 - - 2 -6 - - 1 - - 7 - - 5 - - 5 - - 4 -- - - - - - - - - - - - - - - - - -- - - 6 6 - - - - - 0 4 4 4 0 - -- - - 6 6 - - - - - - 2 7 2 - - -- - - 6 6 - - - - - 0 5 5 5 0 - -- - - 3 3 - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - 4 1 3 - - - - - 1 - - 1 - - -- - 4 1 3 4 1 - - - 1 3 4 - - 4 -- 3 - - 3 4 1 - - - 1 3 4 1 3 - -- - 4 1 - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- 6 4 - 3 2 5 - - 0 - - - - - 1 -- 2 3 5 - 4 6 - - 0 - - - - - 1 -- 4 6 - 2 5 3 - - 0 - - - - - 1 -- 5 2 3 - 4 6 - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - - 6 6 - - - - - - 7 6 4 - - -- 2 1 7 4 1 3 - - 2 1 1 1 1 1 3 -- 2 2 2 3 3 3 - - - - - 5 - - - -- - - 2 3 - - - - - - - 5 - - - -- - 2 2 3 3 - - - - - - - - - - - -4 - 5 - - 3 - 6 - 2 - 3 - 2 - 4 -4 - - 1 0 - - 6 - 6 - 2 3 5 - 4 -4 - - 0 1 - - 6 - 2 - 5 - 3 - 4 -4 - 3 - - 2 - 6 - 6 - - - - - 4 -- - - - - - - - - - - - - - - - - -2 6 0 5 5 1 3 4 - 1 - - 2 - - 0 -4 - - 3 6 - - 2 - - - - 0 - - - -- - - 1 4 - - - - - - - 2 - - - -- - - 6 3 - - - - - - - 5 - - - -- - - 4 1 - - - - - - - - - - - - -- - - - 5 1 1 3 - 0 5 1 0 5 3 3 -5 1 0 5 1 0 5 1 - 0 5 1 0 5 1 6 -- - - - 1 6 5 1 - - - - - 5 1 6 -- - - - 1 0 5 1 - - - - - 5 1 0 -- - - - - - - - - - - - - - - - - -- 0 7 3 - - 2 2 - - 0 7 3 - - 2 -- 0 7 3 - - 2 2 - - 0 7 3 - 3 1 -- 0 7 3 - 6 4 5 - - 0 7 3 - 7 0 -- 0 7 3 - 2 3 4 - - 0 7 3 - 5 6 -- - - - - 7 0 1 - - - - - - - - - -- - - 7 7 7 7 - - 3 4 5 - - - 7 -2 - - - - - - 3 - 7 - - - - - 4 -7 - - - 3 4 5 6 - 7 - - 2 0 1 2 -6 - - - 3 4 5 6 - 0 1 - - - - - -2 3 4 - - - - - - 5 6 0 - - - - - -- 7 - - - - 2 - - 1 1 - - - 3 3 -- 2 - - - - 4 - - 3 3 - - - 5 5 -- 4 - - - - 6 - - 5 5 - - - 1 1 -- 6 - - - - 7 - - - - - - - - - -- - - - - - - - - - - - - - - - - -- 4 - - - - 4 - - 2 - - 1 - - 2 -5 - - 0 0 - - 5 - 5 - - 1 - - 6 -- 4 2 7 7 5 4 - - - - - 6 - - - -- - - 3 3 - - - - - - - 7 - - - -- - - - - - - - - - - - - - - - - -- 1 - - 2 3 4 - - 2 - - 3 0 4 - -4 - - 2 3 1 - - - 3 - 4 3 0 - - -4 - - 2 5 1 - - - 3 - 4 5 0 4 - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -2 - - 1 1 - - 2 - 2 - 3 3 3 - 2 -- 2 - 4 4 - 2 - - - 7 7 0 7 7 - -- - - 4 4 - - - - - - 5 7 5 - - -6 3 2 6 4 2 3 6 - 5 - - - - - 1 -- - - - - - - - - - - - - - - - - -4 2 3 5 7 1 3 6 - 1 - - 1 - - 1 -3 0 1 3 2 4 3 5 - 4 - - 4 - - 4 -- 5 - - 5 - - 5 - 0 3 2 0 4 5 0 -- 6 - - 6 - - 6 - 7 - - 7 - - 7 -- - - - - - - - - - - - - - - - - -- 5 4 - 1 1 - - - 5 - 4 1 - 1 - -0 - - - - - 0 - - 0 6 4 - - 4 2 -- 4 3 5 2 6 3 6 - - 2 6 - - 5 4 -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - - 6 6 - - - - - - 5 5 4 - - -- - 1 6 6 4 - - - - 1 7 2 5 3 - -- 2 7 2 1 5 3 - - 2 1 3 1 4 2 7 -- 3 1 3 4 2 7 - - - 3 5 5 6 6 - -- - - - - - - - - - - - - - - - - -- - 7 3 - - - - - - 1 7 6 - - - -- 3 7 5 1 5 - - - 7 7 0 2 4 0 4 -7 1 4 6 5 6 5 7 - 1 7 7 1 7 7 1 -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - 1 - - 1 - - - - 5 6 1 5 6 - -- 1 1 2 2 1 1 - - 4 7 1 0 1 7 4 -- 3 7 5 7 5 3 - - - 1 1 1 1 1 - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -4 - - - 5 - - 4 - 6 6 7 6 - 4 5 -4 2 7 5 2 2 6 4 - - - 4 1 - 5 2 -- 5 2 7 7 - 7 4 - 4 6 5 4 - 4 2 -- - - 4 - 4 1 - - 0 0 0 5 - - - -- - - - 0 0 0 0 - - - - - - - - - -1 - - - 0 0 - - - 2 - - 0 1 0 - -3 - - 0 2 2 0 - - 4 - 0 1 1 1 0 -5 - - 0 4 4 0 - - 6 - - 4 4 4 - -7 - - - 4 4 - - - - - - 0 1 0 - -- - - 0 1 1 0 - - - - - - - - - - -- - 3 - - 1 7 - - - 7 4 - - 4 3 -1 - - 0 2 0 - - - 5 4 - 3 - - - -4 - 3 6 1 1 6 - - - 1 - - 4 - 1 -- 7 5 - - - 3 - - - - 3 - - - - -- - - - - - - - - - - - - - - - - -1 - - - 1 - - - - 2 - - - 2 - - -- 3 - - 3 3 - - - - 4 - 4 - 4 - -- 5 - - 5 5 - - - 6 - - 7 1 7 - -7 - - - 6 6 - - - - - - - - - - -- - - - - - - - - - - - - - - - - -2 - - 6 - 2 5 1 - 5 - 4 - 4 - 4 -6 - - 3 - - - 3 - 4 2 0 - - - 5 -- - - 6 - 3 6 - - - - 5 - 5 - - -- - - 3 - 4 2 5 - - - - - - - - -- - - - - - - - - - - - - - - - - -6 - - - 4 - - 3 - 0 3 - - 6 - 0 -- - 7 - 1 - 3 - - 7 - 4 7 - 2 - -5 2 3 2 1 6 - 3 - - - 0 4 3 5 4 -- 7 6 - - 0 - - - 4 3 - - - 4 2 -0 - - - - - 6 - - - - - - - - - - -6 1 2 5 1 6 3 0 - - - - - - - 4 -0 5 2 7 1 6 2 - - 3 - - - - - - -6 7 6 4 0 5 2 6 - - - - - - - 1 -6 1 4 0 6 2 3 - - 0 - - - - - - -- 0 4 5 3 7 6 0 - - - - - - - - - -- - - 0 1 - - - - - - 0 7 0 - - -- - 1 2 2 0 - - - - 0 7 0 7 0 - -- 6 - 7 7 - 6 - - 4 1 6 6 6 4 1 -- 5 - 7 7 - 5 - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - - 5 6 - - - - - - 3 3 3 - - -- - 7 5 3 7 - - - - 3 - 6 - 3 - -2 - - 3 7 - - 1 - 2 2 - 3 - 1 1 -- 0 2 5 6 1 0 - - - - - 3 - - - -- - - 3 7 - - - - - - - - - - - - -- 6 - - - - 2 - - - 2 6 0 6 0 - -- 0 - - - - - - - 6 - - - - - - -- 3 3 2 0 6 0 0 - - 6 - - - - 0 -- - - 6 0 2 6 - - - 2 0 - - - - -- - - - - - - - - - - - - - - - - -0 7 - - - - - - - 1 5 - - - - - -7 2 5 - - - - - - 6 3 4 - - - - -5 5 4 4 - - - - - 3 3 5 3 - - - -1 2 2 5 3 - - - - 1 0 0 7 6 - - -3 3 5 5 7 6 - - - - - - - - - - - -- - 2 6 6 2 - - - - 2 1 1 0 2 - -- 2 3 2 2 0 2 - - 2 3 2 5 2 7 2 -2 4 2 5 2 7 2 0 - 2 4 2 6 6 2 0 -- 2 5 2 2 2 7 2 - - 2 5 6 6 7 2 -- - 2 2 2 2 2 - - - - - - - - - - -- - 0 - - 0 - - - 1 0 0 1 0 0 1 -1 7 7 5 5 7 7 1 - 3 2 - 2 - 2 3 -3 7 - 6 6 - 7 3 - 7 - - 6 - - 7 -4 4 5 - - 5 4 4 - - - - - - - - -- - - - - - - - - - - - - - - - - -- 6 3 - - 3 6 - - 6 - 2 - 2 - 6 -2 - 0 1 1 0 - 2 - 5 0 - 7 - 0 5 -- 5 - 6 6 - 5 - - 7 1 4 - 4 1 7 -7 - 4 - - 4 - 7 - 2 0 - - - 0 2 -- 2 - - - - 2 - - - - - - - - - - -6 1 - - - - 4 0 - 2 7 5 5 5 7 3 -6 1 - - - - 4 0 - 2 5 7 7 7 5 3 -6 1 - - - - 4 0 - 2 0 6 6 6 0 3 -6 1 - - - - 4 0 - - - - - - - - -- - - - - - - - - - - - - - - - - -5 - - 1 1 - - 5 - 5 - 4 - 4 - 5 -- 2 4 - - 4 2 - - 7 2 - - - 2 7 -0 - 0 4 4 0 - 0 - 7 2 - - - 2 7 -- 2 3 - - 3 2 - - 5 - 3 - 3 - 5 -5 - - 6 6 - - 5 - - - - - - - - - -2 2 - - - - 5 5 - 5 - - - - - 2 -5 - - - - - - 2 - 1 - 1 5 1 - 3 -5 2 5 3 1 2 5 2 - 2 0 5 - 2 0 5 -- 3 7 - - 3 7 - - - - 2 0 5 - - -- - - - - - - - - - - - - - - - - -0 6 5 2 3 4 1 7 - - - - - 1 - - -- - - 1 1 - - - - - - 1 - - - - -7 1 4 3 2 5 6 0 - - - - - 1 - - -- - - 1 1 - - - - - - 1 - - - - -0 6 5 2 3 4 1 7 - - - - - - - - - -- - 1 - - 1 - - - - 2 4 - 2 4 - -- 2 3 6 5 3 2 - - - 6 5 - 6 5 - -- - - 7 7 - - - - - - - 7 - - - -1 - - 7 7 - - 3 - 2 - - 7 - - 2 -- 3 4 5 6 4 1 - - - - - - - - - - -1 - - 2 2 - - 2 - 1 3 7 3 7 4 2 -- 1 6 - - 6 2 - - 6 - 7 3 7 - 6 -- 4 2 - - 1 3 - - - - 2 6 1 - - -- 4 3 3 4 4 3 - - - - - - - - - -- - - - - - - - - - - - - - - - - -- - - 5 6 - - - - - - - 3 - - - -- - - 1 2 - - - - - - - 4 - - - -- - - 5 7 - - - - - - - 2 - - - -6 5 4 3 2 1 7 5 - - - - - - - - -- - - - - - - - - - - - - - - - - -- 0 - 1 - 2 - - - - 4 - 5 - 6 - -- 7 - 0 - 2 - - - - 6 - 3 - 6 - -- 1 - 1 - 2 - - - - 3 - 5 - 0 - -- 2 - 4 - 6 - - - - 3 - 6 - 7 - -- - - - - - - - - - - - - - - - - -1 1 2 2 3 3 4 4 - 5 5 6 7 6 5 5 -6 4 3 3 2 2 1 6 - 4 6 5 7 6 3 1 -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - -7 4 - 1 2 - 4 7 - 5 5 - 2 - 4 4 -- 5 - 7 7 - 4 - - 1 0 6 7 6 0 2 -- 2 - 5 3 - 1 - - 1 1 - - - 2 2 -6 1 4 - - 4 2 6 - 5 3 - - - 3 5 -- - - - - - - - - - - - - - - - - -1 5 1 0 0 1 5 1 - 1 2 5 - 5 2 1 -3 6 1 2 2 1 6 3 - 4 3 4 - 4 3 4 -3 4 6 5 5 6 4 3 - 0 2 3 - 3 2 0 -2 3 1 5 5 1 3 2 - - - - - - - - -- - - - - - - - - - - - - - - - - -3 0 2 7 5 7 6 5 - 6 - 1 - 2 - 1 -- 6 4 0 3 4 5 - - - 5 - 1 - 4 - -- 7 3 5 6 5 3 - - 1 - 2 - 4 - 2 -6 4 4 6 6 5 5 1 - - - - - - - - -- - - - - - - - - - - - - - - - diff --git a/build.xml b/build.xml deleted file mode 100644 index b44e65f..0000000 --- a/build.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/jni/Android.mk b/jni/Android.mk deleted file mode 100644 index d5ae4e2..0000000 --- a/jni/Android.mk +++ /dev/null @@ -1,75 +0,0 @@ -# Basic makefile for building libmodplug with Android NDK by PA Casey -# (crow from Peculiar Games). -# -# Go ahead and use it however you like, although attribution is always -# appreciated! -# -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_C_INCLUDES := $(LOCAL_PATH)/libmodplug $(LOCAL_PATH)/.. -LOCAL_CPP_INCLUDES := $(LOCAL_PATH)/libmodplug $(LOCAL_PATH)/.. -# -# -DMODPLUG_TRACKER seems to be necessary in order for libmodplug to -# process the JUMP commands (Bxx in effects column) for song -# repeating, etc. -# -# -DPECULIAR_EXTENSIONS adds some hacky functionality -# setTempo() patternLoop() changePattern() etc -# -# -DPECULIAR_EXP_HACKS for more experimental hacks -# (pattern group change) -# -# -DPECULIAR_ONEBYONE for experimental 1x1 pattern jumping -# (PatternJumper Project) -# -# -DPECULIAR_FOURBYFOUR for future more generalized pattern jumping -# -LOCAL_CFLAGS := -DSMALLER_READS -DHAVE_SINF -DHAVE_SETENV \ - -DMODPLUG_TRACKER -DPECULIAR_EXTENSIONS -DPECULIAR_FOURBYFOUR -LOCAL_LDLIBS := -llog -LOCAL_MODULE := modplug-1.0 -# -# These are all the source files that come in the libmodplug archive -# from sourceforge.net EXCEPT jni_stubs.cpp which has the JNI interface -# code (basically just small stub functions that go on to call the -# actual libmodplug methods). -# -LOCAL_SRC_FILES := fastmix.cpp \ - load_669.cpp \ - load_abc.cpp \ - load_amf.cpp \ - load_ams.cpp \ - load_dbm.cpp \ - load_dmf.cpp \ - load_dsm.cpp \ - load_far.cpp \ - load_it.cpp \ - load_j2b.cpp \ - load_mdl.cpp \ - load_med.cpp \ - load_mid.cpp \ - load_mod.cpp \ - load_mt2.cpp \ - load_mtm.cpp \ - load_okt.cpp \ - load_pat.cpp \ - load_psm.cpp \ - load_ptm.cpp \ - load_s3m.cpp \ - load_stm.cpp \ - load_ult.cpp \ - load_umx.cpp \ - load_wav.cpp \ - load_xm.cpp \ - mmcmp.cpp \ - modplug.cpp \ - snd_dsp.cpp \ - snd_flt.cpp \ - snd_fx.cpp \ - sndfile.cpp \ - sndmix.cpp \ - jni_stubs.cpp - -include $(BUILD_SHARED_LIBRARY) diff --git a/jni/fastmix.cpp b/jni/fastmix.cpp deleted file mode 100644 index 62fc4f2..0000000 --- a/jni/fastmix.cpp +++ /dev/null @@ -1,2388 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque - * Markus Fick spline + fir-resampler -*/ - -#include "stdafx.h" -#include "sndfile.h" -#include - -#ifdef MSC_VER -#pragma bss_seg(".modplug") -#endif - -// Front Mix Buffer (Also room for interleaved rear mix) -int MixSoundBuffer[MIXBUFFERSIZE*4]; - -// Reverb Mix Buffer -#ifndef MODPLUG_NO_REVERB -int MixReverbBuffer[MIXBUFFERSIZE*2]; -extern UINT gnReverbSend; -#endif - -#ifndef MODPLUG_FASTSOUNDLIB -int MixRearBuffer[MIXBUFFERSIZE*2]; -float MixFloatBuffer[MIXBUFFERSIZE*2]; -#endif - -#ifdef MSC_VER -#pragma bss_seg() -#endif - - -extern LONG gnDryROfsVol; -extern LONG gnDryLOfsVol; -extern LONG gnRvbROfsVol; -extern LONG gnRvbLOfsVol; - -// 4x256 taps polyphase FIR resampling filter -extern short int gFastSinc[]; -extern short int gKaiserSinc[]; // 8-taps polyphase -/* - *----------------------------------------------------------------------------- - cubic spline interpolation doc, - (derived from "digital image warping", g. wolberg) - - interpolation polynomial: f(x) = A3*(x-floor(x))**3 + A2*(x-floor(x))**2 + - A1*(x-floor(x)) + A0 - - with Y = equispaced data points (dist=1), YD = first derivates of data points and IP = floor(x) - the A[0..3] can be found by solving - A0 = Y[IP] - A1 = YD[IP] - A2 = 3*(Y[IP+1]-Y[IP])-2.0*YD[IP]-YD[IP+1] - A3 = -2.0 * (Y[IP+1]-Y[IP]) + YD[IP] - YD[IP+1] - - with the first derivates as - YD[IP] = 0.5 * (Y[IP+1] - Y[IP-1]); - YD[IP+1] = 0.5 * (Y[IP+2] - Y[IP]) - - the coefs becomes - A0 = Y[IP] - A1 = YD[IP] - = 0.5*(Y[IP+1] - Y[IP-1]); - A2 = 3.0*(Y[IP+1]-Y[IP])-2.0*YD[IP]-YD[IP+1] - = 3.0*(Y[IP+1]-Y[IP]) - 0.5*2.0*(Y[IP+1]-Y[IP-1]) - 0.5*(Y[IP+2]-Y[IP]) - = 3.0*Y[IP+1] - 3.0*Y[IP] - Y[IP+1] + Y[IP-1] - 0.5*Y[IP+2] + 0.5*Y[IP] - = -0.5*Y[IP+2] + 2.0 * Y[IP+1] - 2.5*Y[IP] + Y[IP-1] - = Y[IP-1] + 2 * Y[IP+1] - 0.5 * (5.0 * Y[IP] + Y[IP+2]) - A3 = -2.0*(Y[IP+1]-Y[IP]) + YD[IP] + YD[IP+1] - = -2.0*Y[IP+1] + 2.0*Y[IP] + 0.5*(Y[IP+1]-Y[IP-1]) + 0.5*(Y[IP+2]-Y[IP]) - = -2.0*Y[IP+1] + 2.0*Y[IP] + 0.5*Y[IP+1] - 0.5*Y[IP-1] + 0.5*Y[IP+2] - 0.5*Y[IP] - = 0.5 * Y[IP+2] - 1.5 * Y[IP+1] + 1.5 * Y[IP] - 0.5 * Y[IP-1] - = 0.5 * (3.0 * (Y[IP] - Y[IP+1]) - Y[IP-1] + YP[IP+2]) - - then interpolated data value is (horner rule) - out = (((A3*x)+A2)*x+A1)*x+A0 - - this gives parts of data points Y[IP-1] to Y[IP+2] of - part x**3 x**2 x**1 x**0 - Y[IP-1] -0.5 1 -0.5 0 - Y[IP] 1.5 -2.5 0 1 - Y[IP+1] -1.5 2 0.5 0 - Y[IP+2] 0.5 -0.5 0 0 - *--------------------------------------------------------------------------- - */ -// number of bits used to scale spline coefs -#define SPLINE_QUANTBITS 14 -#define SPLINE_QUANTSCALE (1L< _LScale) ? _LScale : _LCm1) ); - lut[_LIdx+1] = (signed short)( (_LC0 < -_LScale) ? -_LScale : ((_LC0 > _LScale) ? _LScale : _LC0 ) ); - lut[_LIdx+2] = (signed short)( (_LC1 < -_LScale) ? -_LScale : ((_LC1 > _LScale) ? _LScale : _LC1 ) ); - lut[_LIdx+3] = (signed short)( (_LC2 < -_LScale) ? -_LScale : ((_LC2 > _LScale) ? _LScale : _LC2 ) ); -#ifdef SPLINE_CLAMPFORUNITY - _LSum = lut[_LIdx+0]+lut[_LIdx+1]+lut[_LIdx+2]+lut[_LIdx+3]; - if( _LSum != SPLINE_QUANTSCALE ) - { int _LMax = _LIdx; - if( lut[_LIdx+1]>lut[_LMax] ) _LMax = _LIdx+1; - if( lut[_LIdx+2]>lut[_LMax] ) _LMax = _LIdx+2; - if( lut[_LIdx+3]>lut[_LMax] ) _LMax = _LIdx+3; - lut[_LMax] += ((signed short)SPLINE_QUANTSCALE-_LSum); - } -#endif - } -} - -CzCUBICSPLINE::~CzCUBICSPLINE( ) -{ // nothing to do -} - -CzCUBICSPLINE sspline; - -/* - ------------------------------------------------------------------------------ - fir interpolation doc, - (derived from "an engineer's guide to fir digital filters", n.j. loy) - - calculate coefficients for ideal lowpass filter (with cutoff = fc in - 0..1 (mapped to 0..nyquist)) - c[-N..N] = (i==0) ? fc : sin(fc*pi*i)/(pi*i) - - then apply selected window to coefficients - c[-N..N] *= w(0..N) - with n in 2*N and w(n) being a window function (see loy) - - then calculate gain and scale filter coefs to have unity gain. - ------------------------------------------------------------------------------ -*/ -// quantizer scale of window coefs -#define WFIR_QUANTBITS 15 -#define WFIR_QUANTSCALE (1L<>1) -// cutoff (1.0 == pi/2) -#define WFIR_CUTOFF 0.90f -// wfir type -#define WFIR_HANN 0 -#define WFIR_HAMMING 1 -#define WFIR_BLACKMANEXACT 2 -#define WFIR_BLACKMAN3T61 3 -#define WFIR_BLACKMAN3T67 4 -#define WFIR_BLACKMAN4T92 5 -#define WFIR_BLACKMAN4T74 6 -#define WFIR_KAISER4T 7 -#define WFIR_TYPE WFIR_BLACKMANEXACT -// wfir help -#ifndef M_zPI -#define M_zPI 3.1415926535897932384626433832795 -#endif -#define M_zEPS 1e-8 -#define M_zBESSELEPS 1e-21 - -class CzWINDOWEDFIR -{ -public: - CzWINDOWEDFIR( ); - ~CzWINDOWEDFIR( ); - float coef( int _PCnr, float _POfs, float _PCut, int _PWidth, int _PType ) -//OLD args to coef: float _PPos, float _PFc, int _PLen ) - { - double _LWidthM1 = _PWidth-1; - double _LWidthM1Half = 0.5*_LWidthM1; - double _LPosU = ((double)_PCnr - _POfs); - double _LPos = _LPosU-_LWidthM1Half; - double _LPIdl = 2.0*M_zPI/_LWidthM1; - double _LWc,_LSi; - if( fabs(_LPos)_LScale)?_LScale:_LCoef) ); - } - } -} - -CzWINDOWEDFIR::~CzWINDOWEDFIR() -{ // nothing to do -} - -CzWINDOWEDFIR sfir; - -// ---------------------------------------------------------------------------- -// MIXING MACROS -// ---------------------------------------------------------------------------- -#define SNDMIX_BEGINSAMPLELOOP8\ - register MODCHANNEL * const pChn = pChannel;\ - nPos = pChn->nPosLo;\ - const signed char *p = (signed char *)(pChn->pCurrentSample+pChn->nPos);\ - if (pChn->dwFlags & CHN_STEREO) p += pChn->nPos;\ - int *pvol = pbuffer;\ - do { - -#define SNDMIX_BEGINSAMPLELOOP16\ - register MODCHANNEL * const pChn = pChannel;\ - nPos = pChn->nPosLo;\ - const signed short *p = (signed short *)(pChn->pCurrentSample+(pChn->nPos*2));\ - if (pChn->dwFlags & CHN_STEREO) p += pChn->nPos;\ - int *pvol = pbuffer;\ - do { - -#define SNDMIX_ENDSAMPLELOOP\ - nPos += pChn->nInc;\ - } while (pvol < pbufmax);\ - pChn->nPos += nPos >> 16;\ - pChn->nPosLo = nPos & 0xFFFF; - -#define SNDMIX_ENDSAMPLELOOP8 SNDMIX_ENDSAMPLELOOP -#define SNDMIX_ENDSAMPLELOOP16 SNDMIX_ENDSAMPLELOOP - -////////////////////////////////////////////////////////////////////////////// -// Mono - -// No interpolation -#define SNDMIX_GETMONOVOL8NOIDO\ - int vol = p[nPos >> 16] << 8; - -#define SNDMIX_GETMONOVOL16NOIDO\ - int vol = p[nPos >> 16]; - -// Linear Interpolation -#define SNDMIX_GETMONOVOL8LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol = p[poshi];\ - int destvol = p[poshi+1];\ - int vol = (srcvol<<8) + ((int)(poslo * (destvol - srcvol))); - -#define SNDMIX_GETMONOVOL16LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol = p[poshi];\ - int destvol = p[poshi+1];\ - int vol = srcvol + ((int)(poslo * (destvol - srcvol)) >> 8); - -// spline interpolation (2 guard bits should be enough???) -#define SPLINE_FRACSHIFT ((16-SPLINE_FRACBITS)-2) -#define SPLINE_FRACMASK (((1L<<(16-SPLINE_FRACSHIFT))-1)&~3) - -#define SNDMIX_GETMONOVOL8SPLINE \ - int poshi = nPos >> 16; \ - int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \ - int vol = (CzCUBICSPLINE::lut[poslo ]*(int)p[poshi-1] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[poshi ] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[poshi+2] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[poshi+1]) >> SPLINE_8SHIFT; - -#define SNDMIX_GETMONOVOL16SPLINE \ - int poshi = nPos >> 16; \ - int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \ - int vol = (CzCUBICSPLINE::lut[poslo ]*(int)p[poshi-1] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[poshi ] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[poshi+2] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[poshi+1]) >> SPLINE_16SHIFT; - - -// fir interpolation -#define WFIR_FRACSHIFT (16-(WFIR_FRACBITS+1+WFIR_LOG2WIDTH)) -#define WFIR_FRACMASK ((((1L<<(17-WFIR_FRACSHIFT))-1)&~((1L<> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[poshi+1-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[poshi+2-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[poshi+3-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[poshi+4-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[poshi+5-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[poshi+6-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[poshi+7-4]); \ - vol += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[poshi+8-4]); \ - vol >>= WFIR_8SHIFT; - -#define SNDMIX_GETMONOVOL16FIRFILTER \ - int poshi = nPos >> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol1 = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[poshi+1-4]); \ - vol1 += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[poshi+2-4]); \ - vol1 += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[poshi+3-4]); \ - vol1 += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[poshi+4-4]); \ - int vol2 = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[poshi+5-4]); \ - vol2 += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[poshi+6-4]); \ - vol2 += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[poshi+7-4]); \ - vol2 += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[poshi+8-4]); \ - int vol = ((vol1>>1)+(vol2>>1)) >> (WFIR_16BITSHIFT-1); - -///////////////////////////////////////////////////////////////////////////// -// Stereo - -// No interpolation -#define SNDMIX_GETSTEREOVOL8NOIDO\ - int vol_l = p[(nPos>>16)*2] << 8;\ - int vol_r = p[(nPos>>16)*2+1] << 8; - -#define SNDMIX_GETSTEREOVOL16NOIDO\ - int vol_l = p[(nPos>>16)*2];\ - int vol_r = p[(nPos>>16)*2+1]; - -// Linear Interpolation -#define SNDMIX_GETSTEREOVOL8LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol_l = p[poshi*2];\ - int vol_l = (srcvol_l<<8) + ((int)(poslo * (p[poshi*2+2] - srcvol_l)));\ - int srcvol_r = p[poshi*2+1];\ - int vol_r = (srcvol_r<<8) + ((int)(poslo * (p[poshi*2+3] - srcvol_r))); - -#define SNDMIX_GETSTEREOVOL16LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol_l = p[poshi*2];\ - int vol_l = srcvol_l + ((int)(poslo * (p[poshi*2+2] - srcvol_l)) >> 8);\ - int srcvol_r = p[poshi*2+1];\ - int vol_r = srcvol_r + ((int)(poslo * (p[poshi*2+3] - srcvol_r)) >> 8);\ - -// Spline Interpolation -#define SNDMIX_GETSTEREOVOL8SPLINE \ - int poshi = nPos >> 16; \ - int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \ - int vol_l = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2 ] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2 ] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2 ] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2 ]) >> SPLINE_8SHIFT; \ - int vol_r = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2+1] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2+1] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2+1] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2+1]) >> SPLINE_8SHIFT; - -#define SNDMIX_GETSTEREOVOL16SPLINE \ - int poshi = nPos >> 16; \ - int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \ - int vol_l = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2 ] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2 ] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2 ] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2 ]) >> SPLINE_16SHIFT; \ - int vol_r = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2+1] + \ - CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2+1] + \ - CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2+1] + \ - CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2+1]) >> SPLINE_16SHIFT; - -// fir interpolation -#define SNDMIX_GETSTEREOVOL8FIRFILTER \ - int poshi = nPos >> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol_l = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2 ]); \ - vol_l += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2 ]); \ - vol_l >>= WFIR_8SHIFT; \ - int vol_r = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2+1]); \ - vol_r += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2+1]); \ - vol_r >>= WFIR_8SHIFT; - -#define SNDMIX_GETSTEREOVOL16FIRFILTER \ - int poshi = nPos >> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol1_l = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2 ]); \ - vol1_l += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2 ]); \ - vol1_l += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2 ]); \ - vol1_l += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2 ]); \ - int vol2_l = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2 ]); \ - vol2_l += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2 ]); \ - vol2_l += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2 ]); \ - vol2_l += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2 ]); \ - int vol_l = ((vol1_l>>1)+(vol2_l>>1)) >> (WFIR_16BITSHIFT-1); \ - int vol1_r = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2+1]); \ - vol1_r += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2+1]); \ - vol1_r += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2+1]); \ - vol1_r += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2+1]); \ - int vol2_r = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2+1]); \ - vol2_r += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2+1]); \ - vol2_r += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2+1]); \ - vol2_r += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2+1]); \ - int vol_r = ((vol1_r>>1)+(vol2_r>>1)) >> (WFIR_16BITSHIFT-1); - -///////////////////////////////////////////////////////////////////////////// - -#define SNDMIX_STOREMONOVOL\ - pvol[0] += vol * pChn->nRightVol;\ - pvol[1] += vol * pChn->nLeftVol;\ - pvol += 2; - -#define SNDMIX_STORESTEREOVOL\ - pvol[0] += vol_l * pChn->nRightVol;\ - pvol[1] += vol_r * pChn->nLeftVol;\ - pvol += 2; - -#define SNDMIX_STOREFASTMONOVOL\ - int v = vol * pChn->nRightVol;\ - pvol[0] += v;\ - pvol[1] += v;\ - pvol += 2; - -#define SNDMIX_RAMPMONOVOL\ - nRampLeftVol += pChn->nLeftRamp;\ - nRampRightVol += pChn->nRightRamp;\ - pvol[0] += vol * (nRampRightVol >> VOLUMERAMPPRECISION);\ - pvol[1] += vol * (nRampLeftVol >> VOLUMERAMPPRECISION);\ - pvol += 2; - -#define SNDMIX_RAMPFASTMONOVOL\ - nRampRightVol += pChn->nRightRamp;\ - int fastvol = vol * (nRampRightVol >> VOLUMERAMPPRECISION);\ - pvol[0] += fastvol;\ - pvol[1] += fastvol;\ - pvol += 2; - -#define SNDMIX_RAMPSTEREOVOL\ - nRampLeftVol += pChn->nLeftRamp;\ - nRampRightVol += pChn->nRightRamp;\ - pvol[0] += vol_l * (nRampRightVol >> VOLUMERAMPPRECISION);\ - pvol[1] += vol_r * (nRampLeftVol >> VOLUMERAMPPRECISION);\ - pvol += 2; - - -/////////////////////////////////////////////////// -// Resonant Filters - -// Mono -#define MIX_BEGIN_FILTER\ - int fy1 = pChannel->nFilter_Y1;\ - int fy2 = pChannel->nFilter_Y2;\ - -#define MIX_END_FILTER\ - pChannel->nFilter_Y1 = fy1;\ - pChannel->nFilter_Y2 = fy2; - -#define SNDMIX_PROCESSFILTER\ - vol = (vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\ - fy2 = fy1;\ - fy1 = vol;\ - -// Stereo -#define MIX_BEGIN_STEREO_FILTER\ - int fy1 = pChannel->nFilter_Y1;\ - int fy2 = pChannel->nFilter_Y2;\ - int fy3 = pChannel->nFilter_Y3;\ - int fy4 = pChannel->nFilter_Y4;\ - -#define MIX_END_STEREO_FILTER\ - pChannel->nFilter_Y1 = fy1;\ - pChannel->nFilter_Y2 = fy2;\ - pChannel->nFilter_Y3 = fy3;\ - pChannel->nFilter_Y4 = fy4;\ - -#define SNDMIX_PROCESSSTEREOFILTER\ - vol_l = (vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\ - vol_r = (vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1 + 4096) >> 13;\ - fy2 = fy1; fy1 = vol_l;\ - fy4 = fy3; fy3 = vol_r;\ - -////////////////////////////////////////////////////////// -// Interfaces - -typedef VOID (MPPASMCALL * LPMIXINTERFACE)(MODCHANNEL *, int *, int *); - -#define BEGIN_MIX_INTERFACE(func)\ - VOID MPPASMCALL func(MODCHANNEL *pChannel, int *pbuffer, int *pbufmax)\ - {\ - LONG nPos; - -#define END_MIX_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - } - -// Volume Ramps -#define BEGIN_RAMPMIX_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - LONG nRampRightVol = pChannel->nRampRightVol;\ - LONG nRampLeftVol = pChannel->nRampLeftVol; - -#define END_RAMPMIX_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - pChannel->nRampRightVol = nRampRightVol;\ - pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\ - pChannel->nRampLeftVol = nRampLeftVol;\ - pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\ - } - -#define BEGIN_FASTRAMPMIX_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - LONG nRampRightVol = pChannel->nRampRightVol; - -#define END_FASTRAMPMIX_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - pChannel->nRampRightVol = nRampRightVol;\ - pChannel->nRampLeftVol = nRampRightVol;\ - pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\ - pChannel->nLeftVol = pChannel->nRightVol;\ - } - - -// Mono Resonant Filters -#define BEGIN_MIX_FLT_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - MIX_BEGIN_FILTER - - -#define END_MIX_FLT_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - MIX_END_FILTER\ - } - -#define BEGIN_RAMPMIX_FLT_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - LONG nRampRightVol = pChannel->nRampRightVol;\ - LONG nRampLeftVol = pChannel->nRampLeftVol;\ - MIX_BEGIN_FILTER - -#define END_RAMPMIX_FLT_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - MIX_END_FILTER\ - pChannel->nRampRightVol = nRampRightVol;\ - pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\ - pChannel->nRampLeftVol = nRampLeftVol;\ - pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\ - } - -// Stereo Resonant Filters -#define BEGIN_MIX_STFLT_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - MIX_BEGIN_STEREO_FILTER - - -#define END_MIX_STFLT_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - MIX_END_STEREO_FILTER\ - } - -#define BEGIN_RAMPMIX_STFLT_INTERFACE(func)\ - BEGIN_MIX_INTERFACE(func)\ - LONG nRampRightVol = pChannel->nRampRightVol;\ - LONG nRampLeftVol = pChannel->nRampLeftVol;\ - MIX_BEGIN_STEREO_FILTER - -#define END_RAMPMIX_STFLT_INTERFACE()\ - SNDMIX_ENDSAMPLELOOP\ - MIX_END_STEREO_FILTER\ - pChannel->nRampRightVol = nRampRightVol;\ - pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\ - pChannel->nRampLeftVol = nRampLeftVol;\ - pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\ - } - - -///////////////////////////////////////////////////// -// - -void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples); -void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples); -void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); -void X86_StereoMixToFloat(const int *, float *, float *, UINT nCount); -void X86_FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount); - -///////////////////////////////////////////////////// -// Mono samples functions - -BEGIN_MIX_INTERFACE(Mono8BitMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono16BitMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono8BitLinearMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono16BitLinearMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono8BitSplineMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono16BitSplineMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono8BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Mono16BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_STOREMONOVOL -END_MIX_INTERFACE() - - -// Volume Ramps -BEGIN_RAMPMIX_INTERFACE(Mono8BitRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono16BitRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono8BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono16BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono8BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono16BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono8BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Mono16BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_INTERFACE() - - -////////////////////////////////////////////////////// -// Fast mono mix for leftvol=rightvol (1 less imul) - -BEGIN_MIX_INTERFACE(FastMono8BitMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono16BitMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono8BitLinearMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono16BitLinearMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono8BitSplineMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono16BitSplineMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono8BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(FastMono16BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_STOREFASTMONOVOL -END_MIX_INTERFACE() - - -// Fast Ramps -BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - -BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_RAMPFASTMONOVOL -END_FASTRAMPMIX_INTERFACE() - - -////////////////////////////////////////////////////// -// Stereo samples - -BEGIN_MIX_INTERFACE(Stereo8BitMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8NOIDO - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo16BitMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16NOIDO - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo8BitLinearMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8LINEAR - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo16BitLinearMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16LINEAR - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo8BitSplineMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8SPLINE - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo16BitSplineMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16SPLINE - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo8BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8FIRFILTER - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - -BEGIN_MIX_INTERFACE(Stereo16BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16FIRFILTER - SNDMIX_STORESTEREOVOL -END_MIX_INTERFACE() - - -// Volume Ramps -BEGIN_RAMPMIX_INTERFACE(Stereo8BitRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8NOIDO - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo16BitRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16NOIDO - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo8BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8LINEAR - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo16BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16LINEAR - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo8BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8SPLINE - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo16BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16SPLINE - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo8BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8FIRFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - -BEGIN_RAMPMIX_INTERFACE(Stereo16BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16FIRFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_INTERFACE() - - - -////////////////////////////////////////////////////// -// Resonant Filter Mix - -#ifndef NO_FILTER - -// Mono Filter Mix -BEGIN_MIX_FLT_INTERFACE(FilterMono8BitMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono16BitMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono8BitLinearMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono16BitLinearMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono8BitSplineMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono16BitSplineMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono8BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -BEGIN_MIX_FLT_INTERFACE(FilterMono16BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_PROCESSFILTER - SNDMIX_STOREMONOVOL -END_MIX_FLT_INTERFACE() - -// Filter + Ramp -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8NOIDO - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16NOIDO - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8LINEAR - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16LINEAR - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8SPLINE - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16SPLINE - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETMONOVOL8FIRFILTER - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - -BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETMONOVOL16FIRFILTER - SNDMIX_PROCESSFILTER - SNDMIX_RAMPMONOVOL -END_RAMPMIX_FLT_INTERFACE() - - -// Stereo Filter Mix -BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8NOIDO - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16NOIDO - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitLinearMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8LINEAR - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitLinearMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16LINEAR - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitSplineMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8SPLINE - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitSplineMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16SPLINE - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8FIRFILTER - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitFirFilterMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16FIRFILTER - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_STORESTEREOVOL -END_MIX_STFLT_INTERFACE() - -// Stereo Filter + Ramp -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8NOIDO - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16NOIDO - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8LINEAR - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitLinearRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16LINEAR - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8SPLINE - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitSplineRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16SPLINE - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP8 - SNDMIX_GETSTEREOVOL8FIRFILTER - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - -BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitFirFilterRampMix) - SNDMIX_BEGINSAMPLELOOP16 - SNDMIX_GETSTEREOVOL16FIRFILTER - SNDMIX_PROCESSSTEREOFILTER - SNDMIX_RAMPSTEREOVOL -END_RAMPMIX_STFLT_INTERFACE() - - -#else -// Mono -#define FilterMono8BitMix Mono8BitMix -#define FilterMono16BitMix Mono16BitMix -#define FilterMono8BitLinearMix Mono8BitLinearMix -#define FilterMono16BitLinearMix Mono16BitLinearMix -#define FilterMono8BitSplineMix Mono8BitSplineMix -#define FilterMono16BitSplineMix Mono16BitSplineMix -#define FilterMono8BitFirFilterMix Mono8BitFirFilterMix -#define FilterMono16BitFirFilterMix Mono16BitFirFilterMix -#define FilterMono8BitRampMix Mono8BitRampMix -#define FilterMono16BitRampMix Mono16BitRampMix -#define FilterMono8BitLinearRampMix Mono8BitLinearRampMix -#define FilterMono16BitLinearRampMix Mono16BitLinearRampMix -#define FilterMono8BitSplineRampMix Mono8BitSplineRampMix -#define FilterMono16BitSplineRampMix Mono16BitSplineRampMix -#define FilterMono8BitFirFilterRampMix Mono8BitFirFilterRampMix -#define FilterMono16BitFirFilterRampMix Mono16BitFirFilterRampMix -// Stereo -#define FilterStereo8BitMix Stereo8BitMix -#define FilterStereo16BitMix Stereo16BitMix -#define FilterStereo8BitLinearMix Stereo8BitLinearMix -#define FilterStereo16BitLinearMix Stereo16BitLinearMix -#define FilterStereo8BitSplineMix Stereo8BitSplineMix -#define FilterStereo16BitSplineMix Stereo16BitSplineMix -#define FilterStereo8BitFirFilterMix Stereo8BitFirFilterMix -#define FilterStereo16BitFirFilterMix Stereo16BitFirFilterMix -#define FilterStereo8BitRampMix Stereo8BitRampMix -#define FilterStereo16BitRampMix Stereo16BitRampMix -#define FilterStereo8BitLinearRampMix Stereo8BitLinearRampMix -#define FilterStereo16BitLinearRampMix Stereo16BitLinearRampMix -#define FilterStereo8BitSplineRampMix Stereo8BitSplineRampMix -#define FilterStereo16BitSplineRampMix Stereo16BitSplineRampMix -#define FilterStereo8BitFirFilterRampMix Stereo8BitFirFilterRampMix -#define FilterStereo16BitFirFilterRampMix Stereo16BitFirFilterRampMix - -#endif - -/////////////////////////////////////////////////////////////////////////////// -// -// Mix function tables -// -// -// Index is as follow: -// [b1-b0] format (8-bit-mono, 16-bit-mono, 8-bit-stereo, 16-bit-stereo) -// [b2] ramp -// [b3] filter -// [b5-b4] src type -// - -#define MIXNDX_16BIT 0x01 -#define MIXNDX_STEREO 0x02 -#define MIXNDX_RAMP 0x04 -#define MIXNDX_FILTER 0x08 -#define MIXNDX_LINEARSRC 0x10 -#define MIXNDX_SPLINESRC 0x20 -#define MIXNDX_FIRSRC 0x30 - -const LPMIXINTERFACE gpMixFunctionTable[2*2*16] = -{ - // No SRC - Mono8BitMix, Mono16BitMix, Stereo8BitMix, Stereo16BitMix, - Mono8BitRampMix, Mono16BitRampMix, Stereo8BitRampMix, - Stereo16BitRampMix, - // No SRC, Filter - FilterMono8BitMix, FilterMono16BitMix, FilterStereo8BitMix, - FilterStereo16BitMix, FilterMono8BitRampMix, FilterMono16BitRampMix, - FilterStereo8BitRampMix, FilterStereo16BitRampMix, - // Linear SRC - Mono8BitLinearMix, Mono16BitLinearMix, Stereo8BitLinearMix, - Stereo16BitLinearMix, Mono8BitLinearRampMix, Mono16BitLinearRampMix, - Stereo8BitLinearRampMix,Stereo16BitLinearRampMix, - // Linear SRC, Filter - FilterMono8BitLinearMix, FilterMono16BitLinearMix, - FilterStereo8BitLinearMix, FilterStereo16BitLinearMix, - FilterMono8BitLinearRampMix, FilterMono16BitLinearRampMix, - FilterStereo8BitLinearRampMix, FilterStereo16BitLinearRampMix, - - // FirFilter SRC - Mono8BitSplineMix, Mono16BitSplineMix, Stereo8BitSplineMix, - Stereo16BitSplineMix, Mono8BitSplineRampMix, Mono16BitSplineRampMix, - Stereo8BitSplineRampMix,Stereo16BitSplineRampMix, - // Spline SRC, Filter - FilterMono8BitSplineMix, FilterMono16BitSplineMix, - FilterStereo8BitSplineMix, FilterStereo16BitSplineMix, - FilterMono8BitSplineRampMix, FilterMono16BitSplineRampMix, - FilterStereo8BitSplineRampMix, FilterStereo16BitSplineRampMix, - - // FirFilter SRC - Mono8BitFirFilterMix, Mono16BitFirFilterMix, Stereo8BitFirFilterMix, - Stereo16BitFirFilterMix, Mono8BitFirFilterRampMix, - Mono16BitFirFilterRampMix, Stereo8BitFirFilterRampMix, - Stereo16BitFirFilterRampMix, - // FirFilter SRC, Filter - FilterMono8BitFirFilterMix, FilterMono16BitFirFilterMix, - FilterStereo8BitFirFilterMix, FilterStereo16BitFirFilterMix, - FilterMono8BitFirFilterRampMix, FilterMono16BitFirFilterRampMix, - FilterStereo8BitFirFilterRampMix, FilterStereo16BitFirFilterRampMix -}; - -const LPMIXINTERFACE gpFastMixFunctionTable[2*2*16] = -{ - // No SRC - FastMono8BitMix, FastMono16BitMix, Stereo8BitMix, Stereo16BitMix, - FastMono8BitRampMix, FastMono16BitRampMix, Stereo8BitRampMix, - Stereo16BitRampMix, - // No SRC, Filter - FilterMono8BitMix, FilterMono16BitMix, FilterStereo8BitMix, - FilterStereo16BitMix, FilterMono8BitRampMix, FilterMono16BitRampMix, - FilterStereo8BitRampMix, FilterStereo16BitRampMix, - // Linear SRC - FastMono8BitLinearMix, FastMono16BitLinearMix, Stereo8BitLinearMix, - Stereo16BitLinearMix, FastMono8BitLinearRampMix, - FastMono16BitLinearRampMix, Stereo8BitLinearRampMix, - Stereo16BitLinearRampMix, - // Linear SRC, Filter - FilterMono8BitLinearMix, FilterMono16BitLinearMix, - FilterStereo8BitLinearMix, FilterStereo16BitLinearMix, - FilterMono8BitLinearRampMix, FilterMono16BitLinearRampMix, - FilterStereo8BitLinearRampMix, FilterStereo16BitLinearRampMix, - - // Spline SRC - Mono8BitSplineMix, Mono16BitSplineMix, Stereo8BitSplineMix, - Stereo16BitSplineMix, Mono8BitSplineRampMix, Mono16BitSplineRampMix, - Stereo8BitSplineRampMix, Stereo16BitSplineRampMix, - // Spline SRC, Filter - FilterMono8BitSplineMix, FilterMono16BitSplineMix, - FilterStereo8BitSplineMix, FilterStereo16BitSplineMix, - FilterMono8BitSplineRampMix, FilterMono16BitSplineRampMix, - FilterStereo8BitSplineRampMix, FilterStereo16BitSplineRampMix, - - // FirFilter SRC - Mono8BitFirFilterMix, Mono16BitFirFilterMix, Stereo8BitFirFilterMix, - Stereo16BitFirFilterMix, Mono8BitFirFilterRampMix, - Mono16BitFirFilterRampMix, Stereo8BitFirFilterRampMix, - Stereo16BitFirFilterRampMix, - // FirFilter SRC, Filter - FilterMono8BitFirFilterMix, FilterMono16BitFirFilterMix, - FilterStereo8BitFirFilterMix, FilterStereo16BitFirFilterMix, - FilterMono8BitFirFilterRampMix, FilterMono16BitFirFilterRampMix, - FilterStereo8BitFirFilterRampMix, FilterStereo16BitFirFilterRampMix, -}; - - -///////////////////////////////////////////////////////////////////////// - -static LONG MPPFASTCALL GetSampleCount(MODCHANNEL *pChn, LONG nSamples) -//--------------------------------------------------------------------- -{ - LONG nLoopStart = (pChn->dwFlags & CHN_LOOP) ? pChn->nLoopStart : 0; - LONG nInc = pChn->nInc; - - if ((nSamples <= 0) || (!nInc) || (!pChn->nLength)) return 0; - // Under zero ? - if ((LONG)pChn->nPos < nLoopStart) - { - if (nInc < 0) - { - // Invert loop for bidi loops - LONG nDelta = ((nLoopStart - pChn->nPos) << 16) - (pChn->nPosLo & 0xffff); - pChn->nPos = nLoopStart | (nDelta>>16); - pChn->nPosLo = nDelta & 0xffff; - if (((LONG)pChn->nPos < nLoopStart) || - (pChn->nPos >= (nLoopStart+pChn->nLength)/2)) - { - pChn->nPos = nLoopStart; pChn->nPosLo = 0; - } - nInc = -nInc; - pChn->nInc = nInc; - pChn->dwFlags &= ~(CHN_PINGPONGFLAG); // go forward - if ((!(pChn->dwFlags & CHN_LOOP)) || (pChn->nPos >= pChn->nLength)) - { - pChn->nPos = pChn->nLength; - pChn->nPosLo = 0; - return 0; - } - } else - { - // We probably didn't hit the loop end yet - // (first loop), so we do nothing - if ((LONG)pChn->nPos < 0) pChn->nPos = 0; - } - } else - // Past the end - if (pChn->nPos >= pChn->nLength) - { - if (!(pChn->dwFlags & CHN_LOOP)) return 0; // not looping -> stop this channel - if (pChn->dwFlags & CHN_PINGPONGLOOP) - { - // Invert loop - if (nInc > 0) - { - nInc = -nInc; - pChn->nInc = nInc; - } - pChn->dwFlags |= CHN_PINGPONGFLAG; - // adjust loop position - LONG nDeltaHi = (pChn->nPos - pChn->nLength); - LONG nDeltaLo = 0x10000 - (pChn->nPosLo & 0xffff); - pChn->nPos = pChn->nLength - nDeltaHi - (nDeltaLo>>16); - pChn->nPosLo = nDeltaLo & 0xffff; - if ((pChn->nPos <= pChn->nLoopStart) || - (pChn->nPos >= pChn->nLength)) - pChn->nPos = pChn->nLength-1; - } else - { - if (nInc < 0) // This is a bug - { - nInc = -nInc; - pChn->nInc = nInc; - } - // Restart at loop start - pChn->nPos += nLoopStart - pChn->nLength; - if ((LONG)pChn->nPos < nLoopStart) - pChn->nPos = pChn->nLoopStart; - } - } - LONG nPos = pChn->nPos; - // too big increment, and/or too small loop length - if (nPos < nLoopStart) - { - if ((nPos < 0) || (nInc < 0)) return 0; - } - if ((nPos < 0) || (nPos >= (LONG)pChn->nLength)) return 0; - LONG nPosLo = (USHORT)pChn->nPosLo, nSmpCount = nSamples; - if (nInc < 0) - { - LONG nInv = -nInc; - LONG maxsamples = 16384 / ((nInv>>16)+1); - if (maxsamples < 2) maxsamples = 2; - if (nSamples > maxsamples) nSamples = maxsamples; - LONG nDeltaHi = (nInv>>16) * (nSamples - 1); - LONG nDeltaLo = (nInv&0xffff) * (nSamples - 1); - LONG nPosDest = nPos - nDeltaHi + ((nPosLo - nDeltaLo) >> 16); - if (nPosDest < nLoopStart) - { - nSmpCount = (ULONG)(((((LONGLONG)nPos - nLoopStart) << 16) + nPosLo - 1) / nInv) + 1; - } - } else - { - LONG maxsamples = 16384 / ((nInc>>16)+1); - if (maxsamples < 2) maxsamples = 2; - if (nSamples > maxsamples) nSamples = maxsamples; - LONG nDeltaHi = (nInc>>16) * (nSamples - 1); - LONG nDeltaLo = (nInc&0xffff) * (nSamples - 1); - LONG nPosDest = nPos + nDeltaHi + ((nPosLo + nDeltaLo)>>16); - if (nPosDest >= (LONG)pChn->nLength) - { - nSmpCount = (ULONG)(((((LONGLONG)pChn->nLength - nPos) << 16) - nPosLo - 1) / nInc) + 1; - } - } - if (nSmpCount <= 1) return 1; - if (nSmpCount > nSamples) return nSamples; - return nSmpCount; -} - - -UINT CSoundFile::CreateStereoMix(int count) -//----------------------------------------- -{ - LPLONG pOfsL, pOfsR; - DWORD nchused, nchmixed; - - if (!count) return 0; -#ifndef MODPLUG_FASTSOUNDLIB - if (gnChannels > 2) X86_InitMixBuffer(MixRearBuffer, count*2); -#endif - nchused = nchmixed = 0; - for (UINT nChn=0; nChnpCurrentSample) continue; - nMasterCh = (ChnMix[nChn] < m_nChannels) ? ChnMix[nChn]+1 : pChannel->nMasterChn; - pOfsR = &gnDryROfsVol; - pOfsL = &gnDryLOfsVol; - nFlags = 0; - if (pChannel->dwFlags & CHN_16BIT) nFlags |= MIXNDX_16BIT; - if (pChannel->dwFlags & CHN_STEREO) nFlags |= MIXNDX_STEREO; - #ifndef NO_FILTER - if (pChannel->dwFlags & CHN_FILTER) nFlags |= MIXNDX_FILTER; - #endif - if (!(pChannel->dwFlags & CHN_NOIDO)) - { - // use hq-fir mixer? - if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == - (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE) ) - nFlags += MIXNDX_FIRSRC; - else if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == SNDMIX_HQRESAMPLER ) - nFlags += MIXNDX_SPLINESRC; - else - nFlags += MIXNDX_LINEARSRC; // use - } - if ((nFlags < 0x40) && (pChannel->nLeftVol == pChannel->nRightVol) - && ((!pChannel->nRampLength) || (pChannel->nLeftRamp == pChannel->nRightRamp))) - { - pMixFuncTable = gpFastMixFunctionTable; - } else - { - pMixFuncTable = gpMixFunctionTable; - } - nsamples = count; -#ifndef MODPLUG_NO_REVERB - pbuffer = (gdwSoundSetup & SNDMIX_REVERB) ? MixReverbBuffer : MixSoundBuffer; - if (pChannel->dwFlags & CHN_NOREVERB) pbuffer = MixSoundBuffer; - if (pChannel->dwFlags & CHN_REVERB) pbuffer = MixReverbBuffer; - if (pbuffer == MixReverbBuffer) - { - if (!gnReverbSend) memset(MixReverbBuffer, 0, count * 8); - gnReverbSend += count; - } -#else - pbuffer = MixSoundBuffer; -#endif - nchused++; - //////////////////////////////////////////////////// - SampleLooping: - UINT nrampsamples = nsamples; - if (pChannel->nRampLength > 0) - { - if ((LONG)nrampsamples > pChannel->nRampLength) nrampsamples = pChannel->nRampLength; - } - if ((nSmpCount = GetSampleCount(pChannel, nrampsamples)) <= 0) - { - // Stopping the channel - pChannel->pCurrentSample = NULL; - pChannel->nLength = 0; - pChannel->nPos = 0; - pChannel->nPosLo = 0; - pChannel->nRampLength = 0; - X86_EndChannelOfs(pChannel, pbuffer, nsamples); - *pOfsR += pChannel->nROfs; - *pOfsL += pChannel->nLOfs; - pChannel->nROfs = pChannel->nLOfs = 0; - pChannel->dwFlags &= ~CHN_PINGPONGFLAG; - continue; - } - // Should we mix this channel ? - UINT naddmix; - if (((nchmixed >= m_nMaxMixChannels) && (!(gdwSoundSetup & SNDMIX_DIRECTTODISK))) - || ((!pChannel->nRampLength) && (!(pChannel->nLeftVol|pChannel->nRightVol)))) - { - LONG delta = (pChannel->nInc * (LONG)nSmpCount) + (LONG)pChannel->nPosLo; - pChannel->nPosLo = delta & 0xFFFF; - pChannel->nPos += (delta >> 16); - pChannel->nROfs = pChannel->nLOfs = 0; - pbuffer += nSmpCount*2; - naddmix = 0; - } else - // Do mixing - { - // Choose function for mixing - LPMIXINTERFACE pMixFunc; - pMixFunc = (pChannel->nRampLength) ? pMixFuncTable[nFlags|MIXNDX_RAMP] : pMixFuncTable[nFlags]; - int *pbufmax = pbuffer + (nSmpCount*2); - pChannel->nROfs = - *(pbufmax-2); - pChannel->nLOfs = - *(pbufmax-1); - pMixFunc(pChannel, pbuffer, pbufmax); - pChannel->nROfs += *(pbufmax-2); - pChannel->nLOfs += *(pbufmax-1); - pbuffer = pbufmax; - naddmix = 1; - - } - nsamples -= nSmpCount; - if (pChannel->nRampLength) - { - pChannel->nRampLength -= nSmpCount; - if (pChannel->nRampLength <= 0) - { - pChannel->nRampLength = 0; - pChannel->nRightVol = pChannel->nNewRightVol; - pChannel->nLeftVol = pChannel->nNewLeftVol; - pChannel->nRightRamp = pChannel->nLeftRamp = 0; - if ((pChannel->dwFlags & CHN_NOTEFADE) && (!(pChannel->nFadeOutVol))) - { - pChannel->nLength = 0; - pChannel->pCurrentSample = NULL; - } - } - } - if (nsamples > 0) goto SampleLooping; - nchmixed += naddmix; - } - return nchused; -} - - -#ifdef MSC_VER -#pragma warning (disable:4100) -#endif - -// Clip and convert to 8 bit -#ifdef MSC_VER -__declspec(naked) DWORD MPPASMCALL X86_Convert32To8(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -//------------------------------------------------------------------------------ -{ - _asm { - push ebx - push esi - push edi - mov ebx, 16[esp] // ebx = 8-bit buffer - mov esi, 20[esp] // esi = pBuffer - mov edi, 24[esp] // edi = lSampleCount - mov eax, 28[esp] - mov ecx, dword ptr [eax] // ecx = clipmin - mov eax, 32[esp] - mov edx, dword ptr [eax] // edx = clipmax -cliploop: - mov eax, dword ptr [esi] - inc ebx - cdq - and edx, (1 << (24-MIXING_ATTENUATION)) - 1 - add eax, edx - cmp eax, MIXING_CLIPMIN - jl cliplow - cmp eax, MIXING_CLIPMAX - jg cliphigh - cmp eax, ecx - jl updatemin - cmp eax, edx - jg updatemax -cliprecover: - add esi, 4 - sar eax, 24-MIXING_ATTENUATION - xor eax, 0x80 - dec edi - mov byte ptr [ebx-1], al - jnz cliploop - mov eax, 28[esp] - mov dword ptr [eax], ecx - mov eax, 32[esp] - mov dword ptr [eax], edx - mov eax, 24[esp] - pop edi - pop esi - pop ebx - ret -updatemin: - mov ecx, eax - jmp cliprecover -updatemax: - mov edx, eax - jmp cliprecover -cliplow: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMIN - jmp cliprecover -cliphigh: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMAX - jmp cliprecover - } -} -#else //MSC_VER -//---GCCFIX: Asm replaced with C function -// The C version was written by Rani Assaf , I believe -DWORD MPPASMCALL X86_Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -{ - int vumin = *lpMin, vumax = *lpMax; - unsigned char *p = (unsigned char *)lp8; - for (UINT i=0; i MIXING_CLIPMAX) - n = MIXING_CLIPMAX; - if (n < vumin) - vumin = n; - else if (n > vumax) - vumax = n; - p[i] = (n >> (24-MIXING_ATTENUATION)) ^ 0x80; // 8-bit unsigned - } - *lpMin = vumin; - *lpMax = vumax; - return lSampleCount; -} -#endif //MSC_VER, else - - -#ifdef MSC_VER -// Clip and convert to 16 bit -__declspec(naked) DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -//------------------------------------------------------------------------------ -{ - _asm { - push ebx - push esi - push edi - mov ebx, 16[esp] // ebx = 16-bit buffer - mov eax, 28[esp] - mov esi, 20[esp] // esi = pBuffer - mov ecx, dword ptr [eax] // ecx = clipmin - mov edi, 24[esp] // edi = lSampleCount - mov eax, 32[esp] - push ebp - mov ebp, dword ptr [eax] // edx = clipmax -cliploop: - mov eax, dword ptr [esi] - add ebx, 2 - cdq - and edx, (1 << (16-MIXING_ATTENUATION)) - 1 - add esi, 4 - add eax, edx - cmp eax, MIXING_CLIPMIN - jl cliplow - cmp eax, MIXING_CLIPMAX - jg cliphigh - cmp eax, ecx - jl updatemin - cmp eax, ebp - jg updatemax -cliprecover: - sar eax, 16-MIXING_ATTENUATION - dec edi - mov word ptr [ebx-2], ax - jnz cliploop - mov edx, ebp - pop ebp - mov eax, 28[esp] - mov dword ptr [eax], ecx - mov eax, 32[esp] - mov dword ptr [eax], edx - mov eax, 24[esp] - pop edi - shl eax, 1 - pop esi - pop ebx - ret -updatemin: - mov ecx, eax - jmp cliprecover -updatemax: - mov ebp, eax - jmp cliprecover -cliplow: - mov ecx, MIXING_CLIPMIN - mov ebp, MIXING_CLIPMAX - mov eax, MIXING_CLIPMIN - jmp cliprecover -cliphigh: - mov ecx, MIXING_CLIPMIN - mov ebp, MIXING_CLIPMAX - mov eax, MIXING_CLIPMAX - jmp cliprecover - } -} -#else //MSC_VER -//---GCCFIX: Asm replaced with C function -// The C version was written by Rani Assaf , I believe -DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -{ - int vumin = *lpMin, vumax = *lpMax; - signed short *p = (signed short *)lp16; - for (UINT i=0; i MIXING_CLIPMAX) - n = MIXING_CLIPMAX; - if (n < vumin) - vumin = n; - else if (n > vumax) - vumax = n; - p[i] = n >> (16-MIXING_ATTENUATION); // 16-bit signed - } - *lpMin = vumin; - *lpMax = vumax; - return lSampleCount * 2; -} -#endif //MSC_VER, else - -#ifdef MSC_VER -// Clip and convert to 24 bit -__declspec(naked) DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -//------------------------------------------------------------------------------ -{ - _asm { - push ebx - push esi - push edi - mov ebx, 16[esp] // ebx = 8-bit buffer - mov esi, 20[esp] // esi = pBuffer - mov edi, 24[esp] // edi = lSampleCount - mov eax, 28[esp] - mov ecx, dword ptr [eax] // ecx = clipmin - mov eax, 32[esp] - push ebp - mov edx, dword ptr [eax] // edx = clipmax -cliploop: - mov eax, dword ptr [esi] - mov ebp, eax - sar ebp, 31 - and ebp, (1 << (8-MIXING_ATTENUATION)) - 1 - add eax, ebp - cmp eax, MIXING_CLIPMIN - jl cliplow - cmp eax, MIXING_CLIPMAX - jg cliphigh - cmp eax, ecx - jl updatemin - cmp eax, edx - jg updatemax -cliprecover: - add ebx, 3 - sar eax, 8-MIXING_ATTENUATION - add esi, 4 - mov word ptr [ebx-3], ax - shr eax, 16 - dec edi - mov byte ptr [ebx-1], al - jnz cliploop - pop ebp - mov eax, 28[esp] - mov dword ptr [eax], ecx - mov eax, 32[esp] - mov dword ptr [eax], edx - mov edx, 24[esp] - mov eax, edx - pop edi - shl eax, 1 - pop esi - add eax, edx - pop ebx - ret -updatemin: - mov ecx, eax - jmp cliprecover -updatemax: - mov edx, eax - jmp cliprecover -cliplow: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMIN - jmp cliprecover -cliphigh: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMAX - jmp cliprecover - } -} -#else //MSC_VER -//---GCCFIX: Asm replaced with C function -DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -{ - UINT i ; - int vumin = *lpMin, vumax = *lpMax; - int n,p ; - unsigned char* buf = (unsigned char*)lp16 ; - - for ( i=0; i MIXING_CLIPMAX) - n = MIXING_CLIPMAX; - if (n < vumin) - vumin = n; - else if (n > vumax) - vumax = n; - p = n >> (8-MIXING_ATTENUATION) ; // 24-bit signed -#ifdef WORDS_BIGENDIAN - buf[i*3+0] = p & 0xFF0000 >> 24; - buf[i*3+1] = p & 0x00FF00 >> 16 ; - buf[i*3+2] = p & 0x0000FF ; -#else - buf[i*3+0] = p & 0x0000FF ; - buf[i*3+1] = p & 0x00FF00 >> 16; - buf[i*3+2] = p & 0xFF0000 >> 24; -#endif - } - *lpMin = vumin; - *lpMax = vumax; - return lSampleCount * 3; -} -#endif - -#ifdef MSC_VER -// Clip and convert to 32 bit -__declspec(naked) DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -//------------------------------------------------------------------------------ -{ - _asm { - push ebx - push esi - push edi - mov ebx, 16[esp] // ebx = 32-bit buffer - mov esi, 20[esp] // esi = pBuffer - mov edi, 24[esp] // edi = lSampleCount - mov eax, 28[esp] - mov ecx, dword ptr [eax] // ecx = clipmin - mov eax, 32[esp] - mov edx, dword ptr [eax] // edx = clipmax -cliploop: - mov eax, dword ptr [esi] - add ebx, 4 - add esi, 4 - cmp eax, MIXING_CLIPMIN - jl cliplow - cmp eax, MIXING_CLIPMAX - jg cliphigh - cmp eax, ecx - jl updatemin - cmp eax, edx - jg updatemax -cliprecover: - shl eax, MIXING_ATTENUATION - dec edi - mov dword ptr [ebx-4], eax - jnz cliploop - mov eax, 28[esp] - mov dword ptr [eax], ecx - mov eax, 32[esp] - mov dword ptr [eax], edx - mov edx, 24[esp] - pop edi - mov eax, edx - pop esi - shl eax, 2 - pop ebx - ret -updatemin: - mov ecx, eax - jmp cliprecover -updatemax: - mov edx, eax - jmp cliprecover -cliplow: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMIN - jmp cliprecover -cliphigh: - mov ecx, MIXING_CLIPMIN - mov edx, MIXING_CLIPMAX - mov eax, MIXING_CLIPMAX - jmp cliprecover - } -} -#else -//---GCCFIX: Asm replaced with C function -DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) -{ - UINT i ; - int vumin = *lpMin, vumax = *lpMax; - int32_t *p = (int32_t *)lp16; - - for ( i=0; i MIXING_CLIPMAX) - n = MIXING_CLIPMAX; - if (n < vumin) - vumin = n; - else if (n > vumax) - vumax = n; - p[i] = n << MIXING_ATTENUATION; // 32-bit signed - } - *lpMin = vumin; - *lpMax = vumax; - return lSampleCount * 4; -} -#endif - - -#ifdef MSC_VER -void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples) -//------------------------------------------------------------ -{ - _asm { - mov ecx, nSamples - mov esi, pBuffer - xor eax, eax - mov edx, ecx - shr ecx, 2 - and edx, 3 - jz unroll4x -loop1x: - add esi, 4 - dec edx - mov dword ptr [esi-4], eax - jnz loop1x -unroll4x: - or ecx, ecx - jnz loop4x - jmp done -loop4x: - add esi, 16 - dec ecx - mov dword ptr [esi-16], eax - mov dword ptr [esi-12], eax - mov dword ptr [esi-8], eax - mov dword ptr [esi-4], eax - jnz loop4x -done:; - } -} -#else -//---GCCFIX: Asm replaced with C function -// Will fill in later. -void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples) -{ - memset(pBuffer, 0, nSamples * sizeof(int)); -} -#endif - - -#ifdef MSC_VER -__declspec(naked) void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples) -//------------------------------------------------------------------------------ -{ - _asm { - push ebx - push ebp - push esi - push edi - mov ecx, 28[esp] // ecx = samplecount - mov esi, 20[esp] // esi = front buffer - mov edi, 24[esp] // edi = rear buffer - lea esi, [esi+ecx*4] // esi = &front[N] - lea edi, [edi+ecx*4] // edi = &rear[N] - lea ebx, [esi+ecx*4] // ebx = &front[N*2] -interleaveloop: - mov eax, dword ptr [esi-8] - mov edx, dword ptr [esi-4] - sub ebx, 16 - mov ebp, dword ptr [edi-8] - mov dword ptr [ebx], eax - mov dword ptr [ebx+4], edx - mov eax, dword ptr [edi-4] - sub esi, 8 - sub edi, 8 - dec ecx - mov dword ptr [ebx+8], ebp - mov dword ptr [ebx+12], eax - jnz interleaveloop - pop edi - pop esi - pop ebp - pop ebx - ret - } -} -#else -//---GCCFIX: Asm replaced with C function -// Multichannel not supported. -void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples) -{ -} -#endif - - -#ifdef MSC_VER -VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples) -//------------------------------------------------------------- -{ - _asm { - mov ecx, nSamples - mov esi, pMixBuf - mov edi, esi -stloop: - mov eax, dword ptr [esi] - mov edx, dword ptr [esi+4] - add edi, 4 - add esi, 8 - add eax, edx - sar eax, 1 - dec ecx - mov dword ptr [edi-4], eax - jnz stloop - } -} -#else -//---GCCFIX: Asm replaced with C function -VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples) -{ - UINT j; - for(UINT i = 0; i < nSamples; i++) - { - j = i << 1; - pMixBuf[i] = (pMixBuf[j] + pMixBuf[j + 1]) >> 1; - } -} -#endif - -#define OFSDECAYSHIFT 8 -#define OFSDECAYMASK 0xFF - - -#ifdef MSC_VER -void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs) -//------------------------------------------------------------------------------ -{ - _asm { - mov edi, pBuffer - mov ecx, nSamples - mov eax, lpROfs - mov edx, lpLOfs - mov eax, [eax] - mov edx, [edx] - or ecx, ecx - jz fill_loop - mov ebx, eax - or ebx, edx - jz fill_loop -ofsloop: - mov ebx, eax - mov esi, edx - neg ebx - neg esi - sar ebx, 31 - sar esi, 31 - and ebx, OFSDECAYMASK - and esi, OFSDECAYMASK - add ebx, eax - add esi, edx - sar ebx, OFSDECAYSHIFT - sar esi, OFSDECAYSHIFT - sub eax, ebx - sub edx, esi - mov ebx, eax - or ebx, edx - jz fill_loop - add edi, 8 - dec ecx - mov [edi-8], eax - mov [edi-4], edx - jnz ofsloop -fill_loop: - mov ebx, ecx - and ebx, 3 - jz fill4x -fill1x: - mov [edi], eax - mov [edi+4], edx - add edi, 8 - dec ebx - jnz fill1x -fill4x: - shr ecx, 2 - or ecx, ecx - jz done -fill4xloop: - mov [edi], eax - mov [edi+4], edx - mov [edi+8], eax - mov [edi+12], edx - add edi, 8*4 - dec ecx - mov [edi-16], eax - mov [edi-12], edx - mov [edi-8], eax - mov [edi-4], edx - jnz fill4xloop -done: - mov esi, lpROfs - mov edi, lpLOfs - mov [esi], eax - mov [edi], edx - } -} -#else -//---GCCFIX: Asm replaced with C function -#define OFSDECAYSHIFT 8 -#define OFSDECAYMASK 0xFF -void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs) -//---------------------------------------------------------------------------- -{ - int rofs = *lpROfs; - int lofs = *lpLOfs; - - if ((!rofs) && (!lofs)) - { - X86_InitMixBuffer(pBuffer, nSamples*2); - return; - } - for (UINT i=0; i>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT; - int x_l = (lofs + (((-lofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT; - rofs -= x_r; - lofs -= x_l; - pBuffer[i*2] = x_r; - pBuffer[i*2+1] = x_l; - } - *lpROfs = rofs; - *lpLOfs = lofs; -} -#endif - -#ifdef MSC_VER -void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples) -//------------------------------------------------------------------------------ -{ - _asm { - mov esi, pChannel - mov edi, pBuffer - mov ecx, nSamples - mov eax, dword ptr [esi+MODCHANNEL.nROfs] - mov edx, dword ptr [esi+MODCHANNEL.nLOfs] - or ecx, ecx - jz brkloop -ofsloop: - mov ebx, eax - mov esi, edx - neg ebx - neg esi - sar ebx, 31 - sar esi, 31 - and ebx, OFSDECAYMASK - and esi, OFSDECAYMASK - add ebx, eax - add esi, edx - sar ebx, OFSDECAYSHIFT - sar esi, OFSDECAYSHIFT - sub eax, ebx - sub edx, esi - mov ebx, eax - add dword ptr [edi], eax - add dword ptr [edi+4], edx - or ebx, edx - jz brkloop - add edi, 8 - dec ecx - jnz ofsloop -brkloop: - mov esi, pChannel - mov dword ptr [esi+MODCHANNEL.nROfs], eax - mov dword ptr [esi+MODCHANNEL.nLOfs], edx - } -} -#else -//---GCCFIX: Asm replaced with C function -// Will fill in later. -void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples) -{ - int rofs = pChannel->nROfs; - int lofs = pChannel->nLOfs; - - if ((!rofs) && (!lofs)) return; - for (UINT i=0; i>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT; - int x_l = (lofs + (((-lofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT; - rofs -= x_r; - lofs -= x_l; - pBuffer[i*2] += x_r; - pBuffer[i*2+1] += x_l; - } - pChannel->nROfs = rofs; - pChannel->nLOfs = lofs; -} -#endif - - -////////////////////////////////////////////////////////////////////////////////// -// Automatic Gain Control - -#ifndef NO_AGC - -// Limiter -#define MIXING_LIMITMAX (0x08100000) -#define MIXING_LIMITMIN (-MIXING_LIMITMAX) - -#ifdef MSC_VER -__declspec(naked) UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC) -//------------------------------------------------------------------------------ -{ - __asm { - push ebx - push ebp - push esi - push edi - mov esi, 20[esp] // esi = pBuffer+i - mov ecx, 24[esp] // ecx = i - mov edi, 28[esp] // edi = AGC (0..256) -agcloop: - mov eax, dword ptr [esi] - imul edi - shrd eax, edx, AGC_PRECISION - add esi, 4 - cmp eax, MIXING_LIMITMIN - jl agcupdate - cmp eax, MIXING_LIMITMAX - jg agcupdate -agcrecover: - dec ecx - mov dword ptr [esi-4], eax - jnz agcloop - mov eax, edi - pop edi - pop esi - pop ebp - pop ebx - ret -agcupdate: - dec edi - jmp agcrecover - } -} - -#pragma warning (default:4100) -#else -// Version for GCC -UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC) -{ - int x; - - while(nSamples) - { - x = ((int64_t)(*pBuffer) * nAGC) >> AGC_PRECISION; - - if((x < MIXING_LIMITMIN) || (x > MIXING_LIMITMAX)) - nAGC--; - - *pBuffer = x; - - pBuffer++; - nSamples--; - } - - return nAGC; -} -#endif - -void CSoundFile::ProcessAGC(int count) -//------------------------------------ -{ - static DWORD gAGCRecoverCount = 0; - UINT agc = X86_AGC(MixSoundBuffer, count, gnAGC); - // Some kind custom law, so that the AGC stays quite stable, but slowly - // goes back up if the sound level stays below a level inversely - // proportional to the AGC level. (J'me comprends) - if ((agc >= gnAGC) && (gnAGC < AGC_UNITY) && (gnVUMeter < (0xFF - (gnAGC >> (AGC_PRECISION-7))) )) - { - gAGCRecoverCount += count; - UINT agctimeout = gdwMixingFreq + gnAGC; - if (gnChannels >= 2) agctimeout <<= 1; - if (gAGCRecoverCount >= agctimeout) - { - gAGCRecoverCount = 0; - gnAGC++; - } - } else - { - gnAGC = agc; - gAGCRecoverCount = 0; - } -} - - - -void CSoundFile::ResetAGC() -//------------------------- -{ - gnAGC = AGC_UNITY; -} - -#endif // NO_AGC diff --git a/jni/jni_stubs.cpp b/jni/jni_stubs.cpp deleted file mode 100644 index be8b1c9..0000000 --- a/jni/jni_stubs.cpp +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Quick-n-dirty JNI interface for using libmodplug in - * Android (P.A. Casey www.peculiar-games.com) - * - * go ahead and use it however you like, although - * attribution is always appreciated! - */ - -/* - * JNI and your interface class headers. - */ -#include -#include - -#include "stdafx.h" -#include "modplug.h" -#include "sndfile.h" - -#include "andmodplug_PlayerThread.h" - -struct _ModPlugFile -{ - CSoundFile mSoundFile; -}; - -const ModPlug_Settings gSettings8000 = -{ - MODPLUG_ENABLE_OVERSAMPLING | - MODPLUG_ENABLE_NOISE_REDUCTION | - MODPLUG_ENABLE_REVERB, - - 2, - 16, - 8000, - MODPLUG_RESAMPLE_LINEAR, - 128, - 32, - 50, - 100, - 0, - 0, - 0 -}; - -const ModPlug_Settings gSettings16000 = -{ - MODPLUG_ENABLE_OVERSAMPLING | - MODPLUG_ENABLE_NOISE_REDUCTION | - MODPLUG_ENABLE_REVERB, - - 2, - 16, - 16000, - MODPLUG_RESAMPLE_LINEAR, - 128, - 32, - 50, - 100, - 0, - 0, - 0 -}; - -const ModPlug_Settings gSettings22000 = -{ - MODPLUG_ENABLE_OVERSAMPLING | - MODPLUG_ENABLE_NOISE_REDUCTION | - MODPLUG_ENABLE_REVERB, - - 2, - 16, - 22000, - MODPLUG_RESAMPLE_LINEAR, - 128, - 32, - 50, - 100, - 0, - 0, - 0 -}; - -const ModPlug_Settings gSettings32000 = -{ - MODPLUG_ENABLE_OVERSAMPLING | - MODPLUG_ENABLE_NOISE_REDUCTION | - MODPLUG_ENABLE_REVERB, - - 2, - 16, - 32000, - MODPLUG_RESAMPLE_LINEAR, - 128, - 32, - 50, - 100, - 0, - 0, - 0 -}; - -// -// ADD FOLLOWING JNI INTERFACE FUNCTIONS after the header files -// -// ************************************************************ -// Start of JNI stub code -// ************************************************************ -ModPlugFile* currmodFile; - -#define SAMPLEBUFFERSIZE 40000 - -unsigned char samplebuffer[SAMPLEBUFFERSIZE]; - -int currsample; - -/* - * DIAB hack to change tempo!! - */ -int DIABtempochange; -int DIABtempooverride; -int DIABholdpattern; -int DIABnextpattern; -int DIABpatternchanged; -int DIABoverridejump; -int DIABforcedpatternchange; - -/* - * More generalized pattern jumping... - */ -int ANDMODPLUGpatternfrom; -int ANDMODPLUGpatternto; -int ANDMODPLUGpendingfrom; -int ANDMODPLUGpendingto; -int ANDMODPLUGpatternrangeset; -int ANDMODPLUGnextpattern; -int ANDMODPLUGnextpatternmode; -int ANDMODPLUGjumpeffect; -int ANDMODPLUGlogoutput; - -/* - * Class: com_peculiar_1games_andmodplug_PlayerThread - * Method: ModPlug_Init - * Signature: (I)Z - */ -JNIEXPORT jboolean JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1Init - (JNIEnv *env, jclass cls, jint rate) -{ - /* - * If trying to make this truly re-entrant, separate buffers could be - * allocated here. - */ - __android_log_print(ANDROID_LOG_INFO, "JNI_STUBS", "Initializing modplug with rate %d", rate); - - switch (rate) - { - case 8000: - ModPlug_SetSettings(&gSettings8000); - break; - case 16000: - ModPlug_SetSettings(&gSettings16000); - break; - case 22000: - ModPlug_SetSettings(&gSettings22000); - break; - case 32000: - ModPlug_SetSettings(&gSettings32000); - break; - case 44100: - /* - * This is the default, so settings needn't be changed. - */ - break; - } - - currmodFile = NULL; - DIABtempochange = 0; - DIABtempooverride = 0; - DIABpatternchanged = 0; - ANDMODPLUGpatternrangeset = 0; - ANDMODPLUGnextpattern = -1; - ANDMODPLUGnextpatternmode = 0; - ANDMODPLUGjumpeffect = -1; - ANDMODPLUGlogoutput = 0; - - return JNI_TRUE; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_JLoad - * Signature: ([BI)Z - */ -JNIEXPORT jboolean JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1JLoad - (JNIEnv *env, jobject obj, jbyteArray buffer, jint size) -{ - int csize = (int) size; - - /* - * Set the current sample as already beyond end of buffer (so a reload - * happens immediately). - */ - currsample = SAMPLEBUFFERSIZE+1; - - /* - * Convert from Java buffer into a C buffer. - */ - jbyte* bytes = env->GetByteArrayElements(buffer, 0); - currmodFile = ModPlug_Load(bytes, csize); - env->ReleaseByteArrayElements(buffer, bytes, 0); - - DIABpatternchanged = 0; - ANDMODPLUGpatternfrom = 0; - ANDMODPLUGpatternto = 0; - ANDMODPLUGpendingfrom = 0; - ANDMODPLUGpendingto = 0; - ANDMODPLUGpatternrangeset = 0; - ANDMODPLUGnextpattern = -1; - ANDMODPLUGnextpatternmode = 0; - ANDMODPLUGjumpeffect = -1; - - if (currmodFile != NULL) - { - return JNI_TRUE; - } - else - { - return JNI_FALSE; - } -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_JGetName - * Signature: ()Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1JGetName - (JNIEnv *env, jobject obj) -{ - if (currmodFile != NULL) - return env->NewStringUTF(ModPlug_GetName(currmodFile)); - else - return NULL; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_JNumChannels - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1JNumChannels - (JNIEnv *env, jobject obj) -{ - jint numchannels = 0; - - if (currmodFile != NULL) - numchannels = ModPlug_NumChannels(currmodFile); - return numchannels; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetCurrentPos - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetCurrentPos - (JNIEnv *, jobject) -{ - jint curr = 0; - - if (currmodFile != NULL) - curr = currmodFile->mSoundFile.GetCurrentPos(); - return curr; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetMaxPos - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetMaxPos - (JNIEnv *, jobject) -{ - jint maxpos = 0; - - if (currmodFile != NULL) - maxpos = currmodFile->mSoundFile.GetMaxPosition(); - return maxpos; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetCurrentOrder - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetCurrentOrder - (JNIEnv *env, jobject obj) -{ - jint curr = 0; - - if (currmodFile != NULL) - curr = ModPlug_GetCurrentOrder(currmodFile); - return curr; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetCurrentPattern - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetCurrentPattern - (JNIEnv *env, jobject obj) -{ - jint curr = 0; - - if (currmodFile != NULL) - curr = ModPlug_GetCurrentPattern(currmodFile); - return curr; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetCurrentRow - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetCurrentRow - (JNIEnv *env, jobject obj) -{ - jint curr = 0; - - if (currmodFile != NULL) - curr = ModPlug_GetCurrentRow(currmodFile); - return curr; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_JGetSoundData - * Signature: ([SI)I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1JGetSoundData - (JNIEnv *env, jobject obj, jshortArray jbuffer, jint size) -{ - jint smpsize = 0; - - if (currmodFile == NULL) - return 0; - -#ifndef SMALLER_READS - if (currsample >= SAMPLEBUFFERSIZE) - { - /* - * Need to read another buffer full of sample data. - */ - smpsize = ModPlug_Read(currmodFile, samplebuffer, SAMPLEBUFFERSIZE); - if (smpsize) - { - currsample = 0; - } - } -#else // SMALLER_READS - /* - * In this mode, we read in exactly how much Java requested to improve - * frame rate. - */ - smpsize = ModPlug_Read(currmodFile, samplebuffer, size*sizeof(jshort)); - currsample = 0; -#endif // SMALLER_READS - - /* - * Now convert the C sample buffer data to a java short array. - */ - if (size && samplebuffer && (smpsize || currsample < SAMPLEBUFFERSIZE)) - { - env->SetShortArrayRegion(jbuffer, 0 ,size, (jshort *) (((char *) samplebuffer)+currsample)); - currsample += size*sizeof(jshort); - - return size; - } - else - { - return 0; - } -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_JUnload - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1JUnload - (JNIEnv *env, jclass cls) -{ - if (currmodFile != NULL) - { - ModPlug_Unload(currmodFile); - currmodFile = NULL; - } - - return JNI_TRUE; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_CloseDown - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1CloseDown - (JNIEnv *env, jclass cls) -{ - /* - * Maybe for a proper re-entrant library, need to handle shutdown - * stuff, deallocting buffers etc., but for my crappy, hacky single- - * entry version, do nothing much... - */ - - return JNI_TRUE; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_GetNativeTempo - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1GetNativeTempo - (JNIEnv *env, jclass cls) -{ - if (currmodFile != NULL) - return currmodFile->mSoundFile.m_nMusicTempo; - else - return 0; -} - -/* - * Class: com_peculiargames_modplayer_PlayerThread - * Method: ModPlug_ChangeTempo - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1ChangeTempo - (JNIEnv *env, jclass cls, jint tc) -{ - /* - * Hack the tempo. - */ - DIABtempochange = tc; -} - -/* - * Class: com_peculiargames_modplayer_PlayerThread - * Method: ModPlug_SetTempo - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetTempo - (JNIEnv *env, jclass cls, jint to) -{ - /* - * Hack the tempo. - */ - DIABtempooverride = to; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_ChangePattern - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1ChangePattern - (JNIEnv *env, jclass cls, jint newpattern) -{ - DIABnextpattern = newpattern-1; - DIABpatternchanged = 0; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_RepeatPattern - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1RepeatPattern - (JNIEnv *env, jclass cls, jint pattern) -{ - DIABholdpattern = 1; - DIABnextpattern = pattern-1; - DIABpatternchanged = 0; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_CheckPatternChange - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1CheckPatternChange - (JNIEnv *env, jclass cls) -{ - if (DIABpatternchanged) - { - DIABpatternchanged = 0; - return JNI_TRUE; - } - else - return JNI_FALSE; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_SetPatternLoopMode - * Signature: (Z)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetPatternLoopMode - (JNIEnv *env, jclass cls, jboolean flag) -{ - if (flag == JNI_TRUE) - DIABholdpattern = 1; - else - DIABholdpattern = 0; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_SetPatternLoopRange - * Signature: (III)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetPatternLoopRange - (JNIEnv *env, jclass cls, jint from, jint to, jint when) -{ - if (ANDMODPLUGpatternrangeset == 0) - { - ANDMODPLUGpatternrangeset = 1; - ANDMODPLUGpatternfrom = from; - ANDMODPLUGpatternto = to; - __android_log_print(ANDROID_LOG_INFO, "JNI_STUBS", "ANDMODPLUGpatternfrom=%d to=%d", - ANDMODPLUGpatternfrom, ANDMODPLUGpatternto); - } - else - { - ANDMODPLUGpendingfrom = from; - ANDMODPLUGpendingto = to; - __android_log_print(ANDROID_LOG_INFO, "JNI_STUBS", "ANDMODPLUGpendingfrom=%d to=%d", - ANDMODPLUGpendingfrom, ANDMODPLUGpendingto); - } - - switch(when) - { - case com_peculiargames_andmodplug_PlayerThread_PATTERN_CHANGE_IMMEDIATE: - ANDMODPLUGpatternfrom = ANDMODPLUGpendingfrom; - ANDMODPLUGpatternto = ANDMODPLUGpendingto; - break; - case com_peculiargames_andmodplug_PlayerThread_PATTERN_CHANGE_AFTER_CURRENT: - if (currmodFile != NULL) - ANDMODPLUGpatternto = currmodFile->mSoundFile.GetCurrentPattern(); - break; - case com_peculiargames_andmodplug_PlayerThread_PATTERN_CHANGE_AFTER_GROUP: - default: - break; - } -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_SetCurrentPattern - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetCurrentPattern - (JNIEnv *env, jobject obj, jint pattern) -{ - ANDMODPLUGnextpattern = pattern; - ANDMODPLUGnextpatternmode = 1; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_SetNextPattern - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetNextPattern - (JNIEnv *env, jobject obj, jint pattern) -{ - ANDMODPLUGnextpattern = pattern; - ANDMODPLUGnextpatternmode = 0; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_LogOutput - * Signature: (Z)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1LogOutput - (JNIEnv *env, jclass cls, jboolean flag) -{ - if (flag == JNI_TRUE) - ANDMODPLUGlogoutput = 1; - else - ANDMODPLUGlogoutput = 0; -} - -/* - * Class: com_peculiargames_andmodplug_PlayerThread - * Method: ModPlug_SetLoopCount - * Signature: (I)V - */ -JNIEXPORT void JNICALL Java_com_peculiargames_andmodplug_PlayerThread_ModPlug_1SetLoopCount - (JNIEnv *env, jclass cls, jint loopcount) -{ - ModPlug_Settings settings; - - ModPlug_GetSettings(&settings); - settings.mLoopCount = loopcount; - ModPlug_SetSettings(&settings); -} - -// ************************************************************ -// End of JNI stub code for libmodplug -// ************************************************************ diff --git a/jni/libmodplug/it_defs.h b/jni/libmodplug/it_defs.h deleted file mode 100644 index 89cb456..0000000 --- a/jni/libmodplug/it_defs.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef _ITDEFS_H_ -#define _ITDEFS_H_ - -#pragma pack(1) - -typedef struct tagITFILEHEADER -{ - DWORD id; // 0x4D504D49 - CHAR songname[26]; - WORD reserved1; // 0x1004 - WORD ordnum; - WORD insnum; - WORD smpnum; - WORD patnum; - WORD cwtv; - WORD cmwt; - WORD flags; - WORD special; - BYTE globalvol; - BYTE mv; - BYTE speed; - BYTE tempo; - BYTE sep; - BYTE zero; - WORD msglength; - DWORD msgoffset; - DWORD reserved2; - BYTE chnpan[64]; - BYTE chnvol[64]; -} ITFILEHEADER; - - -typedef struct tagITENVELOPE -{ - BYTE flags; - BYTE num; - BYTE lpb; - BYTE lpe; - BYTE slb; - BYTE sle; - BYTE data[25*3]; - BYTE reserved; -} ITENVELOPE; - -// Old Impulse Instrument Format (cmwt < 0x200) -typedef struct tagITOLDINSTRUMENT -{ - DWORD id; // IMPI = 0x49504D49 - CHAR filename[12]; // DOS file name - BYTE zero; - BYTE flags; - BYTE vls; - BYTE vle; - BYTE sls; - BYTE sle; - WORD reserved1; - WORD fadeout; - BYTE nna; - BYTE dnc; - WORD trkvers; - BYTE nos; - BYTE reserved2; - CHAR name[26]; - WORD reserved3[3]; - BYTE keyboard[240]; - BYTE volenv[200]; - BYTE nodes[50]; -} ITOLDINSTRUMENT; - - -// Impulse Instrument Format -typedef struct tagITINSTRUMENT -{ - DWORD id; - CHAR filename[12]; - BYTE zero; - BYTE nna; - BYTE dct; - BYTE dca; - WORD fadeout; - signed char pps; - BYTE ppc; - BYTE gbv; - BYTE dfp; - BYTE rv; - BYTE rp; - WORD trkvers; - BYTE nos; - BYTE reserved1; - CHAR name[26]; - BYTE ifc; - BYTE ifr; - BYTE mch; - BYTE mpr; - WORD mbank; - BYTE keyboard[240]; - ITENVELOPE volenv; - ITENVELOPE panenv; - ITENVELOPE pitchenv; - BYTE dummy[4]; // was 7, but IT v2.17 saves 554 bytes -} ITINSTRUMENT; - - -// IT Sample Format -typedef struct ITSAMPLESTRUCT -{ - DWORD id; // 0x53504D49 - CHAR filename[12]; - BYTE zero; - BYTE gvl; - BYTE flags; - BYTE vol; - CHAR name[26]; - BYTE cvt; - BYTE dfp; - DWORD length; - DWORD loopbegin; - DWORD loopend; - DWORD C5Speed; - DWORD susloopbegin; - DWORD susloopend; - DWORD samplepointer; - BYTE vis; - BYTE vid; - BYTE vir; - BYTE vit; -} ITSAMPLESTRUCT; - -#pragma pack() - -extern BYTE autovibit2xm[8]; -extern BYTE autovibxm2it[8]; - -#endif diff --git a/jni/libmodplug/sndfile.h b/jni/libmodplug/sndfile.h deleted file mode 100644 index ed7d47e..0000000 --- a/jni/libmodplug/sndfile.h +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque , - * Adam Goode (endian and char fixes for PPC) -*/ - -#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) -#include "config.h" -#define CONFIG_H_INCLUDED 1 -#endif - -#ifndef __SNDFILE_H -#define __SNDFILE_H - -#ifdef UNDER_CE -int _strnicmp(const char *str1,const char *str2, int n); -#endif - -#ifndef LPCBYTE -typedef const BYTE * LPCBYTE; -#endif - -#define MOD_AMIGAC2 0x1AB -#define MAX_SAMPLE_LENGTH 16000000 -#define MAX_SAMPLE_RATE 192000 -#define MAX_ORDERS 256 -#define MAX_PATTERNS 240 -#define MAX_SAMPLES 240 -#define MAX_INSTRUMENTS MAX_SAMPLES -#ifdef MODPLUG_FASTSOUNDLIB -#define MAX_CHANNELS 80 -#else -#define MAX_CHANNELS 128 -#endif -#define MAX_BASECHANNELS 64 -#define MAX_ENVPOINTS 32 -#define MIN_PERIOD 0x0020 -#define MAX_PERIOD 0xFFFF -#define MAX_PATTERNNAME 32 -#define MAX_CHANNELNAME 20 -#define MAX_INFONAME 80 -#define MAX_EQ_BANDS 6 -#define MAX_MIXPLUGINS 8 - - -#define MOD_TYPE_NONE 0x00 -#define MOD_TYPE_MOD 0x01 -#define MOD_TYPE_S3M 0x02 -#define MOD_TYPE_XM 0x04 -#define MOD_TYPE_MED 0x08 -#define MOD_TYPE_MTM 0x10 -#define MOD_TYPE_IT 0x20 -#define MOD_TYPE_669 0x40 -#define MOD_TYPE_ULT 0x80 -#define MOD_TYPE_STM 0x100 -#define MOD_TYPE_FAR 0x200 -#define MOD_TYPE_WAV 0x400 -#define MOD_TYPE_AMF 0x800 -#define MOD_TYPE_AMS 0x1000 -#define MOD_TYPE_DSM 0x2000 -#define MOD_TYPE_MDL 0x4000 -#define MOD_TYPE_OKT 0x8000 -#define MOD_TYPE_MID 0x10000 -#define MOD_TYPE_DMF 0x20000 -#define MOD_TYPE_PTM 0x40000 -#define MOD_TYPE_DBM 0x80000 -#define MOD_TYPE_MT2 0x100000 -#define MOD_TYPE_AMF0 0x200000 -#define MOD_TYPE_PSM 0x400000 -#define MOD_TYPE_J2B 0x800000 -#define MOD_TYPE_ABC 0x1000000 -#define MOD_TYPE_PAT 0x2000000 -#define MOD_TYPE_UMX 0x80000000 // Fake type -#define MAX_MODTYPE 24 - - - -// Channel flags: -// Bits 0-7: Sample Flags -#define CHN_16BIT 0x01 -#define CHN_LOOP 0x02 -#define CHN_PINGPONGLOOP 0x04 -#define CHN_SUSTAINLOOP 0x08 -#define CHN_PINGPONGSUSTAIN 0x10 -#define CHN_PANNING 0x20 -#define CHN_STEREO 0x40 -#define CHN_PINGPONGFLAG 0x80 -// Bits 8-31: Channel Flags -#define CHN_MUTE 0x100 -#define CHN_KEYOFF 0x200 -#define CHN_NOTEFADE 0x400 -#define CHN_SURROUND 0x800 -#define CHN_NOIDO 0x1000 -#define CHN_HQSRC 0x2000 -#define CHN_FILTER 0x4000 -#define CHN_VOLUMERAMP 0x8000 -#define CHN_VIBRATO 0x10000 -#define CHN_TREMOLO 0x20000 -#define CHN_PANBRELLO 0x40000 -#define CHN_PORTAMENTO 0x80000 -#define CHN_GLISSANDO 0x100000 -#define CHN_VOLENV 0x200000 -#define CHN_PANENV 0x400000 -#define CHN_PITCHENV 0x800000 -#define CHN_FASTVOLRAMP 0x1000000 -#define CHN_EXTRALOUD 0x2000000 -#define CHN_REVERB 0x4000000 -#define CHN_NOREVERB 0x8000000 - - -#define ENV_VOLUME 0x0001 -#define ENV_VOLSUSTAIN 0x0002 -#define ENV_VOLLOOP 0x0004 -#define ENV_PANNING 0x0008 -#define ENV_PANSUSTAIN 0x0010 -#define ENV_PANLOOP 0x0020 -#define ENV_PITCH 0x0040 -#define ENV_PITCHSUSTAIN 0x0080 -#define ENV_PITCHLOOP 0x0100 -#define ENV_SETPANNING 0x0200 -#define ENV_FILTER 0x0400 -#define ENV_VOLCARRY 0x0800 -#define ENV_PANCARRY 0x1000 -#define ENV_PITCHCARRY 0x2000 - -#define CMD_NONE 0 -#define CMD_ARPEGGIO 1 -#define CMD_PORTAMENTOUP 2 -#define CMD_PORTAMENTODOWN 3 -#define CMD_TONEPORTAMENTO 4 -#define CMD_VIBRATO 5 -#define CMD_TONEPORTAVOL 6 -#define CMD_VIBRATOVOL 7 -#define CMD_TREMOLO 8 -#define CMD_PANNING8 9 -#define CMD_OFFSET 10 -#define CMD_VOLUMESLIDE 11 -#define CMD_POSITIONJUMP 12 -#define CMD_VOLUME 13 -#define CMD_PATTERNBREAK 14 -#define CMD_RETRIG 15 -#define CMD_SPEED 16 -#define CMD_TEMPO 17 -#define CMD_TREMOR 18 -#define CMD_MODCMDEX 19 -#define CMD_S3MCMDEX 20 -#define CMD_CHANNELVOLUME 21 -#define CMD_CHANNELVOLSLIDE 22 -#define CMD_GLOBALVOLUME 23 -#define CMD_GLOBALVOLSLIDE 24 -#define CMD_KEYOFF 25 -#define CMD_FINEVIBRATO 26 -#define CMD_PANBRELLO 27 -#define CMD_XFINEPORTAUPDOWN 28 -#define CMD_PANNINGSLIDE 29 -#define CMD_SETENVPOSITION 30 -#define CMD_MIDI 31 - - -// Volume Column commands -#define VOLCMD_VOLUME 1 -#define VOLCMD_PANNING 2 -#define VOLCMD_VOLSLIDEUP 3 -#define VOLCMD_VOLSLIDEDOWN 4 -#define VOLCMD_FINEVOLUP 5 -#define VOLCMD_FINEVOLDOWN 6 -#define VOLCMD_VIBRATOSPEED 7 -#define VOLCMD_VIBRATO 8 -#define VOLCMD_PANSLIDELEFT 9 -#define VOLCMD_PANSLIDERIGHT 10 -#define VOLCMD_TONEPORTAMENTO 11 -#define VOLCMD_PORTAUP 12 -#define VOLCMD_PORTADOWN 13 - -#define RSF_16BIT 0x04 -#define RSF_STEREO 0x08 - -#define RS_PCM8S 0 // 8-bit signed -#define RS_PCM8U 1 // 8-bit unsigned -#define RS_PCM8D 2 // 8-bit delta values -#define RS_ADPCM4 3 // 4-bit ADPCM-packed -#define RS_PCM16D 4 // 16-bit delta values -#define RS_PCM16S 5 // 16-bit signed -#define RS_PCM16U 6 // 16-bit unsigned -#define RS_PCM16M 7 // 16-bit motorola order -#define RS_STPCM8S (RS_PCM8S|RSF_STEREO) // stereo 8-bit signed -#define RS_STPCM8U (RS_PCM8U|RSF_STEREO) // stereo 8-bit unsigned -#define RS_STPCM8D (RS_PCM8D|RSF_STEREO) // stereo 8-bit delta values -#define RS_STPCM16S (RS_PCM16S|RSF_STEREO) // stereo 16-bit signed -#define RS_STPCM16U (RS_PCM16U|RSF_STEREO) // stereo 16-bit unsigned -#define RS_STPCM16D (RS_PCM16D|RSF_STEREO) // stereo 16-bit delta values -#define RS_STPCM16M (RS_PCM16M|RSF_STEREO) // stereo 16-bit signed big endian -// IT 2.14 compressed samples -#define RS_IT2148 0x10 -#define RS_IT21416 0x14 -#define RS_IT2158 0x12 -#define RS_IT21516 0x16 -// AMS Packed Samples -#define RS_AMS8 0x11 -#define RS_AMS16 0x15 -// DMF Huffman compression -#define RS_DMF8 0x13 -#define RS_DMF16 0x17 -// MDL Huffman compression -#define RS_MDL8 0x20 -#define RS_MDL16 0x24 -#define RS_PTM8DTO16 0x25 -// Stereo Interleaved Samples -#define RS_STIPCM8S (RS_PCM8S|0x40|RSF_STEREO) // stereo 8-bit signed -#define RS_STIPCM8U (RS_PCM8U|0x40|RSF_STEREO) // stereo 8-bit unsigned -#define RS_STIPCM16S (RS_PCM16S|0x40|RSF_STEREO) // stereo 16-bit signed -#define RS_STIPCM16U (RS_PCM16U|0x40|RSF_STEREO) // stereo 16-bit unsigned -#define RS_STIPCM16M (RS_PCM16M|0x40|RSF_STEREO) // stereo 16-bit signed big endian -// 24-bit signed -#define RS_PCM24S (RS_PCM16S|0x80) // mono 24-bit signed -#define RS_STIPCM24S (RS_PCM16S|0x80|RSF_STEREO) // stereo 24-bit signed -#define RS_PCM32S (RS_PCM16S|0xC0) // mono 24-bit signed -#define RS_STIPCM32S (RS_PCM16S|0xC0|RSF_STEREO) // stereo 24-bit signed - -// NNA types -#define NNA_NOTECUT 0 -#define NNA_CONTINUE 1 -#define NNA_NOTEOFF 2 -#define NNA_NOTEFADE 3 - -// DCT types -#define DCT_NONE 0 -#define DCT_NOTE 1 -#define DCT_SAMPLE 2 -#define DCT_INSTRUMENT 3 - -// DNA types -#define DNA_NOTECUT 0 -#define DNA_NOTEOFF 1 -#define DNA_NOTEFADE 2 - -// Mixer Hardware-Dependent features -#define SYSMIX_ENABLEMMX 0x01 -#define SYSMIX_WINDOWSNT 0x02 -#define SYSMIX_SLOWCPU 0x04 -#define SYSMIX_FASTCPU 0x08 - -// Module flags -#define SONG_EMBEDMIDICFG 0x0001 -#define SONG_FASTVOLSLIDES 0x0002 -#define SONG_ITOLDEFFECTS 0x0004 -#define SONG_ITCOMPATMODE 0x0008 -#define SONG_LINEARSLIDES 0x0010 -#define SONG_PATTERNLOOP 0x0020 -#define SONG_STEP 0x0040 -#define SONG_PAUSED 0x0080 -#define SONG_FADINGSONG 0x0100 -#define SONG_ENDREACHED 0x0200 -#define SONG_GLOBALFADE 0x0400 -#define SONG_CPUVERYHIGH 0x0800 -#define SONG_FIRSTTICK 0x1000 -#define SONG_MPTFILTERMODE 0x2000 -#define SONG_SURROUNDPAN 0x4000 -#define SONG_EXFILTERRANGE 0x8000 -#define SONG_AMIGALIMITS 0x10000 - -// Global Options (Renderer) -#define SNDMIX_REVERSESTEREO 0x0001 -#define SNDMIX_NOISEREDUCTION 0x0002 -#define SNDMIX_AGC 0x0004 -#define SNDMIX_NORESAMPLING 0x0008 -#define SNDMIX_HQRESAMPLER 0x0010 -#define SNDMIX_MEGABASS 0x0020 -#define SNDMIX_SURROUND 0x0040 -#define SNDMIX_REVERB 0x0080 -#define SNDMIX_EQ 0x0100 -#define SNDMIX_SOFTPANNING 0x0200 -#define SNDMIX_ULTRAHQSRCMODE 0x0400 -// Misc Flags (can safely be turned on or off) -#define SNDMIX_DIRECTTODISK 0x10000 -#define SNDMIX_ENABLEMMX 0x20000 -#define SNDMIX_NOBACKWARDJUMPS 0x40000 -#define SNDMIX_MAXDEFAULTPAN 0x80000 // Used by the MOD loader - - -// Reverb Types (GM2 Presets) -enum { - REVERBTYPE_SMALLROOM, - REVERBTYPE_MEDIUMROOM, - REVERBTYPE_LARGEROOM, - REVERBTYPE_SMALLHALL, - REVERBTYPE_MEDIUMHALL, - REVERBTYPE_LARGEHALL, - NUM_REVERBTYPES -}; - - -enum { - SRCMODE_NEAREST, - SRCMODE_LINEAR, - SRCMODE_SPLINE, - SRCMODE_POLYPHASE, - NUM_SRC_MODES -}; - - -// Sample Struct -typedef struct _MODINSTRUMENT -{ - UINT nLength,nLoopStart,nLoopEnd; - UINT nSustainStart, nSustainEnd; - signed char *pSample; - UINT nC4Speed; - WORD nPan; - WORD nVolume; - WORD nGlobalVol; - WORD uFlags; - signed char RelativeTone; - signed char nFineTune; - BYTE nVibType; - BYTE nVibSweep; - BYTE nVibDepth; - BYTE nVibRate; - CHAR name[22]; -} MODINSTRUMENT; - - -// Instrument Struct -typedef struct _INSTRUMENTHEADER -{ - UINT nFadeOut; - DWORD dwFlags; - WORD nGlobalVol; - WORD nPan; - WORD VolPoints[MAX_ENVPOINTS]; - WORD PanPoints[MAX_ENVPOINTS]; - WORD PitchPoints[MAX_ENVPOINTS]; - BYTE VolEnv[MAX_ENVPOINTS]; - BYTE PanEnv[MAX_ENVPOINTS]; - BYTE PitchEnv[MAX_ENVPOINTS]; - BYTE Keyboard[128]; - BYTE NoteMap[128]; - - BYTE nVolEnv; - BYTE nPanEnv; - BYTE nPitchEnv; - BYTE nVolLoopStart; - BYTE nVolLoopEnd; - BYTE nVolSustainBegin; - BYTE nVolSustainEnd; - BYTE nPanLoopStart; - BYTE nPanLoopEnd; - BYTE nPanSustainBegin; - BYTE nPanSustainEnd; - BYTE nPitchLoopStart; - BYTE nPitchLoopEnd; - BYTE nPitchSustainBegin; - BYTE nPitchSustainEnd; - BYTE nNNA; - BYTE nDCT; - BYTE nDNA; - BYTE nPanSwing; - BYTE nVolSwing; - BYTE nIFC; - BYTE nIFR; - WORD wMidiBank; - BYTE nMidiProgram; - BYTE nMidiChannel; - BYTE nMidiDrumKey; - signed char nPPS; - unsigned char nPPC; - CHAR name[32]; - CHAR filename[12]; -} INSTRUMENTHEADER; - - -// Channel Struct -typedef struct _MODCHANNEL -{ - // First 32-bytes: Most used mixing information: don't change it - signed char * pCurrentSample; - DWORD nPos; - DWORD nPosLo; // actually 16-bit - LONG nInc; // 16.16 - LONG nRightVol; - LONG nLeftVol; - LONG nRightRamp; - LONG nLeftRamp; - // 2nd cache line - DWORD nLength; - DWORD dwFlags; - DWORD nLoopStart; - DWORD nLoopEnd; - LONG nRampRightVol; - LONG nRampLeftVol; - LONG nFilter_Y1, nFilter_Y2, nFilter_Y3, nFilter_Y4; - LONG nFilter_A0, nFilter_B0, nFilter_B1; - LONG nROfs, nLOfs; - LONG nRampLength; - // Information not used in the mixer - signed char * pSample; - LONG nNewRightVol, nNewLeftVol; - LONG nRealVolume, nRealPan; - LONG nVolume, nPan, nFadeOutVol; - LONG nPeriod, nC4Speed, nPortamentoDest; - INSTRUMENTHEADER *pHeader; - MODINSTRUMENT *pInstrument; - DWORD nVolEnvPosition, nPanEnvPosition, nPitchEnvPosition; - DWORD nMasterChn, nVUMeter; - LONG nGlobalVol, nInsVol; - LONG nFineTune, nTranspose; - LONG nPortamentoSlide, nAutoVibDepth; - UINT nAutoVibPos, nVibratoPos, nTremoloPos, nPanbrelloPos; - // 16-bit members - signed short nVolSwing, nPanSwing; - // 8-bit members - BYTE nNote, nNNA; - BYTE nNewNote, nNewIns, nCommand, nArpeggio; - BYTE nOldVolumeSlide, nOldFineVolUpDown; - BYTE nOldPortaUpDown, nOldFinePortaUpDown; - BYTE nOldPanSlide, nOldChnVolSlide; - BYTE nVibratoType, nVibratoSpeed, nVibratoDepth; - BYTE nTremoloType, nTremoloSpeed, nTremoloDepth; - BYTE nPanbrelloType, nPanbrelloSpeed, nPanbrelloDepth; - BYTE nOldCmdEx, nOldVolParam, nOldTempo; - BYTE nOldOffset, nOldHiOffset; - BYTE nCutOff, nResonance; - BYTE nRetrigCount, nRetrigParam; - BYTE nTremorCount, nTremorParam; - BYTE nPatternLoop, nPatternLoopCount; - BYTE nRowNote, nRowInstr; - BYTE nRowVolCmd, nRowVolume; - BYTE nRowCommand, nRowParam; - BYTE nLeftVU, nRightVU; - BYTE nActiveMacro, nPadding; -} MODCHANNEL; - - -typedef struct _MODCHANNELSETTINGS -{ - UINT nPan; - UINT nVolume; - DWORD dwFlags; - UINT nMixPlugin; - char szName[MAX_CHANNELNAME]; // changed from CHAR -} MODCHANNELSETTINGS; - - -typedef struct _MODCOMMAND -{ - BYTE note; - BYTE instr; - BYTE volcmd; - BYTE command; - BYTE vol; - BYTE param; -} MODCOMMAND, *LPMODCOMMAND; - -//////////////////////////////////////////////////////////////////// -// Mix Plugins -#define MIXPLUG_MIXREADY 0x01 // Set when cleared - -class IMixPlugin -{ -public: - virtual ~IMixPlugin(); - virtual int AddRef() = 0; - virtual int Release() = 0; - virtual void SaveAllParameters() = 0; - virtual void RestoreAllParameters() = 0; - virtual void Process(float *pOutL, float *pOutR, unsigned long nSamples) = 0; - virtual void Init(unsigned long nFreq, int bReset) = 0; - virtual void MidiSend(DWORD dwMidiCode) = 0; - virtual void MidiCommand(UINT nMidiCh, UINT nMidiProg, UINT note, UINT vol) = 0; -}; - - -#define MIXPLUG_INPUTF_MASTEREFFECT 0x01 // Apply to master mix -#define MIXPLUG_INPUTF_BYPASS 0x02 // Bypass effect -#define MIXPLUG_INPUTF_WETMIX 0x04 // Wet Mix (dry added) - -typedef struct _SNDMIXPLUGINSTATE -{ - DWORD dwFlags; // MIXPLUG_XXXX - LONG nVolDecayL, nVolDecayR; // Buffer click removal - int *pMixBuffer; // Stereo effect send buffer - float *pOutBufferL; // Temp storage for int -> float conversion - float *pOutBufferR; -} SNDMIXPLUGINSTATE, *PSNDMIXPLUGINSTATE; - -typedef struct _SNDMIXPLUGININFO -{ - DWORD dwPluginId1; - DWORD dwPluginId2; - DWORD dwInputRouting; // MIXPLUG_INPUTF_XXXX - DWORD dwOutputRouting; // 0=mix 0x80+=fx - DWORD dwReserved[4]; // Reserved for routing info - CHAR szName[32]; - CHAR szLibraryName[64]; // original DLL name -} SNDMIXPLUGININFO, *PSNDMIXPLUGININFO; // Size should be 128 - -typedef struct _SNDMIXPLUGIN -{ - IMixPlugin *pMixPlugin; - PSNDMIXPLUGINSTATE pMixState; - ULONG nPluginDataSize; - PVOID pPluginData; - SNDMIXPLUGININFO Info; -} SNDMIXPLUGIN, *PSNDMIXPLUGIN; - -typedef BOOL (*PMIXPLUGINCREATEPROC)(PSNDMIXPLUGIN); - -//////////////////////////////////////////////////////////////////// - -enum { - MIDIOUT_START=0, - MIDIOUT_STOP, - MIDIOUT_TICK, - MIDIOUT_NOTEON, - MIDIOUT_NOTEOFF, - MIDIOUT_VOLUME, - MIDIOUT_PAN, - MIDIOUT_BANKSEL, - MIDIOUT_PROGRAM, -}; - - -typedef struct MODMIDICFG -{ - char szMidiGlb[9*32]; // changed from CHAR - char szMidiSFXExt[16*32]; // changed from CHAR - char szMidiZXXExt[128*32]; // changed from CHAR -} MODMIDICFG, *LPMODMIDICFG; - -#define NOTE_MAX 120 //Defines maximum notevalue as well as maximum number of notes. - -typedef VOID (* LPSNDMIXHOOKPROC)(int *, unsigned long, unsigned long); // buffer, samples, channels - - - -//============== -class CSoundFile -//============== -{ -public: // Static Members - static UINT m_nXBassDepth, m_nXBassRange; - static UINT m_nReverbDepth, m_nReverbDelay, gnReverbType; - static UINT m_nProLogicDepth, m_nProLogicDelay; - static UINT m_nStereoSeparation; - static UINT m_nMaxMixChannels; - static LONG m_nStreamVolume; - static DWORD gdwSysInfo, gdwSoundSetup, gdwMixingFreq, gnBitsPerSample, gnChannels; - static UINT gnAGC, gnVolumeRampSamples, gnVUMeter, gnCPUUsage; - static LPSNDMIXHOOKPROC gpSndMixHook; - static PMIXPLUGINCREATEPROC gpMixPluginCreateProc; - -public: // for Editing - MODCHANNEL Chn[MAX_CHANNELS]; // Channels - UINT ChnMix[MAX_CHANNELS]; // Channels to be mixed - MODINSTRUMENT Ins[MAX_SAMPLES]; // Instruments - INSTRUMENTHEADER *Headers[MAX_INSTRUMENTS]; // Instrument Headers - MODCHANNELSETTINGS ChnSettings[MAX_BASECHANNELS]; // Channels settings - MODCOMMAND *Patterns[MAX_PATTERNS]; // Patterns - WORD PatternSize[MAX_PATTERNS]; // Patterns Lengths - BYTE Order[MAX_ORDERS]; // Pattern Orders - MODMIDICFG m_MidiCfg; // Midi macro config table - SNDMIXPLUGIN m_MixPlugins[MAX_MIXPLUGINS]; // Mix plugins - UINT m_nDefaultSpeed, m_nDefaultTempo, m_nDefaultGlobalVolume; - DWORD m_dwSongFlags; // Song flags SONG_XXXX - UINT m_nChannels, m_nMixChannels, m_nMixStat, m_nBufferCount; - UINT m_nType, m_nSamples, m_nInstruments; - UINT m_nTickCount, m_nTotalCount, m_nPatternDelay, m_nFrameDelay; - UINT m_nMusicSpeed, m_nMusicTempo; - UINT m_nNextRow, m_nRow; - UINT m_nPattern,m_nCurrentPattern,m_nNextPattern,m_nRestartPos; - UINT m_nMasterVolume, m_nGlobalVolume, m_nSongPreAmp; - UINT m_nFreqFactor, m_nTempoFactor, m_nOldGlbVolSlide; - LONG m_nMinPeriod, m_nMaxPeriod, m_nRepeatCount, m_nInitialRepeatCount; - DWORD m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples; - UINT m_nMaxOrderPosition; - UINT m_nPatternNames; - LPSTR m_lpszSongComments, m_lpszPatternNames; - char m_szNames[MAX_INSTRUMENTS][32]; // changed from CHAR - CHAR CompressionTable[16]; - -public: - CSoundFile(); - ~CSoundFile(); - -public: - BOOL Create(LPCBYTE lpStream, DWORD dwMemLength=0); - BOOL Destroy(); - UINT GetType() const { return m_nType; } - UINT GetNumChannels() const; - UINT GetLogicalChannels() const { return m_nChannels; } - BOOL SetMasterVolume(UINT vol, BOOL bAdjustAGC=FALSE); - UINT GetMasterVolume() const { return m_nMasterVolume; } - UINT GetNumPatterns() const; - UINT GetNumInstruments() const; - UINT GetNumSamples() const { return m_nSamples; } - UINT GetCurrentPos() const; - UINT GetCurrentPattern() const { return m_nPattern; } - UINT GetCurrentOrder() const { return m_nCurrentPattern; } - UINT GetSongComments(LPSTR s, UINT cbsize, UINT linesize=32); - UINT GetRawSongComments(LPSTR s, UINT cbsize, UINT linesize=32); - UINT GetMaxPosition() const; - void SetCurrentPos(UINT nPos); - void SetCurrentOrder(UINT nOrder); - void GetTitle(LPSTR s) const { lstrcpyn(s,m_szNames[0],32); } - LPCSTR GetTitle() const { return m_szNames[0]; } - UINT GetSampleName(UINT nSample,LPSTR s=NULL) const; - UINT GetInstrumentName(UINT nInstr,LPSTR s=NULL) const; - UINT GetMusicSpeed() const { return m_nMusicSpeed; } - UINT GetMusicTempo() const { return m_nMusicTempo; } - DWORD GetLength(BOOL bAdjust, BOOL bTotal=FALSE); - DWORD GetSongTime() { return GetLength(FALSE, TRUE); } - void SetRepeatCount(int n) { m_nRepeatCount = n; m_nInitialRepeatCount = n; } - int GetRepeatCount() const { return m_nRepeatCount; } - BOOL IsPaused() const { return (m_dwSongFlags & SONG_PAUSED) ? TRUE : FALSE; } - void LoopPattern(int nPat, int nRow=0); - void CheckCPUUsage(UINT nCPU); - BOOL SetPatternName(UINT nPat, LPCSTR lpszName); - BOOL GetPatternName(UINT nPat, LPSTR lpszName, UINT cbSize=MAX_PATTERNNAME) const; - // Module Loaders - BOOL ReadXM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadS3M(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMod(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMed(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMTM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadSTM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadIT(LPCBYTE lpStream, DWORD dwMemLength); - BOOL Read669(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadUlt(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadWav(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadDSM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadFAR(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadAMS(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMDL(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadOKT(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadDMF(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadPTM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadDBM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadAMF(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMT2(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadPSM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadJ2B(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadUMX(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadABC(LPCBYTE lpStream, DWORD dwMemLength); - BOOL TestABC(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMID(LPCBYTE lpStream, DWORD dwMemLength); - BOOL TestMID(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadPAT(LPCBYTE lpStream, DWORD dwMemLength); - BOOL TestPAT(LPCBYTE lpStream, DWORD dwMemLength); - // Save Functions -#ifndef MODPLUG_NO_FILESAVE - UINT WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen=0); - BOOL SaveXM(LPCSTR lpszFileName, UINT nPacking=0); - BOOL SaveS3M(LPCSTR lpszFileName, UINT nPacking=0); - BOOL SaveMod(LPCSTR lpszFileName, UINT nPacking=0); - BOOL SaveIT(LPCSTR lpszFileName, UINT nPacking=0); -#endif // MODPLUG_NO_FILESAVE - // MOD Convert function - UINT GetBestSaveFormat() const; - UINT GetSaveFormats() const; - void ConvertModCommand(MODCOMMAND *) const; - void S3MConvert(MODCOMMAND *m, BOOL bIT) const; - void S3MSaveConvert(UINT *pcmd, UINT *pprm, BOOL bIT) const; - WORD ModSaveCommand(const MODCOMMAND *m, BOOL bXM) const; - -public: - // Real-time sound functions - VOID ResetChannels(); - - UINT Read(LPVOID lpBuffer, UINT cbBuffer); - UINT CreateStereoMix(int count); - BOOL FadeSong(UINT msec); - BOOL GlobalFadeSong(UINT msec); - UINT GetTotalTickCount() const { return m_nTotalCount; } - VOID ResetTotalTickCount() { m_nTotalCount = 0; } - -public: - // Mixer Config - static BOOL InitPlayer(BOOL bReset=FALSE); - static BOOL SetMixConfig(UINT nStereoSeparation, UINT nMaxMixChannels); - static BOOL SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX=FALSE); - static BOOL SetResamplingMode(UINT nMode); // SRCMODE_XXXX - static BOOL IsStereo() { return (gnChannels > 1) ? TRUE : FALSE; } - static DWORD GetSampleRate() { return gdwMixingFreq; } - static DWORD GetBitsPerSample() { return gnBitsPerSample; } - static DWORD InitSysInfo(); - static DWORD GetSysInfo() { return gdwSysInfo; } - // AGC - static BOOL GetAGC() { return (gdwSoundSetup & SNDMIX_AGC) ? TRUE : FALSE; } - static void SetAGC(BOOL b); - static void ResetAGC(); - static void ProcessAGC(int count); - - //GCCFIX -- added these functions back in! - static BOOL SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ); - // DSP Effects - static void InitializeDSP(BOOL bReset); - static void ProcessStereoDSP(int count); - static void ProcessMonoDSP(int count); - // [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms] - static BOOL SetReverbParameters(UINT nDepth, UINT nDelay); - // [XBass level 0(quiet)-100(loud)], [cutoff in Hz 10-100] - static BOOL SetXBassParameters(UINT nDepth, UINT nRange); - // [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-40ms] - static BOOL SetSurroundParameters(UINT nDepth, UINT nDelay); -public: - BOOL ReadNote(); - BOOL ProcessRow(); - BOOL ProcessEffects(); - UINT GetNNAChannel(UINT nChn) const; - void CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut); - void NoteChange(UINT nChn, int note, BOOL bPorta=FALSE, BOOL bResetEnv=TRUE); - void InstrumentChange(MODCHANNEL *pChn, UINT instr, BOOL bPorta=FALSE,BOOL bUpdVol=TRUE,BOOL bResetEnv=TRUE); - // Channel Effects - void PortamentoUp(MODCHANNEL *pChn, UINT param); - void PortamentoDown(MODCHANNEL *pChn, UINT param); - void FinePortamentoUp(MODCHANNEL *pChn, UINT param); - void FinePortamentoDown(MODCHANNEL *pChn, UINT param); - void ExtraFinePortamentoUp(MODCHANNEL *pChn, UINT param); - void ExtraFinePortamentoDown(MODCHANNEL *pChn, UINT param); - void TonePortamento(MODCHANNEL *pChn, UINT param); - void Vibrato(MODCHANNEL *pChn, UINT param); - void FineVibrato(MODCHANNEL *pChn, UINT param); - void VolumeSlide(MODCHANNEL *pChn, UINT param); - void PanningSlide(MODCHANNEL *pChn, UINT param); - void ChannelVolSlide(MODCHANNEL *pChn, UINT param); - void FineVolumeUp(MODCHANNEL *pChn, UINT param); - void FineVolumeDown(MODCHANNEL *pChn, UINT param); - void Tremolo(MODCHANNEL *pChn, UINT param); - void Panbrello(MODCHANNEL *pChn, UINT param); - void RetrigNote(UINT nChn, UINT param); - void NoteCut(UINT nChn, UINT nTick); - void KeyOff(UINT nChn); - int PatternLoop(MODCHANNEL *, UINT param); - void ExtendedMODCommands(UINT nChn, UINT param); - void ExtendedS3MCommands(UINT nChn, UINT param); - void ExtendedChannelEffect(MODCHANNEL *, UINT param); - void ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0); - void SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier=256) const; - // Low-Level effect processing - void DoFreqSlide(MODCHANNEL *pChn, LONG nFreqSlide); - // Global Effects - void SetTempo(UINT param); - void SetSpeed(UINT param); - void GlobalVolSlide(UINT param); - DWORD IsSongFinished(UINT nOrder, UINT nRow) const; - BOOL IsValidBackwardJump(UINT nStartOrder, UINT nStartRow, UINT nJumpOrder, UINT nJumpRow) const; - // Read/Write sample functions - signed char GetDeltaValue(signed char prev, UINT n) const { return (signed char)(prev + CompressionTable[n & 0x0F]); } - UINT PackSample(int &sample, int next); - BOOL CanPackSample(LPSTR pSample, UINT nLen, UINT nPacking, BYTE *result=NULL); - UINT ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR pMemFile, DWORD dwMemLength); - BOOL DestroySample(UINT nSample); - BOOL DestroyInstrument(UINT nInstr); - BOOL IsSampleUsed(UINT nSample); - BOOL IsInstrumentUsed(UINT nInstr); - BOOL RemoveInstrumentSamples(UINT nInstr); - UINT DetectUnusedSamples(BOOL *); - BOOL RemoveSelectedSamples(BOOL *); - void AdjustSampleLoop(MODINSTRUMENT *pIns); - // I/O from another sound file - BOOL ReadInstrumentFromSong(UINT nInstr, CSoundFile *, UINT nSrcInstrument); - BOOL ReadSampleFromSong(UINT nSample, CSoundFile *, UINT nSrcSample); - // Period/Note functions - UINT GetNoteFromPeriod(UINT period) const; - UINT GetPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const; - UINT GetFreqFromPeriod(UINT period, UINT nC4Speed, int nPeriodFrac=0) const; - // Misc functions - MODINSTRUMENT *GetSample(UINT n) { return Ins+n; } - void ResetMidiCfg(); - UINT MapMidiInstrument(DWORD dwProgram, UINT nChannel, UINT nNote); - BOOL ITInstrToMPT(const void *p, INSTRUMENTHEADER *penv, UINT trkvers); - UINT SaveMixPlugins(FILE *f=NULL, BOOL bUpdate=TRUE); - UINT LoadMixPlugins(const void *pData, UINT nLen); -#ifndef NO_FILTER - DWORD CutOffToFrequency(UINT nCutOff, int flt_modifier=256) const; // [0-255] => [1-10KHz] -#endif - - // Static helper functions -public: - static DWORD TransposeToFrequency(int transp, int ftune=0); - static int FrequencyToTranspose(DWORD freq); - static void FrequencyToTranspose(MODINSTRUMENT *psmp); - - // System-Dependant functions -public: - static MODCOMMAND *AllocatePattern(UINT rows, UINT nchns); - static signed char* AllocateSample(UINT nbytes); - static void FreePattern(LPVOID pat); - static void FreeSample(LPVOID p); - static UINT Normalize24BitBuffer(LPBYTE pbuffer, UINT cbsizebytes, DWORD lmax24, DWORD dwByteInc); -}; - - -// inline DWORD BigEndian(DWORD x) { return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24); } -// inline WORD BigEndianW(WORD x) { return (WORD)(((x >> 8) & 0xFF) | ((x << 8) & 0xFF00)); } - - -////////////////////////////////////////////////////////// -// WAVE format information - -#pragma pack(1) - -// Standard IFF chunks IDs -#define IFFID_FORM 0x4d524f46 -#define IFFID_RIFF 0x46464952 -#define IFFID_WAVE 0x45564157 -#define IFFID_LIST 0x5453494C -#define IFFID_INFO 0x4F464E49 - -// IFF Info fields -#define IFFID_ICOP 0x504F4349 -#define IFFID_IART 0x54524149 -#define IFFID_IPRD 0x44525049 -#define IFFID_INAM 0x4D414E49 -#define IFFID_ICMT 0x544D4349 -#define IFFID_IENG 0x474E4549 -#define IFFID_ISFT 0x54465349 -#define IFFID_ISBJ 0x4A425349 -#define IFFID_IGNR 0x524E4749 -#define IFFID_ICRD 0x44524349 - -// Wave IFF chunks IDs -#define IFFID_wave 0x65766177 -#define IFFID_fmt 0x20746D66 -#define IFFID_wsmp 0x706D7377 -#define IFFID_pcm 0x206d6370 -#define IFFID_data 0x61746164 -#define IFFID_smpl 0x6C706D73 -#define IFFID_xtra 0x61727478 - -typedef struct WAVEFILEHEADER -{ - DWORD id_RIFF; // "RIFF" - DWORD filesize; // file length-8 - DWORD id_WAVE; -} WAVEFILEHEADER; - - -typedef struct WAVEFORMATHEADER -{ - DWORD id_fmt; // "fmt " - DWORD hdrlen; // 16 - WORD format; // 1 - WORD channels; // 1:mono, 2:stereo - DWORD freqHz; // sampling freq - DWORD bytessec; // bytes/sec=freqHz*samplesize - WORD samplesize; // sizeof(sample) - WORD bitspersample; // bits per sample (8/16) -} WAVEFORMATHEADER; - - -typedef struct WAVEDATAHEADER -{ - DWORD id_data; // "data" - DWORD length; // length of data -} WAVEDATAHEADER; - - -typedef struct WAVESMPLHEADER -{ - // SMPL - DWORD smpl_id; // "smpl" -> 0x6C706D73 - DWORD smpl_len; // length of smpl: 3Ch (54h with sustain loop) - DWORD dwManufacturer; - DWORD dwProduct; - DWORD dwSamplePeriod; // 1000000000/freqHz - DWORD dwBaseNote; // 3Ch = C-4 -> 60 + RelativeTone - DWORD dwPitchFraction; - DWORD dwSMPTEFormat; - DWORD dwSMPTEOffset; - DWORD dwSampleLoops; // number of loops - DWORD cbSamplerData; -} WAVESMPLHEADER; - - -typedef struct SAMPLELOOPSTRUCT -{ - DWORD dwIdentifier; - DWORD dwLoopType; // 0=normal, 1=bidi - DWORD dwLoopStart; - DWORD dwLoopEnd; // Byte offset ? - DWORD dwFraction; - DWORD dwPlayCount; // Loop Count, 0=infinite -} SAMPLELOOPSTRUCT; - - -typedef struct WAVESAMPLERINFO -{ - WAVESMPLHEADER wsiHdr; - SAMPLELOOPSTRUCT wsiLoops[2]; -} WAVESAMPLERINFO; - - -typedef struct WAVELISTHEADER -{ - DWORD list_id; // "LIST" -> 0x5453494C - DWORD list_len; - DWORD info; // "INFO" -} WAVELISTHEADER; - - -typedef struct WAVEEXTRAHEADER -{ - DWORD xtra_id; // "xtra" -> 0x61727478 - DWORD xtra_len; - DWORD dwFlags; - WORD wPan; - WORD wVolume; - WORD wGlobalVol; - WORD wReserved; - BYTE nVibType; - BYTE nVibSweep; - BYTE nVibDepth; - BYTE nVibRate; -} WAVEEXTRAHEADER; - -#pragma pack() - -/////////////////////////////////////////////////////////// -// Low-level Mixing functions - -#define MIXBUFFERSIZE 512 -#define MIXING_ATTENUATION 4 -#define MIXING_CLIPMIN (-0x08000000) -#define MIXING_CLIPMAX (0x07FFFFFF) -#define VOLUMERAMPPRECISION 12 -#define FADESONGDELAY 100 -#define EQ_BUFFERSIZE (MIXBUFFERSIZE) -#define AGC_PRECISION 9 -#define AGC_UNITY (1 << AGC_PRECISION) - -// Calling conventions -#ifdef MSC_VER -#define MPPASMCALL __cdecl -#define MPPFASTCALL __fastcall -#else -#define MPPASMCALL -#define MPPFASTCALL -#endif - -#define MOD2XMFineTune(k) ((int)( (signed char)((k)<<4) )) -#define XM2MODFineTune(k) ((int)( (k>>4)&0x0f )) - -int _muldiv(long a, long b, long c); -int _muldivr(long a, long b, long c); - - -// Byte swapping functions from the GNU C Library and libsdl - -/* Swap bytes in 16 bit value. */ -#ifdef __GNUC__ -# define bswap_16(x) \ - (__extension__ \ - ({ unsigned short int __bsx = (x); \ - ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); })) -#else -static __inline unsigned short int -bswap_16 (unsigned short int __bsx) -{ - return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); -} -#endif - -/* Swap bytes in 32 bit value. */ -#ifdef __GNUC__ -# define bswap_32(x) \ - (__extension__ \ - ({ unsigned int __bsx = (x); \ - ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | \ - (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); })) -#else -static __inline unsigned int -bswap_32 (unsigned int __bsx) -{ - return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | - (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); -} -#endif - -#if (defined ARM) && (defined _WIN32_WCE) -static __inline unsigned short int -ARM_get16(const void *data) -{ - unsigned short int s; - memcpy(&s,data,sizeof(s)); - return s; -} - -static __inline unsigned int -ARM_get32(const void *data) -{ - unsigned int s; - memcpy(&s,data,sizeof(s)); - return s; -} - -#define bswapLE16(X) ARM_get16(&X) -#define bswapLE32(X) ARM_get32(&X) -#define bswapBE16(X) bswap_16(ARM_get16(&X)) -#define bswapBE32(X) bswap_32(ARM_get32(&X)) - -// From libsdl -#elif defined(WORDS_BIGENDIAN) && WORDS_BIGENDIAN -#define bswapLE16(X) bswap_16(X) -#define bswapLE32(X) bswap_32(X) -#define bswapBE16(X) (X) -#define bswapBE32(X) (X) -#else -#define bswapLE16(X) (X) -#define bswapLE32(X) (X) -#define bswapBE16(X) bswap_16(X) -#define bswapBE32(X) bswap_32(X) -#endif - -#endif diff --git a/jni/libmodplug/stdafx.h b/jni/libmodplug/stdafx.h deleted file mode 100644 index 0330170..0000000 --- a/jni/libmodplug/stdafx.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Rani Assaf , - * Olivier Lapicque , - * Adam Goode (endian and char fixes for PPC) - */ - -#ifndef _STDAFX_H_ -#define _STDAFX_H_ - -/* Autoconf detection of stdint/inttypes */ -#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) -# include "config.h" -# define CONFIG_H_INCLUDED 1 -#endif -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif - - -#ifdef _WIN32 - -#ifdef MSC_VER -#pragma warning (disable:4201) -#pragma warning (disable:4514) -#endif - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include -#include - -#define srandom(_seed) srand(_seed) -#define random() rand() -#define sleep(_ms) Sleep(_ms) - -inline void ProcessPlugins(int n) {} - -#define strncasecmp(a,b,c) strncmp(a,b,c) -#define strcasecmp(a,b) strcmp(a,b) -#define strnicmp(a,b,c) strncasecmp(a,b,c) -#define HAVE_SINF 1 - -#else - -#include -#include -#include -#ifdef HAVE_MALLOC_H -#include -#endif - -typedef int8_t CHAR; -typedef uint8_t UCHAR; -typedef uint8_t* PUCHAR; -typedef uint16_t USHORT; -typedef uint32_t ULONG; -typedef uint32_t UINT; -typedef uint32_t DWORD; -typedef int32_t LONG; -typedef int64_t LONGLONG; -typedef int32_t* LPLONG; -typedef uint32_t* LPDWORD; -typedef uint16_t WORD; -typedef uint8_t BYTE; -typedef uint8_t* LPBYTE; -typedef bool BOOL; -typedef char* LPSTR; -typedef void* LPVOID; -typedef uint16_t* LPWORD; -typedef const char* LPCSTR; -typedef void* PVOID; -typedef void VOID; - -inline LONG MulDiv (long a, long b, long c) -{ - // if (!c) return 0; - return ((uint64_t) a * (uint64_t) b ) / c; -} - -#define MODPLUG_NO_FILESAVE -#define NO_AGC -#define LPCTSTR LPCSTR -#define lstrcpyn strncpy -#define lstrcpy strcpy -#define lstrcmp strcmp -#define WAVE_FORMAT_PCM 1 -//#define ENABLE_EQ - -#define GHND 0 - -inline int8_t * GlobalAllocPtr(unsigned int, size_t size) -{ - int8_t * p = (int8_t *) malloc(size); - - if (p != NULL) memset(p, 0, size); - return p; -} - -inline void ProcessPlugins(int n) {} - -#define GlobalFreePtr(p) free((void *)(p)) - -#define strnicmp(a,b,c) strncasecmp(a,b,c) -#define wsprintf sprintf - -#ifndef FALSE -#define FALSE false -#endif - -#ifndef TRUE -#define TRUE true -#endif - -#endif // _WIN32 - -#endif - - - diff --git a/jni/load_669.cpp b/jni/load_669.cpp deleted file mode 100644 index f3aa0ee..0000000 --- a/jni/load_669.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque , - * Adam Goode (endian and char fixes for PPC) -*/ - -//////////////////////////////////////////////////////////// -// 669 Composer / UNIS 669 module loader -//////////////////////////////////////////////////////////// - -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -typedef struct tagFILEHEADER669 -{ - WORD sig; // 'if' or 'JN' - signed char songmessage[108]; // Song Message - BYTE samples; // number of samples (1-64) - BYTE patterns; // number of patterns (1-128) - BYTE restartpos; - BYTE orders[128]; - BYTE tempolist[128]; - BYTE breaks[128]; -} FILEHEADER669; - - -typedef struct tagSAMPLE669 -{ - BYTE filename[13]; - BYTE length[4]; // when will somebody think about DWORD align ??? - BYTE loopstart[4]; - BYTE loopend[4]; -} SAMPLE669; - -DWORD lengthArrayToDWORD(const BYTE length[4]) { - DWORD len = (length[3] << 24) + - (length[2] << 16) + - (length[1] << 8) + - (length[0]); - - return(len); -} - - -BOOL CSoundFile::Read669(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - BOOL b669Ext; - const FILEHEADER669 *pfh = (const FILEHEADER669 *)lpStream; - const SAMPLE669 *psmp = (const SAMPLE669 *)(lpStream + 0x1F1); - DWORD dwMemPos = 0; - - if ((!lpStream) || (dwMemLength < sizeof(FILEHEADER669))) return FALSE; - if ((bswapLE16(pfh->sig) != 0x6669) && (bswapLE16(pfh->sig) != 0x4E4A)) return FALSE; - b669Ext = (bswapLE16(pfh->sig) == 0x4E4A) ? TRUE : FALSE; - if ((!pfh->samples) || (pfh->samples > 64) || (pfh->restartpos >= 128) - || (!pfh->patterns) || (pfh->patterns > 128)) return FALSE; - DWORD dontfuckwithme = 0x1F1 + pfh->samples * sizeof(SAMPLE669) + pfh->patterns * 0x600; - if (dontfuckwithme > dwMemLength) return FALSE; - for (UINT ichk=0; ichksamples; ichk++) - { - DWORD len = lengthArrayToDWORD(psmp[ichk].length); - dontfuckwithme += len; - } - if (dontfuckwithme > dwMemLength) return FALSE; - // That should be enough checking: this must be a 669 module. - m_nType = MOD_TYPE_669; - m_dwSongFlags |= SONG_LINEARSLIDES; - m_nMinPeriod = 28 << 2; - m_nMaxPeriod = 1712 << 3; - m_nDefaultTempo = 125; - m_nDefaultSpeed = 6; - m_nChannels = 8; - memcpy(m_szNames[0], pfh->songmessage, 16); - m_nSamples = pfh->samples; - for (UINT nins=1; nins<=m_nSamples; nins++, psmp++) - { - DWORD len = lengthArrayToDWORD(psmp->length); - DWORD loopstart = lengthArrayToDWORD(psmp->loopstart); - DWORD loopend = lengthArrayToDWORD(psmp->loopend); - if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH; - if ((loopend > len) && (!loopstart)) loopend = 0; - if (loopend > len) loopend = len; - if (loopstart + 4 >= loopend) loopstart = loopend = 0; - Ins[nins].nLength = len; - Ins[nins].nLoopStart = loopstart; - Ins[nins].nLoopEnd = loopend; - if (loopend) Ins[nins].uFlags |= CHN_LOOP; - memcpy(m_szNames[nins], psmp->filename, 13); - Ins[nins].nVolume = 256; - Ins[nins].nGlobalVol = 64; - Ins[nins].nPan = 128; - } - // Song Message - m_lpszSongComments = new char[109]; - memcpy(m_lpszSongComments, pfh->songmessage, 108); - m_lpszSongComments[108] = 0; - // Reading Orders - memcpy(Order, pfh->orders, 128); - m_nRestartPos = pfh->restartpos; - if (Order[m_nRestartPos] >= pfh->patterns) m_nRestartPos = 0; - // Reading Pattern Break Locations - for (UINT npan=0; npan<8; npan++) - { - ChnSettings[npan].nPan = (npan & 1) ? 0x30 : 0xD0; - ChnSettings[npan].nVolume = 64; - } - // Reading Patterns - dwMemPos = 0x1F1 + pfh->samples * 25; - for (UINT npat=0; npatpatterns; npat++) - { - Patterns[npat] = AllocatePattern(64, m_nChannels); - if (!Patterns[npat]) break; - PatternSize[npat] = 64; - MODCOMMAND *m = Patterns[npat]; - const BYTE *p = lpStream + dwMemPos; - for (UINT row=0; row<64; row++) - { - MODCOMMAND *mspeed = m; - if ((row == pfh->breaks[npat]) && (row != 63)) - { - for (UINT i=0; i<8; i++) - { - m[i].command = CMD_PATTERNBREAK; - m[i].param = 0; - } - } - for (UINT n=0; n<8; n++, m++, p+=3) - { - UINT note = p[0] >> 2; - UINT instr = ((p[0] & 0x03) << 4) | (p[1] >> 4); - UINT vol = p[1] & 0x0F; - if (p[0] < 0xFE) - { - m->note = note + 37; - m->instr = instr + 1; - } - if (p[0] <= 0xFE) - { - m->volcmd = VOLCMD_VOLUME; - m->vol = (vol << 2) + 2; - } - if (p[2] != 0xFF) - { - UINT command = p[2] >> 4; - UINT param = p[2] & 0x0F; - switch(command) - { - case 0x00: command = CMD_PORTAMENTOUP; break; - case 0x01: command = CMD_PORTAMENTODOWN; break; - case 0x02: command = CMD_TONEPORTAMENTO; break; - case 0x03: command = CMD_MODCMDEX; param |= 0x50; break; - case 0x04: command = CMD_VIBRATO; param |= 0x40; break; - case 0x05: if (param) command = CMD_SPEED; else command = 0; param += 2; break; - case 0x06: if (param == 0) { command = CMD_PANNINGSLIDE; param = 0xFE; } else - if (param == 1) { command = CMD_PANNINGSLIDE; param = 0xEF; } else - command = 0; - break; - default: command = 0; - } - if (command) - { - if (command == CMD_SPEED) mspeed = NULL; - m->command = command; - m->param = param; - } - } - } - if ((!row) && (mspeed)) - { - for (UINT i=0; i<8; i++) if (!mspeed[i].command) - { - mspeed[i].command = CMD_SPEED; - mspeed[i].param = pfh->tempolist[npat] + 2; - break; - } - } - } - dwMemPos += 0x600; - } - // Reading Samples - for (UINT n=1; n<=m_nSamples; n++) - { - UINT len = Ins[n].nLength; - if (dwMemPos >= dwMemLength) break; - if (len > 4) ReadSample(&Ins[n], RS_PCM8U, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos); - dwMemPos += len; - } - return TRUE; -} - - diff --git a/jni/load_abc.cpp b/jni/load_abc.cpp deleted file mode 100644 index a3e681b..0000000 --- a/jni/load_abc.cpp +++ /dev/null @@ -1,5189 +0,0 @@ -/* - - MikMod Sound System - - By Jake Stine of Divine Entertainment (1996-2000) - - Support: - If you find problems with this code, send mail to: - air@divent.org - - Distribution / Code rights: - Use this source code in any fashion you see fit. Giving me credit where - credit is due is optional, depending on your own levels of integrity and - honesty. - - ----------------------------------------- - Module: LOAD_ABC - - ABC module loader. - by Peter Grootswagers (2006) - - - Portability: - All systems - all compilers (hopefully) -*/ - -#include -#include -#include -#include -#include -#ifndef _WIN32 -#include // for sleep -#endif // _WIN32 - -#ifdef NEWMIKMOD -#include "mikmod.h" -#include "uniform.h" -typedef UBYTE BYTE; -typedef UWORD WORD; -#else -#include "stdafx.h" -#include "sndfile.h" -#endif - -#include "load_pat.h" - -#define MAXABCINCLUDES 8 -#define MAXCHORDNAMES 80 -#define ABC_ENV_DUMPTRACKS "MMABC_DUMPTRACKS" -#define ABC_ENV_NORANDOMPICK "MMABC_NO_RANDOM_PICK" - -// gchords use tracks with vpos 1 thru 7 -// drums use track with vpos 8 -// voice chords use vpos 0 and vpos from 11 up -#define GCHORDBPOS 1 -#define GCHORDFPOS 2 -#define GCHORDCPOS 3 -#define DRUMPOS 8 -#define DRONEPOS1 9 -#define DRONEPOS2 10 - -// in the patterns a whole note at unmodified tempo is 16 rows -#define ROWSPERNOTE 16 -// a 1/64-th note played in triool equals a 1/96-th note, to be able -// to play them and also to play the 1/64-th we need a resolution of 192 -// because 2/192 = 1/96 and 3/192 = 1/64 -#define RESOLUTION 192 - -#pragma pack(1) - -/************************************************************************** -**************************************************************************/ -#ifdef NEWMIKMOD -static char ABC_Version[] = "ABC+2.0 (draft IV)"; -#endif - -typedef enum { - note, - octave, - smpno, - volume, - effect, - effoper -} ABCEVENT_X_NOTE; - -typedef enum { - none, - trill, - bow, - accent -} ABCEVENT_X_EFFECT; - -typedef enum { - cmdflag, - command, - chordnum, - chordnote, - chordbase, - jumptype -} ABCEVENT_X_CMD; - -typedef enum { - cmdsegno = '$', - cmdcapo = 'B', - cmdchord = 'C', - cmdfine = 'F', - cmdhide = 'H', - cmdjump = 'J', - cmdloop = 'L', - cmdcoda = 'O', - cmdpartbrk = 'P', - cmdsync = 'S', - cmdtempo = 'T', - cmdvariant = 'V', - cmdtocoda = 'X' -} ABCEVENT_CMD; - -typedef enum { - jumpnormal, - jumpfade, - jumpdacapo, - jumpdcfade, - jumpdasegno, - jumpdsfade, - jumpfine, - jumptocoda, - jumpvariant, - jumpnot -} ABCEVENT_JUMPTYPE; - -typedef struct _ABCEVENT -{ - struct _ABCEVENT *next; - uint32_t tracktick; - union { - uint8_t par[6]; - struct { - uint8_t flg; - uint8_t cmd; - uint32_t lpar; // for variant selections, bit pattern - }; - }; - uint8_t part; - uint8_t tiednote; -} ABCEVENT; - -typedef struct _ABCTRACK -{ - struct _ABCTRACK *next; - ABCEVENT *head; - ABCEVENT *tail; - ABCEVENT *capostart; - ABCEVENT *tienote; - int transpose; - int octave_shift; - uint32_t slidevoltime; // for crescendo and diminuendo - int slidevol; // -2:fade away, -1:diminuendo, 0:none, +1:crescendo - uint8_t vno; // 0 is track is free for use, from previous song in multi-songbook - uint8_t vpos; // 0 is main voice, other is subtrack for gchords, gchords or drumnotes - uint8_t tiedvpos; - uint8_t mute; - uint8_t chan; // 10 is percussion channel, any other is melodic channel - uint8_t volume; - uint8_t instr; // current instrument for this track - uint8_t legato; - char v[22]; // first twenty characters are significant -} ABCTRACK; - -typedef struct _ABCMACRO -{ - struct _ABCMACRO *next; - char *name; - char *subst; - char *n; -} ABCMACRO; - -/************************************************************************** -**************************************************************************/ - -typedef struct _ABCHANDLE -{ -#ifdef NEWMIKMOD - MM_ALLOC *allochandle; - MM_ALLOC *macrohandle; - MM_ALLOC *trackhandle; - MM_ALLOC *ho; -#endif - ABCMACRO *macro; - ABCMACRO *umacro; - ABCTRACK *track; - long int pickrandom; - unsigned int len; - int speed; - char *line; - char *beatstring; - uint8_t beat[4]; // a:first note, b:strong notes, c:weak notes, n:strong note every n - char gchord[80]; // last setting for gchord - char drum[80]; // last setting for drum - char drumins[80]; // last setting for drum - char drumvol[80]; // last setting for drum - uint32_t barticks; - // parse variables, declared here to avoid parameter pollution - int abcchordvol, abcchordprog, abcbassvol, abcbassprog; - int ktrans; - int drumon, gchordon, droneon; - int dronegm, dronepitch[2], dronevol[2]; - ABCTRACK *tp, *tpc, *tpr; - uint32_t tracktime; -} ABCHANDLE; - -static int global_voiceno, global_octave_shift, global_tempo_factor, global_tempo_divider; -static char global_part; -static uint32_t global_songstart; -/* Named guitar chords */ -static char chordname[MAXCHORDNAMES][8]; -static int chordnotes[MAXCHORDNAMES][6]; -static int chordlen[MAXCHORDNAMES]; -static int chordsnamed = 0; - -static const char *sig[] = { - " C D EF G A Bc d ef g a b", // 7 sharps C# - " C D EF G AB c d ef g ab ", // 6 sharps F# - " C DE F G AB c de f g ab ", // 5 sharps B - " C DE F GA B c de f ga b ", // 4 sharps E - " CD E F GA B cd e f ga b ", // 3 sharps A - " CD E FG A B cd e fg a b ", // 2 sharps D - " C D E FG A Bc d e fg a b", // 1 sharps G - " C D EF G A Bc d ef g a b", // 0 sharps C - " C D EF G AB c d ef g ab ", // 1 flats F - " C DE F G AB c de f g ab ", // 2 flats Bb - " C DE F GA B c de f ga b ", // 3 flats Eb - " CD E F GA B cd e f ga b ", // 4 flats Ab - " CD E FG A B cd e fg a b ", // 5 flats Db - "C D E FG A Bc d e fg a b ", // 6 flats Gb - "C D EF G A Bc d ef g a b ", // 7 flats Cb -// 0123456789012345678901234 -}; - -static const char *keySigs[] = { -/* 0....:....1....:....2....:....3....:....4....:....5. */ - "7 sharps: C# A#m G#Mix D#Dor E#Phr F#Lyd B#Loc ", - "6 sharps: F# D#m C#Mix G#Dor A#Phr BLyd E#Loc ", - "5 sharps: B G#m F#Mix C#Dor D#Phr ELyd A#Loc ", - "4 sharps: E C#m BMix F#Dor G#Phr ALyd D#Loc ", - "3 sharps: A F#m EMix BDor C#Phr DLyd G#Loc ", - "2 sharps: D Bm AMix EDor F#Phr GLyd C#Loc ", - "1 sharp : G Em DMix ADor BPhr CLyd F#Loc ", - "0 sharps: C Am GMix DDor EPhr FLyd BLoc ", - "1 flat : F Dm CMix GDor APhr BbLyd ELoc ", - "2 flats : Bb Gm FMix CDor DPhr EbLyd ALoc ", - "3 flats : Eb Cm BbMix FDor GPhr AbLyd DLoc ", - "4 flats : Ab Fm EbMix BbDor CPhr DbLyd GLoc ", - "5 flats : Db Bbm AbMix EbDor FPhr GbLyd CLoc ", - "6 flats : Gb Ebm DbMix AbDor BbPhr CbLyd FLoc ", - "7 flats : Cb Abm GbMix DbDor EbPhr FbLyd BbLoc ", - 0 -}; - -// local prototypes -static int abc_getnumber(const char *p, int *number); -static ABCTRACK *abc_locate_track(ABCHANDLE *h, const char *voice, int pos); -static void abc_add_event(ABCHANDLE *h, ABCTRACK *tp, ABCEVENT *e); -static void abc_add_setloop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime); -static void abc_add_setjumploop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, ABCEVENT_JUMPTYPE j); -static uint32_t abc_pattracktime(ABCHANDLE *h, uint32_t tracktime); -static int abc_patno(ABCHANDLE *h, uint32_t tracktime); - -#ifndef HAVE_SETENV -static void setenv(const char *name, const char *value, int overwrite) -{ - int len = strlen(name)+1+strlen(value)+1; - char *str = (char *)malloc(len); - sprintf(str, "%s=%s", name, value); - putenv(str); - free(str); -} -#endif - -static int abc_isvalidchar(char c) { - return(isalpha(c) || isdigit(c) || isspace(c) || c == '%' || c == ':'); -} - -static const char *abc_skipspace(const char *p) -{ - while (*p && isspace(*p)) - p++; - return p; -} - -static void abc_extractkeyvalue(char *key, size_t key_max, - char *value, size_t value_max, const char *src) -{ - while (*src && isspace(*src)) - src++; - - size_t key_size; - for (key_size = 0; key_size < key_max - 1 && *src;) { - if (*src == '=') { - src++; - break; - } - key[key_size++] = *src++; - } - while (key_size > 0 && isspace(key[key_size - 1])) - key_size--; - key[key_size] = '\0'; - - while (*src && isspace(*src)) - src++; - - size_t value_size; - for (value_size = 0; value_size < value_max - 1 && *src;) - value[value_size++] = *src++; - while (value_size > 0 && isspace(value[value_size - 1])) - value_size--; - value[value_size] = '\0'; -} - -static void abc_message(const char *s1, const char *s2) -{ - char txt[256]; - if( strlen(s1) + strlen(s2) > 255 ) return; - sprintf(txt, s1, s2); -#ifdef NEWMIKMOD - _mmlog(txt); -#else - fprintf(stderr, "load_abc > %s\n", txt); -#endif -} - -static uint32_t modticks(uint32_t abcticks) -{ - return abcticks / RESOLUTION; -} - -static uint32_t abcticks(uint32_t modticks) -{ - return modticks * RESOLUTION; -} - -static uint32_t notelen_notediv_to_ticks(int speed, int len, int div) -{ - uint32_t u; - if (div == 0) return 0; - u = (ROWSPERNOTE * RESOLUTION * speed * len * global_tempo_factor) / (div * global_tempo_divider); - return u; -} - -static void abc_dumptracks(ABCHANDLE *h, const char *p) -{ - ABCTRACK *t; - ABCEVENT *e; - int n,pat,row,tck; - char nn[3]; - if( !h ) return; - for( t=h->track; t; t=t->next ) { - printf("track %d.%d chan=%d %s\n", (int)(t->vno), (int)(t->vpos), - (int)(t->chan), (char *)(t->v)); - if( strcmp(p,"nonotes") ) - n = 1; - else - n = 0; - for( e=t->head; e; e=e->next ) { - tck = modticks(e->tracktick); - row = tck / h->speed; - pat = row / 64; - tck = tck % h->speed; - row = row % 64; - nn[0] = ( e->tracktick % abcticks(h->speed * 64) ) ? ' ': '-'; - if( e->flg == 1 ) { - printf(" %6d.%02d.%d%c%c %d.%d %s ", - pat, row, tck, nn[0], (int)(e->part), (int)(t->vno), - (int)(t->vpos), (char *)(t->v)); - if( e->cmd == cmdchord ) { - nn[0] = "CCCDDEFFGGAABccddeffggaabb"[e->par[chordnote]]; - nn[1] = "b # # # # # # # # # # #"[e->par[chordnote]]; - nn[2] = '\0'; - if( isspace(nn[1]) ) nn[1] = '\0'; - printf("CMD %c: gchord %s%s", - (char)(e->cmd), nn, chordname[e->par[chordnum]]); - if( e->par[chordbase] != e->par[chordnote] ) { - nn[0] = "CCCDDEFFGGAABccddeffggaabb"[e->par[chordbase]]; - nn[1] = "b # # # # # # # # # # #"[e->par[chordbase]]; - nn[2] = '\0'; - printf("/%s", nn); - } - printf("\n"); - } - else - printf("CMD %c @%p 0x%08lX\n", - (char)(e->cmd), e, - (unsigned long)(e->lpar)); - if( strcmp(p,"nonotes") ) - n = 1; - else - n = 0; - } - else if( n ) { - printf(" %6d.%02d.%d%c%c %d.%d %s ", pat, row, tck, nn[0], e->part, t->vno, t->vpos, t->v); - if( e->par[note] ) { - nn[0] = "CCCDDEFFGGAABccddeffggaabb"[e->par[note]-23]; - nn[1] = "b # # # # # # # # # # #"[e->par[note]-23]; - nn[2] = '\0'; - } - else strcpy(nn,"--"); - printf("NOTE %s octave %d inst %s vol %03d\n", - nn, e->par[octave], pat_gm_name(pat_smptogm(e->par[smpno])),e->par[volume]); - if( strcmp(p,"all") ) - n = 0; - } - } - } -} - -#ifdef NEWMIKMOD - -#define MMFILE MMSTREAM -#define mmfgetc(x) _mm_read_SBYTE(x) -#define mmfeof(x) _mm_feof(x) -#define mmfgets(buf,sz,f) _mm_fgets(f,buf,sz) -#define mmftell(x) _mm_ftell(x) -#define mmfseek(f,p,w) _mm_fseek(f,p,w) -#define mmfopen(s,m) _mm_fopen(s,m) -#define mmfclose(f) _mm_fclose(f) - -#else - -#if defined(WIN32) && defined(_mm_free) -#undef _mm_free -#endif - -#define MMSTREAM FILE -#define _mm_fopen(name,mode) fopen(name,mode) -#define _mm_fgets(f,buf,sz) fgets(buf,sz,f) -#define _mm_fseek(f,pos,whence) fseek(f,pos,whence) -#define _mm_ftell(f) ftell(f) -#define _mm_read_UBYTES(buf,sz,f) fread(buf,sz,1,f) -#define _mm_read_SBYTES(buf,sz,f) fread(buf,sz,1,f) -#define _mm_feof(f) feof(f) -#define _mm_fclose(f) fclose(f) -#define DupStr(h,buf,sz) strdup(buf) -#define _mm_calloc(h,n,sz) calloc(n,sz) -#define _mm_recalloc(h,buf,sz,elsz) realloc(buf,sz) -#define _mm_free(h,p) free(p) - -typedef struct { - char *mm; - int sz; - int pos; -} MMFILE; - -static MMFILE *mmfopen(const char *name, const char *mode) -{ - FILE *fp; - MMFILE *mmfile; - long len; - if( *mode != 'r' ) return NULL; - fp = fopen(name, mode); - if( !fp ) return NULL; - fseek(fp, 0, SEEK_END); - len = ftell(fp); - mmfile = (MMFILE *)malloc(len+sizeof(MMFILE)); - if( !mmfile ) return NULL; - fseek(fp, 0, SEEK_SET); - fread(&mmfile[1],1,len,fp); - fclose(fp); - mmfile->mm = (char *)&mmfile[1]; - mmfile->sz = len; - mmfile->pos = 0; - return mmfile; -} - -static void mmfclose(MMFILE *mmfile) -{ - free(mmfile); -} - -static bool mmfeof(MMFILE *mmfile) -{ - if( mmfile->pos < 0 ) return TRUE; - if( mmfile->pos < mmfile->sz ) return FALSE; - return TRUE; -} - -static int mmfgetc(MMFILE *mmfile) -{ - int b; - if( mmfeof(mmfile) ) return EOF; - b = mmfile->mm[mmfile->pos]; - mmfile->pos++; - if( b=='\r' && !mmfeof(mmfile) && mmfile->mm[mmfile->pos] == '\n' ) { - b = '\n'; - mmfile->pos++; - } - return b; -} - -static void mmfgets(char buf[], unsigned int bufsz, MMFILE *mmfile) -{ - int i,b; - for( i=0; i<(int)bufsz-1; i++ ) { - b = mmfgetc(mmfile); - if( b==EOF ) break; - buf[i] = b; - if( b == '\n' ) break; - } - buf[i] = '\0'; -} - -static long mmftell(MMFILE *mmfile) -{ - return mmfile->pos; -} - -static void mmfseek(MMFILE *mmfile, long p, int whence) -{ - switch(whence) { - case SEEK_SET: - mmfile->pos = p; - break; - case SEEK_CUR: - mmfile->pos += p; - break; - case SEEK_END: - mmfile->pos = mmfile->sz + p; - break; - } -} -#endif - -// ===================================================================================== -static ABCEVENT *abc_new_event(ABCHANDLE *h, uint32_t abctick, const char data[]) -// ===================================================================================== -{ - ABCEVENT *retval; - int i; - - retval = (ABCEVENT *)_mm_calloc(h->trackhandle, 1,sizeof(ABCEVENT)); - retval->next = NULL; - retval->tracktick = abctick; - for( i=0; i<6; i++ ) - retval->par[i] = data[i]; - retval->part = global_part; - retval->tiednote = 0; - return retval; -} - -// ============================================================================= -static ABCEVENT *abc_copy_event(ABCHANDLE *h, ABCEVENT *se) -// ============================================================================= -{ - ABCEVENT *e; - e = (ABCEVENT *)_mm_calloc(h->trackhandle, 1,sizeof(ABCEVENT)); - e->next = NULL; - e->tracktick = se->tracktick; - e->flg = se->flg; - e->cmd = se->cmd; - e->lpar = se->lpar; - e->part = se->part; - return e; -} - -// ============================================================================= -static void abc_new_macro(ABCHANDLE *h, const char *m) -// ============================================================================= -{ - ABCMACRO *retval; - char key[256], value[256]; - abc_extractkeyvalue(key, sizeof(key), value, sizeof(value), m); - - retval = (ABCMACRO *)_mm_calloc(h->macrohandle, 1,sizeof(ABCTRACK)); - retval->name = DupStr(h->macrohandle, key, strlen(key)); - retval->n = strrchr(retval->name, 'n'); // for transposing macro's - retval->subst = DupStr(h->macrohandle, value, strlen(value)); - retval->next = h->macro; - h->macro = retval; -} - -// ============================================================================= -static void abc_new_umacro(ABCHANDLE *h, const char *m) -// ============================================================================= -{ - ABCMACRO *retval, *mp; - char key[256], value[256]; - abc_extractkeyvalue(key, sizeof(key), value, sizeof(value), m); - if( strlen(key) > 1 || strchr("~HIJKLMNOPQRSTUVWXY",toupper(key[0])) == 0 ) return; - while( char *q = strchr(key, '!') ) - *q = '+'; // translate oldstyle to newstyle - if( !strcmp(key,"+nil+") ) { // delete a macro - mp = NULL; - for( retval=h->umacro; retval; retval = retval->next ) { - if( retval->name[0] == key[0] ) { // delete this one - if( mp ) mp->next = retval->next; - else h->umacro = retval->next; - _mm_free(h->macrohandle, retval); - return; - } - mp = retval; - } - return; - } - retval = (ABCMACRO *)_mm_calloc(h->macrohandle, 1,sizeof(ABCTRACK)); - retval->name = DupStr(h->macrohandle, key, 1); - retval->subst = DupStr(h->macrohandle, value, strlen(value)); - retval->n = 0; - retval->next = h->umacro; // by placing it up front we mask out the old macro until we +nil+ it - h->umacro = retval; -} - -// ============================================================================= -static ABCTRACK *abc_new_track(ABCHANDLE *h, const char *voice, int pos) -// ============================================================================= -{ - ABCTRACK *retval; - if( !pos ) global_voiceno++; - retval = (ABCTRACK *)_mm_calloc(h->trackhandle, 1,sizeof(ABCTRACK)); - retval->next = NULL; - retval->vno = global_voiceno; - retval->vpos = pos; - retval->tiedvpos = pos; - retval->instr = 1; - strncpy(retval->v, voice, 20); - retval->v[20] = '\0'; - retval->head = NULL; - retval->tail = NULL; - retval->capostart = NULL; - retval->tienote = NULL; - retval->mute = 0; - retval->chan = 0; - retval->transpose = 0; - retval->volume = h->track? h->track->volume: 120; - retval->slidevoltime = 0; - retval->slidevol = 0; - retval->legato = 0; - return retval; -} - -static int abc_numtracks(ABCHANDLE *h) -{ - int n; - ABCTRACK *t; - n=0; - for( t = h->track; t; t=t->next ) - n++; - return n; -} - -static int abc_interval(const char *s, const char *d) -{ - const char *p; - int i,j,k; - int n,oct,m[2]; - for( j=0; j<2; j++ ) { - if( j ) p = d; - else p = s; - switch(p[0]) { - case '^': - n = p[1]; - i = 2; - break; - case '_': - n = p[1]; - i = 2; - break; - case '=': - n = p[1]; - i = 2; - break; - default: - n = p[0]; - i = 1; - break; - } - for( k=0; k<25; k++ ) - if( n == sig[7][k] ) - break; - oct = 4; // ABC note pitch C is C4 and pitch c is C5 - if( k > 12 ) { - oct++; - k -= 12; - } - while( p[i] == ',' || p[i] == '\'' ) { - if( p[i] == ',' ) - oct--; - else - oct++; - i++; - } - m[j] = k + 12 * oct; - } - return m[0] - m[1]; -} - -static int abc_transpose(const char *v) -{ - int i,j,t; - const char *m = "B", *mv = ""; - t = 0; - global_octave_shift = 99; - for( ; *v && *v != ']'; v++ ) { - if( !strncasecmp(v,"t=",2) ) { - v+=2; - if( *v=='-' ) { - j = -1; - v++; - } - else j = 1; - v+=abc_getnumber(v,&i); - t += i * j; - global_octave_shift = 0; - } - if( !strncasecmp(v,"octave=",7) ) { - v+=7; - if( *v=='-' ) { - j = -1; - v++; - } - else j = 1; - v+=abc_getnumber(v,&i); - t += i * j * 12; - global_octave_shift = 0; - } - if( !strncasecmp(v,"transpose=",10) ) { - v+=10; - if( *v=='-' ) { - j = -1; - v++; - } - else j = 1; - v+=abc_getnumber(v,&i); - t += i * j; - global_octave_shift = 0; - } - if( !strncasecmp(v,"octave=",7) ) { // used in kv304*.abc - v+=7; - if( *v=='-' ) { - j = -1; - v++; - } - else j = 1; - v+=abc_getnumber(v,&i); - t += i * j * 12; - global_octave_shift = 0; - } - if( !strncasecmp(v,"m=",2) ) { - v += 2; - mv = v; // get the pitch for the middle staff line - while( *v && *v != ' ' && *v != ']' ) v++; - global_octave_shift = 0; - } - if( !strncasecmp(v,"middle=",7) ) { - v += 7; - mv = v; // get the pitch for the middle staff line - while( *v && *v != ' ' && *v != ']' ) v++; - global_octave_shift = 0; - } - if( !strncasecmp(v,"clef=",5) ) - v += 5; - j = 1; - if( !strncasecmp(v,"treble",6) ) { - j = 0; - v += 6; - switch( *v ) { - case '1': v++; m = "d"; break; - case '2': v++; - default: m = "B"; break; - case '3': v++; m = "G"; break; - case '4': v++; m = "E"; break; - case '5': v++; m = "C"; break; - } - global_octave_shift = 0; - } - if( j && !strncasecmp(v,"bass",4) ) { - m = "D,"; - j = 0; - v += 4; - switch( *v ) { - case '1': v++; m = "C"; break; - case '2': v++; m = "A,"; break; - case '3': v++; m = "F,"; break; - case '4': v++; - default: m = "D,"; break; - case '5': v++; m = "B,,"; break; - } - if( global_octave_shift == 99 ) - global_octave_shift = -2; - } - if( j && !strncasecmp(v,"tenor",5) ) { - j = 0; - v += 5; - switch( *v ) { - case '1': v++; m = "G"; break; - case '2': v++; m = "E"; break; - case '3': v++; m = "C"; break; - case '4': v++; - default: m = "A,"; break; - case '5': v++; m = "F,"; break; - } - if( global_octave_shift == 99 ) - global_octave_shift = 1; - } - if( j && !strncasecmp(v,"alto",4) ) { - j = 0; - v += 4; - switch( *v ) { - case '1': v++; m = "G"; break; - case '2': v++; m = "E"; break; - case '3': v++; - default: m = "C"; break; - case '4': v++; m = "A,"; break; - case '5': v++; m = "F,"; break; - } - if( global_octave_shift == 99 ) - global_octave_shift = 1; - } - if( j && strchr("+-",*v) && *v && v[1]=='8' ) { - switch(*v) { - case '+': - t += 12; - break; - case '-': - t -= 12; - break; - } - v += 2; - if( !strncasecmp(v,"va",2) ) v += 2; - global_octave_shift = 0; - j = 0; - } - if( j ) { - while( *v && *v != ' ' && *v != ']' ) v++; - } - } - if( strlen(mv) > 0 ) // someone set the middle note - t += abc_interval(mv, m); - if( global_octave_shift == 99 ) - global_octave_shift = 0; - return t; -} - -// ============================================================================= -static ABCTRACK *abc_locate_track(ABCHANDLE *h, const char *voice, int pos) -// ============================================================================= -{ - ABCTRACK *tr, *prev, *trunused; - char vc[21]; - int i, trans=0, voiceno=0, instrno = 1, channo = 0; - for( ; *voice == ' '; voice++ ) ; // skip leading spaces - for( i=0; i+1 < sizeof(vc) && *voice && *voice != ']' && *voice != '%' && !isspace(*voice); voice++ ) // can work with inline voice instructions - vc[i++] = *voice; - vc[i] = '\0'; - prev = NULL; - trunused = NULL; - if( !pos ) trans = abc_transpose(voice); - for( tr=h->track; tr; tr=tr->next ) { - if( tr->vno == 0 ) { - if( !trunused ) trunused = tr; // must reuse mastertrack (h->track) as first - } - else { - if( !strncasecmp(tr->v, vc, 20) ) { - if( tr->vpos == pos ) - return tr; - trans = tr->transpose; - global_octave_shift = tr->octave_shift; - voiceno = tr->vno; - instrno = tr->instr; - channo = tr->chan; - } - } - prev = tr; - } - if( trunused ) { - tr = trunused; - if( pos ) { - tr->vno = voiceno; - tr->instr = instrno; - tr->chan = channo; - } - else { - global_voiceno++; - tr->vno = global_voiceno; - tr->instr = 1; - tr->chan = 0; - } - tr->vpos = pos; - tr->tiedvpos = pos; - strncpy(tr->v, vc, 20); - tr->v[20] = '\0'; - tr->mute = 0; - tr->transpose = trans; - tr->octave_shift = global_octave_shift; - tr->volume = h->track->volume; - tr->tienote = NULL; - tr->legato = 0; - return tr; - } - tr = abc_new_track(h, vc, pos); - if( pos ) { - tr->vno = voiceno; - tr->instr = instrno; - tr->chan = channo; - } - tr->transpose = trans; - tr->octave_shift = global_octave_shift; - if( prev ) prev->next = tr; - else h->track = tr; - return tr; -} - -// ============================================================================= -static ABCTRACK *abc_check_track(ABCHANDLE *h, ABCTRACK *tp) -// ============================================================================= -{ - if( !tp ) { - tp = abc_locate_track(h, "", 0); // must work for voiceless abc too... - tp->transpose = h->ktrans; - } - return tp; -} - -static void abc_add_capo(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdcapo; - e = abc_new_event(h, tracktime, d); - tp->capostart = e; - abc_add_event(h, tp, e); // do this last (recursion danger) -} - -static void abc_add_segno(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdsegno; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_coda(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdcoda; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_fine(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdfine; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_tocoda(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdtocoda; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -// first track is dirigent, remove all control events from other tracks -// to keep the information where the events should be relative to note events -// in the same tick the ticks are octated and four added for note events -// the control events that come before the note events get a decremented tick, -// those that come after get an incremented tick, for example: -// ctrl ctrl note ctrl ctrl note -// original: t t t t t+1 t+1 -// recoded: 8t+1 8t+2 8t+4 8t+5 8t+11 8t+12 -static void abc_remove_unnecessary_events(ABCHANDLE *h) -{ - ABCTRACK *tp,*ptp; - ABCEVENT *ep, *el; - uint32_t ct, et; - int d; - ptp = NULL; - for( tp=h->track; tp; tp=tp->next ) { - el = NULL; - ep = tp->head; - ct = 0; - d = -3; - while( ep ) { - et = ep->tracktick; - ep->tracktick <<= 3; - ep->tracktick += 4; - if( ep->flg == 1 ) { - ep->tracktick += d; - d++; - if( d == 0 ) d = -1; - if( d == 4 ) d = 3; - if( tp!=h->track ) ep->cmd = cmdhide; - switch( ep->cmd ) { - case cmdhide: - case cmdsync: - if( el ) { - el->next = ep->next; - if( !el->next ) - tp->tail = el; - _mm_free(h->trackhandle,ep); - ep = el->next; - } - else { - tp->head = ep->next; - if( !tp->head ) - tp->tail = NULL; - _mm_free(h->trackhandle,ep); - ep = tp->head; - } - break; - default: - el = ep; - ep = ep->next; - break; - } - } - else { - el = ep; - ep = ep->next; - d = 1; - } - if( et > ct ) - d = -3; - ct = et; - } - if( !tp->head ) { // no need to keep empty tracks... - if( ptp ) { - ptp->next = tp->next; - _mm_free(h->trackhandle,tp); - tp = ptp; - } - else if (tp->next) { - h->track = tp->next; - _mm_free(h->trackhandle,tp); - tp = h->track; - } else { - break; - } - } - ptp = tp; // remember previous track - } -} - -// set ticks back, and handle partbreaks -static void abc_retick_events(ABCHANDLE *h) -{ - ABCTRACK *tp; - ABCEVENT *ep; - uint32_t et, tt=0, at = abcticks(64 * h->speed); - for( tp=h->track; tp; tp=tp->next ) { - // make ticks relative - tt = 0; - for( ep=tp->head; ep; ep=ep->next ) { - et = ep->tracktick >> 3; - ep->tracktick = et - tt; - tt = et; - } - // make ticks absolute again, skipping no-op partbreaks - tt = 0; - for( ep=tp->head; ep; ep=ep->next ) { - ep->tracktick += tt; - tt = ep->tracktick; - if( ep->flg == 1 && ep->cmd == cmdpartbrk ) { - if( tt % at ) { - tt += at; - tt /= at; - tt *= at; - ep->tracktick -= abcticks(h->speed); // break plays current row - } - else ep->cmd = cmdhide; - } - } - } -} - -// make sure every track has the control events it needs, this way it is not -// necessary to have redundant +segno+ +D.C.+ etc in the voices, the first voice -// is the master, it is pointed to by the member 'track' in the ABCHANDLE -static void abc_synchronise_tracks(ABCHANDLE *h) -{ - ABCTRACK *tp; - uint32_t tm; // tracktime in master - ABCEVENT *em, *es, *et, *ec; // events in master, slave, slave temporary and copied event - if( !h || !h->track ) return; - abc_remove_unnecessary_events(h); - for( tp = h->track->next; tp; tp = tp->next ) { - for( em=h->track->head; em; em=em->next ) { - if( em->flg == 1 ) { // some kind of control event - switch( em->cmd ) { - case cmdchord: - case cmdhide: - case cmdtempo: - case cmdsync: - break; - default: // check to see if copy is necessary - ec = abc_copy_event(h, em); - tm = em->tracktick; - es = tp->head; // allways search from the begin... - for( et=es; et && et->tracktick <= tm; et=et->next ) - es = et; - if( es == NULL || es->tracktick > tm ) { // special case: head of track - ec->next = es; - tp->head = ec; - } - else { - ec->next = es->next; - es->next = ec; - } - break; - } - } - } - } - abc_retick_events(h); -} - -static void abc_add_event(ABCHANDLE *h, ABCTRACK *tp, ABCEVENT *e) -{ - if( !tp->capostart ) abc_add_capo(h, tp, global_songstart); - if( tp->tail ) { - tp->tail->next = e; - tp->tail = e; - } - else { - tp->head = e; - tp->tail = e; - } -} - -static void abc_add_partbreak(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdpartbrk; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_tempo_event(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int tempo) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdtempo; - e = abc_new_event(h, tracktime, d); - e->lpar = tempo; - abc_add_event(h, tp, e); -} - -static void abc_add_noteoff(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - d[note] = 0; - d[octave] = 0; - d[smpno] = pat_gmtosmp(tp->instr); - d[volume] = 0; - d[effect] = 0; - d[effoper] = 0; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static int abc_dynamic_volume(ABCTRACK *tp, uint32_t tracktime, int vol) -{ - uint32_t slidetime; - int voldelta; - if( tp->mute ) return 0; - if( tp->slidevol == 0 ) return vol; - if( tracktime < tp->slidevoltime ) return vol; - slidetime = modticks(tracktime - tp->slidevoltime); - voldelta = (slidetime * 15) / 64 / 6; // slide from say mf up to f in one pattern's time - if( tp->slidevol > -2 && voldelta > 15 ) voldelta = 15; // never to much dynamics - if( tp->slidevol > 0 ) vol += voldelta; - else vol -= voldelta; - if( vol < 2 ) vol = 2; // xmms divides this by 2.... - if( vol > 127 ) vol = 127; - return vol; -} - -static void abc_track_untie_short_chordnotes(ABCHANDLE *h) -{ - ABCTRACK *tp; - int vn; - tp = h->tp; - vn = tp->vno; - for( tp = h->track; tp; tp = tp->next ) - if( tp != h->tp && tp->vno == vn && tp->tienote ) { - abc_message("short notes in chord can not be tied:\n%s", h->line); - tp->tienote = 0; - } -} - -static void abc_track_clear_tiednote(ABCHANDLE *h) -{ - ABCTRACK *tp; - int vn; - tp = h->tp; - vn = tp->vno; - for( tp = h->track; tp; tp = tp->next ) - if( tp->vno == vn ) tp->tienote = 0; -} - -static void abc_track_clear_tiedvpos(ABCHANDLE *h) -{ - ABCTRACK *tp; - int vn; - tp = h->tp; - vn = tp->vno; - for( tp = h->track; tp; tp = tp->next ) - if( tp->vno == vn ) tp->tiedvpos = tp->vpos; -} - -static ABCTRACK *abc_track_with_note_tied(ABCHANDLE *h, uint32_t tracktime, int n, int oct) -{ - int vn, vp; - ABCTRACK *tp; - ABCEVENT *e; - tp = h->tp; - vn = tp->vno; - vp = tp->vpos; - for( tp = h->track; tp; tp = tp->next ) { - if( tp->vno == vn ) { - e = tp->tienote; - if( e && e->tracktick < tracktime - && e->par[octave] == oct && abs(e->par[note] - n) < 3 ) { - if( tp->vpos != vp ) tp->tiedvpos = vp; - h->tp = tp; - return tp; - } - } - } - tp = h->tp; - vp = tp->tiedvpos; - if( tp->vpos != vp ) { - // chord note track allready returned in previous call - for( tp = h->track; tp; tp = tp->next ) { - if( tp->vno == vn && tp->vpos == vp ) { - tp->tiedvpos = h->tp->vpos; - h->tp = tp; - return tp; - } - } - } - return h->tp; -} - -static int abc_add_noteon(ABCHANDLE *h, int ch, const char *p, uint32_t tracktime, char *barkey, int vol, ABCEVENT_X_EFFECT fx, int fxop) -{ - ABCEVENT *e; - ABCTRACK *tp; - int i,j,k; - int n,oct; - char d[6]; - tp = h->tp; - switch(ch) { - case '^': - if( p[0] == '^' ) { - n = p[1]; - i = 2; - ch = 'x'; - } - else { - n = p[0]; - i = 1; - } - break; - case '_': - if( p[0] == '_' ) { - n = p[1]; - i = 2; - ch = 'b'; - } - else { - n = p[0]; - i = 1; - } - break; - case '=': - n = p[0]; - i = 1; - break; - default: - n = ch; - i = 0; - break; - } - for( k=0; k<51; k++ ) { - if( n == barkey[k] ) - break; - } - j = k; - if( k > 24 ) - k -= 25; // had something like A# over Bb key F signature.... - if( i ) { - // propagate accidentals if necessary - // DON'T do redundant accidentals they're always relative to C-scale - for( k=0; k<25; k++ ) { - if( n == sig[7][k] ) - break; - } - if( k < 25 ) { // only do real notes... - switch(ch) { - case 'x': - k++; - case '^': - k++; - break; - case 'b': - k--; - case '_': - k--; - break; - case '=': - break; - } - if( j < 25 ) // was it not A# over Bb? - barkey[j] = ' '; - barkey[k] = n; - } - } - oct = 3; // ABC note pitch C is C4 and pitch c is C5 - if( k < 25 ) { - k += tp->transpose; - while( k > 12 ) { - oct++; - k -= 12; - } - while( k < 0 ) { - oct--; - k += 12; - } - d[note] = 23 + k; // C0 is midi notenumber 24 - } - else - d[note] = 0; // someone has doen ^X3 or something like it... - while( p[i] && strchr(",'",p[i]) ) { - if( p[i]==',' ) oct--; - else oct++; - i++; - tp->octave_shift = 0; // forget we ever had to look at it - } - if( tp->octave_shift ) - tp->transpose += 12 * tp->octave_shift; - oct += tp->octave_shift; - tp->octave_shift = 0; // after the first note we never have to look at it again - if( oct < 0 ) oct = 0; - if( oct > 9 ) oct = 9; - d[octave] = oct; - d[smpno] = pat_gmtosmp(tp->instr); - d[volume] = abc_dynamic_volume(tp, tracktime, vol); - d[effect] = fx; // effect - d[effoper] = fxop; - tp = abc_track_with_note_tied(h, tracktime, d[note], oct); - if( tp->tienote ) { - if( tp->tienote->par[note] != d[note] ) { - if( abs(tp->tienote->par[note] - d[note]) < 3 ) { - // may be tied over bar symbol, recover local accidental to barkey - k = tp->tienote->par[note] - 23 - tp->transpose; - while( k < 0 ) k += 12; - while( k > 12 ) k -= 12; - if( (isupper(n) && barkey[k+12] == ' ') || (islower(n) && barkey[k] == ' ') ) { - barkey[j] = ' '; - if( isupper(n) ) - barkey[k] = n; - else - barkey[k+12] = n; - d[note] = tp->tienote->par[note]; - d[octave] = tp->tienote->par[octave]; - } - } - } - } - if( tp->tienote - && tp->tienote->par[note] == d[note] - && tp->tienote->par[octave] == d[octave] ) { - for( e = tp->tienote; e; e = e->next ) { - if( e->par[note] == 0 && e->par[octave] == 0 ) { // undo noteoff - e->flg = 1; - e->cmd = cmdhide; - e->lpar = 0; - break; - } - } - tp->tienote->tiednote = 1; // mark him for the pattern writers - for( j=i; isdigit(p[j]) || p[j]=='/'; j++ ) ; // look ahead to see if this one is tied too - if( p[j] != '-' ) // is this note tied too? - tp->tienote = NULL; // if not the tie ends here... - return i; - } - tp->tienote = NULL; - if( tp->tail - && tp->tail->tracktick == tracktime - && tp->tail->par[note] == 0 - && tp->tail->par[octave] == 0 ) { - for( j=0; j<6; j++ ) - tp->tail->par[j] = d[j]; - } - else { - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); - } - if( i > 0 && p[i-1] == '"' ) { - i--; // someone coded a weird note like ^"E" - abc_message("strange note encountered scanning %s", h->line); - } - return i; -} - -static void abc_add_dronenote(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int nnum, int vol) -{ - ABCEVENT *e; - int j,k; - int oct; - char d[6]; - oct = -1; // ABC note pitch C is C4 and pitch c is C5 - k = nnum + 1; - while( k > 12 ) { - oct++; - k -= 12; - } - while( k < 0 ) { - oct--; - k += 12; - } - if( oct < 0 ) oct = 0; - d[note] = 23 + k; // C0 is midi notenumber 24 - d[octave] = oct; - d[smpno] = pat_gmtosmp(tp->instr); - d[volume] = abc_dynamic_volume(tp, tracktime, vol); - d[effect] = 0; // effect - d[effoper] = 0; - if( tp->tail - && tp->tail->tracktick == tracktime - && tp->tail->par[note] == 0 - && tp->tail->par[octave] == 0 ) { - for( j=0; j<6; j++ ) - tp->tail->par[j] = d[j]; - } - else { - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); - } -} - -static void abc_add_chordnote(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int nnum, int vol) -{ - abc_add_dronenote(h, tp, tracktime, nnum + 23, tp->mute? 0: vol); -} - -static void abc_add_drumnote(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int nnum, int vol) -{ - abc_add_dronenote(h, tp, tracktime, nnum, tp->mute? 0: vol); -} - -static void abc_add_variant_start(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, int n) -{ - ABCEVENT *e; - char d[6]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdvariant; - e = abc_new_event(h, tracktime, d); - e->lpar = 1<tail->lpar |= 1<flg != 1 && e->par[note] != 0 ) - e->par[volume] = abc_dynamic_volume(tp, e->tracktick, e->par[volume]); - e = e->next; - } -} - -static void abc_add_setjumploop(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime, ABCEVENT_JUMPTYPE j) -{ - ABCEVENT *e; - char d[8]; - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdjump; - d[jumptype] = j; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_sync(ABCHANDLE *h, ABCTRACK *tp, uint32_t tracktime) -{ - ABCEVENT *e; - char d[6]; - e = tp->tail; - if( e && e->tracktick == tracktime ) return; - if( e && e->flg == 1 && e->cmd == cmdsync ) { - e->tracktick = tracktime; - return; - } - d[0] = d[1] = d[2] = d[3] = d[4] = d[5] = 0; - d[cmdflag] = 1; - d[command] = cmdsync; - e = abc_new_event(h, tracktime, d); - abc_add_event(h, tp, e); -} - -static void abc_add_gchord_syncs(ABCHANDLE *h, ABCTRACK *tpc, uint32_t tracktime) -{ - ABCTRACK *tp; - int i; - for( i = GCHORDBPOS; i < DRUMPOS; i++ ) { - tp = abc_locate_track(h, tpc->v, i); - abc_add_sync(h,tp,tracktime); - } -} - -static void abc_add_drum_sync(ABCHANDLE *h, ABCTRACK *tpr, uint32_t tracktime) -{ - ABCTRACK *tp; - tp = abc_locate_track(h, tpr->v, DRUMPOS); - abc_add_sync(h,tp,tracktime); -} - -static int abc_getnumber(const char *p, int *number) -{ - int i,h; - i = 0; - h = 0; - while( isdigit(p[i]) ) { - h = 10 * h + p[i] - '0'; - i++; - } - if( i==0 ) - *number = 1; - else - *number = h; - return i; -} - -static int abc_getexpr(const char *p, int *number) -{ - int i, term, total; - i = 0; - while( isspace(p[i]) ) - i++; - if( p[i] == '(' ) { - i += abc_getexpr(p+i+1, number); - while( p[i] && (p[i] != ')') ) - i++; - return i; - } - i += abc_getnumber(p+i, &total); - while( isspace(p[i]) ) - i++; - while( p[i] == '+' ) { - i += 1 + abc_getexpr(p+i+1, &term); - total += term; - while( isspace(p[i]) ) - i++; - } - *number = total; - return i; -} - -static int abc_notelen(const char *p, int *len, int *div) -{ - int i,h,k; - i = abc_getnumber(p,len); - h = 1; - while( p[i] == '/' ) { - h *= 2; - i++; - } - if( isdigit(p[i]) ) { - h /= 2; - i += abc_getnumber(p+i,&k); - } - else k = 1; - *div = h * k; - return i; -} - -static int abc_brokenrithm(const char *p, int *nl, int *nd, int *b, int hornpipe) -{ - switch( *b ) { - case '<': - *nl *= 3; - *nd *= 2; - hornpipe = 0; - break; - case '>': - *nd *= 2; - hornpipe = 0; - break; - } - *b = *p; - switch( *b ) { - case '>': - *nl *= 3; - *nd *= 2; - return 1; - case '<': - *nd *= 2; - return 1; - default: - *b = 0; - break; - } - if( hornpipe ) { // still true then make 1/8 notes broken rithme - if( *nl == 1 && *nd == 1 ) { - *b = '>'; - *nl = 3; - *nd = 2; - } - } - return 0; -} - -// put p notes in the time q for the next r notes -static int abc_tuplet(int *nl, int *nd, int p, int q, int r) -{ - if( !r ) return 0; - *nl *= q; - *nd *= p; - return r - 1; -} - -// evaluate [Q:"string" n1/m1 n2/m2 n3/m3 n4/m4=bpm "string"] -// minimal form [Q:"string"] -// most used form [Q: 1/4=120] -static int abc_extract_tempo(const char *p, int invoice) -{ - int nl, nd, ns, in, tempo; - int nl1=0, nd1, notes, state; - const char *q; - in = 0; - nl = 0; - nd = 1; - ns = 120; - notes = 0; - state = 0; - for( q=p; *q; q++ ) { - if( in ) { - if( *q=='"' ) - in = 0; - } - else { - if( *q == ']' ) break; - switch( *q ) { - case '"': - in = 1; - break; - case '/': - notes++; - state = 1; - nl1 = ns; - break; - case '=': - break; - default: - if( isdigit(*q) ) { - if( state ) { - q+=abc_getnumber(q,&nd1)-1; - state = 0; - nl = nl * nd1 + nl1 * nd; - nd = nd * nd1; - } - else - q+=abc_getnumber(q,&ns)-1; - } - break; - } - } - } - if( !notes ) { - nl = 1; - nd = 4; - } - if( !nd ) tempo = 120; - else tempo = ns * nl * 4 / nd; // mod tempo is really BPM where one B is equal to a quartnote - if( tempo <= 0 ) - tempo = 120; - if( invoice ) { - nl = global_tempo_factor; - nd = global_tempo_divider; - } - global_tempo_factor = 1; - global_tempo_divider = 1; - while( tempo/global_tempo_divider > 255 ) - global_tempo_divider++; - tempo /= global_tempo_divider; - while( tempo * global_tempo_factor < 256 ) - global_tempo_factor++; - global_tempo_factor--; - tempo *= global_tempo_factor; - if( tempo * 3 < 512 ) { - global_tempo_factor *= 3; - global_tempo_divider *= 2; - tempo = (tempo * 3) / 2; - } - if( invoice ) { - if( nl != global_tempo_factor || nd != global_tempo_divider ) { - ns = (tempo * nl * global_tempo_divider) / (nd * global_tempo_factor); - if( ns > 31 && ns < 256 ) { - tempo = ns; - global_tempo_factor = nl; - global_tempo_divider = nd; - } - else - abc_message("Failure: inconvenient tempo change in middle of voice (%s)", p); - } - } - return tempo; -} - -static void abc_set_parts(char **d, char *p) -{ - int i,j,k,m,n; - char *q; -#ifdef NEWMIKMOD - static MM_ALLOC *h; - if( *d ) _mmalloc_close(h); -#else - if( *d ) free(*d); -#endif - *d = 0; - if( !p ) return; - for( i=0; p[i] && p[i] != '%'; i++ ) { - if( !strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ().0123456789 ",p[i]) ) { - abc_message("invalid characters in part string scanning P:%s", p); - return; - } - } -#ifdef NEWMIKMOD - h = _mmalloc_create("Load_ABC_parts", NULL); -#endif - // decode constructs like "((AB)2.(CD)2)3.(AB)E2" to "ABABCDCDABABCDCDABABCDCDABEE" - // first compute needed storage... - j=0; - k=0; - for( i=0; p[i] && p[i] != '%'; i++ ) { - if( isupper(p[i]) ) { - j++; - } - if( isdigit(p[i]) ) { - n=abc_getnumber(p+i,&k); - if( k == 0 ) - k = 1; - if( p[i-1] == ')' ) - j *= k; // never mind multiple parens, just take the worst case - else - j += k-1; - i += n-1; - } - } - q = (char *)_mm_calloc(h, j+1, sizeof(char)); // enough storage for the worst case - // now copy bytes from p to *d, taking parens and digits in account - j = 0; - for( i=0; p[i] && p[i] != '%'; i++ ) { - if( isdigit(p[i]) || isupper(p[i]) || p[i] == '(' || p[i] == ')' ) { - if( p[i] == ')' ) { - for( n=j; n > 0 && q[n-1] != '('; n-- ) ; // find open paren in q - // q[n+1] to q[j] contains the substring that must be repeated - if( n > 0 ) { - for( k = n; k 1 ) { - for( m=0; m 1 ) { - q[j] = q[j-1]; - j++; - } - continue; - } - q[j] = p[i]; - j++; - } - } - q[j] = '\0'; - // remove any left over parens - for( i=0; itail->tracktick - pt1; - for( e=tp->head; e && e->tracktick <= pt2; e=e->next ) { - if( e->tracktick >= pt1 ) { - if( e->flg != 1 || e->cmd == cmdsync || e->cmd == cmdchord ) { - if( e != tp->tail ) { - // copy this event at tail - ec = abc_copy_event(h,e); - ec->tracktick += dt; - ec->part = '*'; - tp->tail->next = ec; - tp->tail = ec; - } - } - } - } - abc_add_sync(h, tp, pt2 + dt); // make sure there is progression... -} - -static uint32_t abc_pattracktime(ABCHANDLE *h, uint32_t tracktime) -{ - ABCEVENT *e; - uint32_t dt,et,pt=abcticks(64 * h->speed); - if(!h || !h->track || !h->track->head ) return 0; - dt = 0; - for( e=h->track->head; e && e->tracktick <= tracktime; e=e->next ) { - if( e->flg == 1 && e->cmd == cmdpartbrk ) { - et = e->tracktick + dt; - if( et % pt ) { - et += pt; - et /= pt; - et *= pt; - dt = et - e->tracktick; - } - } - } - return (tracktime + dt); -} - -static int abc_patno(ABCHANDLE *h, uint32_t tracktime) -{ - return modticks(abc_pattracktime(h, tracktime)) / 64 / h->speed; -} - -static void abc_stripoff(ABCHANDLE *h, ABCTRACK *tp, uint32_t tt) -{ - ABCEVENT *e1, *e2; - e2 = NULL; - for( e1 = tp->head; e1 && e1->tracktick <= tt; e1=e1->next ) - e2 = e1; - if( e2 ) { - e1 = e2->next; - tp->tail = e2; - e2->next = NULL; - } - else { - e1 = tp->tail; - tp->head = NULL; - tp->tail = NULL; - } - while( e1 ) { - e2 = e1->next; - _mm_free(h->trackhandle,e1); - e1 = e2; - } -} - -static void abc_keeptiednotes(ABCHANDLE *h, uint32_t fromtime, uint32_t totime) { - ABCTRACK *tp; - ABCEVENT *e,*n,*f; - if( totime <= fromtime ) return; - for( tp=h->track; tp; tp=tp->next ) { - if( tp->vno ) { // if track is in use... - n = NULL; - for( e=tp->head; e && e->tracktick < fromtime; e = e->next ) - if( e->flg != 1 ) n = e; // remember it when it is a note event - if( n && n->tiednote ) { // we've a candidate to tie over the break - while( e && e->tracktick < totime ) e=e->next; // skip to other part - if( e && e->tracktick == totime ) { // if this is on begin row of this part - f = NULL; - while( !f && e && e->tracktick == totime ) { - if( e->flg != 1 ) f = e; - e = e->next; - } - if( f && f->par[note] ) { // pfoeie, we've found a candidate - if( abs(n->par[note] - f->par[note]) < 3 ) { // undo the note on - f->flg = 1; - f->cmd = cmdhide; - f->lpar = 0; - } - } - } - } - } - } -} - -static uint32_t abc_fade_tracks(ABCHANDLE *h, char *abcparts, uint32_t ptt[27]) -{ - ABCTRACK *tp; - ABCEVENT *e0; - char *p; - int vol; - uint32_t pt1, pt2; - uint32_t tt; - tt = h->track->tail->tracktick; - for( tp=h->track->next; tp; tp=tp->next ) { - if( !tp->tail ) abc_add_sync(h, tp, tt); // no empty tracks please... - if( tp->tail->tracktick > tt ) abc_stripoff(h, tp, tt); // should not happen.... - if( tp->tail->tracktick < tt ) abc_add_sync(h, tp, tt); - } - for( tp=h->track; tp; tp=tp->next ) { - vol = 127; - e0 = tp->tail; - if( tp->slidevol != -2 ) { - tp->slidevol = -2; - tp->slidevoltime = e0->tracktick; - } - tp->mute = 0; // unmute track for safety, notes in a muted track already have zero volume... - while( vol > 5 ) { - for( p=abcparts; *p && vol > 5; p++ ) { - pt1 = ptt[*p-'A']; - pt2 = ptt[*p-'A'+1]; - abc_appendpart(h, tp, pt1, pt2); - vol = abc_dynamic_volume(tp, tp->tail->tracktick, 127); - } - } - abc_fade_track(tp,e0); - } - return h->track->tail->tracktick; -} - -static void abc_song_to_parts(ABCHANDLE *h, char **abcparts, BYTE partp[27][2]) -{ - uint32_t starttick; - ABCEVENT *e; - int i, fading, loop, normal, partno, partsegno, partloop, partcoda, parttocoda, partfine, skip, x, y; - int vmask[27],nextp[27]; - uint32_t ptt[27]; - char buf[256]; // must be enough, mod's cannot handle more than 240 patterns - char *pfade; - if( !h || !h->track || !h->track->capostart ) return; - strcpy(buf,"A"); // initialize our temporary array - i = 1; - loop = 1; - partno = 0; - partsegno = 0; - partloop = 0; - partcoda = -1; - parttocoda = -1; - partfine = -1; - starttick = h->track->capostart->tracktick; - ptt[0] = starttick; - vmask[0] = -1; - nextp[0] = 1; - for( e=h->track->capostart; e; e=e->next ) { - if( e->flg == 1 ) { - switch( e->cmd ) { - case cmdpartbrk: - if( e->tracktick > starttick) { - starttick = e->tracktick; // do not make empty parts - if( partno < 26 ) { - partno++; - ptt[partno] = starttick; - } - if( i < 255 ) buf[i++] = partno+'A'; - vmask[partno] = -1; - nextp[partno] = partno+1; - } - break; - case cmdloop: - partloop = partno; - loop = 1; // start counting anew... - break; - case cmdvariant: - vmask[partno] = e->lpar; - break; - case cmdjump: - x = 0; - fading = 0; - normal = 0; - skip = 0; - pfade = &buf[i]; - switch( e->par[jumptype] ) { - case jumpfade: - fading = 1; - case jumpnormal: - normal = 1; - x = partloop; - loop++; - break; - case jumpdsfade: - fading = 1; - case jumpdasegno: - x = partsegno; - break; - case jumpdcfade: - fading = 1; - case jumpdacapo: - x = 0; - break; - default: - x = 0; - break; - } - if( vmask[partno] != -1 ) nextp[partno] = x; - if( partno < 26 ) ptt[partno+1] = e->tracktick; // for handling ties over breaks - while( x <= partno ) { - if( skip == 1 && x == partcoda ) skip = 0; - y = !skip; - if( y ) { - if( !normal ) { - if( x == partfine ) skip = 2; - if( x == parttocoda ) skip = 1; - y = !skip; - } - if( !(vmask[x] & (1<tracktick; - buf[i] = '\0'; // close up pfade with zero byte - starttick = abc_fade_tracks(h, pfade, ptt); - buf[i++] = partno+'A'; - partno++; - ptt[partno] = starttick; - buf[i++] = partno+'A'; // one extra to throw away... - e = h->track->tail; // this is the edge of the world captain... - } - break; - case cmdtocoda: - parttocoda = partno; - break; - case cmdcoda: - partcoda = partno; - break; - case cmdfine: - partfine = partno; - break; - case cmdsegno: - partsegno = partno; - break; - } - } - e->part = partno+'a'; // small caps for generated parts... - } - i--; // strip off last partno - if( partno > 0 ) partno--; - buf[i] = '\0'; - if( i > 1 ) { - for( i=1; buf[i]; i++ ) { - if( buf[i] != buf[i-1] + 1 ) { - x = buf[i-1] - 'A'; - y = buf[i] - 'A'; - abc_keeptiednotes(h, ptt[x+1], ptt[y]); - } - } - } - starttick = h->track->tail->tracktick; - ptt[partno+1] = starttick; - for( i=0; i<=partno; i++ ) { - partp[i][0] = abc_patno(h, ptt[i]); - partp[i][1] = abc_patno(h, ptt[i+1]); - } - // calculate end point of last part - starttick = abc_pattracktime(h, starttick); - if( starttick % abcticks(64 * h->speed) ) - partp[partno][1]++; - abc_set_parts(abcparts, buf); -} - -// ===================================================================================== -static char *abc_fgets(MMFILE *mmfile, char buf[], unsigned int bufsz) -// ===================================================================================== -{ - if( mmfeof(mmfile) ) return NULL; - mmfgets(buf,bufsz,mmfile); - return buf; -} - -// ===================================================================================== -static char *abc_fgetbytes(MMFILE *mmfile, char buf[], unsigned int bufsz) -// ===================================================================================== -{ - unsigned int i; - long pos; - if( mmfeof(mmfile) ) return NULL; - for( i=0; iline, target)) ) { - if( (i=strlen(h->line)) + n - l >= (int)h->len ) { - h->line = (char *)_mm_recalloc(h->allochandle, h->line, h->len<<1, sizeof(char)); - h->len <<= 1; - p=strstr(h->line, target); - } - if( n > l ) { - for( q=&h->line[i]; q>p; q-- ) q[n-l] = q[0]; - for( q=s; *q; q++ ) *p++ = *q; - } - else { - strcpy(p,s); - strcat(p,p+l); - } - } -} - -static void abc_preprocess(ABCHANDLE *h, ABCMACRO *m) -{ - int i, j, k, l, a, b; - if( m->n ) { - k = m->n - m->name; - for( i=0; i<14; i++ ) { - char t[strlen(m->name) + 1]; - strcpy(t, m->name); - t[k] = "CDEFGABcdefgab"[i]; - l = strlen(m->subst); - char s[2 * l + 1]; - char *p = s; - for( j=0; jsubst[j]; - if( a > 'g' && islower(a) ) { - b = a - 'n'; - a = "CDEFGABCDEFGABcdefgabcdefgab"[i+b+7]; - *p++ = a; - if( i+b < 0 ) - *p++ = ','; - else if( i+b > 13 ) - *p++ = '\''; - } - else *p++ = a; - } - *p = '\0'; - abc_substitute(h, t, s); - } - } - else - abc_substitute(h, m->name, m->subst); -} - -static char *abc_gets(ABCHANDLE *h, MMFILE *mmfile) -{ - int i; - ABCMACRO *mp; - if( !h->len ) { - h->len = 64; // initial line size, adequate for most abc's - h->line = (char *)_mm_calloc(h->allochandle, h->len, sizeof(char)); - } - if( abc_fgetbytes(mmfile, h->line, h->len) ) { - while( (i=strlen(h->line)) > (int)(h->len - 3) ) { - // line too short, double it - h->line = (char *)_mm_recalloc(h->allochandle, h->line, h->len<<1, sizeof(char)); - if( h->line[i-1] != '\n' ) - abc_fgetbytes(mmfile, &h->line[i], h->len); - h->len <<= 1; - } - h->line[i-1] = '\0'; // strip off newline - for( mp=h->macro; mp; mp=mp->next ) - abc_preprocess(h,mp); - return h->line; - } - return NULL; -} - -static int abc_parse_decorations(ABCHANDLE *h, ABCTRACK *tp, const char *p) -{ - int vol=0; - if( !strncmp(p,"mp",2) ) vol = 75; - if( !strncmp(p,"mf",2) ) vol = 90; - if( !strncmp(p,"sfz",3) ) vol = 100; - if( *p == 'p' ) { - vol = 60; - while( *p++ == 'p' ) vol -= 15; - if( vol < 1 ) vol = 1; - } - if( *p == 'f' ) { - vol = 105; - while( *p++ == 'f' ) vol += 15; - if( vol > 135 ) vol = 127; // ffff - if( vol > 127 ) vol = 125; // fff - } - if( vol ) { - tp->volume = vol; - if( tp == h->track ) { // copy volume over to all voice tracks - for( ; tp; tp=tp->next ) { - if( tp->vpos == 0 || tp->vpos > DRONEPOS2 ) tp->volume = vol; - } - tp = h->track; - } - } - return tp->volume; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -BOOL ABC_Test(MMSTREAM *mmfile) -#else -BOOL CSoundFile::TestABC(const BYTE *lpStream, DWORD dwMemLength) -#endif -// ===================================================================================== -{ - char id[128]; - // scan file for first K: line (last in header) -#ifdef NEWMIKMOD - _mm_fseek(mmfile,0,SEEK_SET); - while(abc_fgets(mmfile,id,128)) { -#else - MMFILE mmfile; - mmfile.mm = (char *)lpStream; - mmfile.sz = dwMemLength; - mmfseek(&mmfile,0,SEEK_SET); - int ppos = mmfile.pos; - - while(abc_fgets(&mmfile,id,128)) { -#endif - - if (id[0] == 0 && mmfile.pos < ppos + 120) return(0); //probably binary - if (id[0] == 0) continue; // blank line. - - if (!abc_isvalidchar(id[0]) || !abc_isvalidchar(id[1])) { - return(0); // probably not an ABC. - } - if(id[0]=='K' - && id[1]==':' - && (isalpha(id[2]) || isspace(id[2])) ) return 1; - } - return 0; -} - -// ===================================================================================== -static ABCHANDLE *ABC_Init(void) -{ - ABCHANDLE *retval; - char *p; - char buf[10]; -#ifdef NEWMIKMOD - MM_ALLOC *allochandle; - - allochandle = _mmalloc_create("Load_ABC", NULL); - retval = (ABCHANDLE *)_mm_calloc(allochandle, 1,sizeof(ABCHANDLE)); - if( !retval ) return NULL; - retval->allochandle = allochandle; - allochandle = _mmalloc_create("Load_ABC_macros", NULL); - retval->macrohandle = allochandle; - allochandle = _mmalloc_create("Load_ABC_tracks", NULL); - retval->trackhandle = allochandle; -#else - retval = (ABCHANDLE *)calloc(1,sizeof(ABCHANDLE)); - if( !retval ) return NULL; -#endif - retval->track = NULL; - retval->macro = NULL; - retval->umacro = NULL; - retval->beatstring = NULL; - retval->pickrandom = 0; - retval->len = 0; - retval->line = NULL; - strcpy(retval->gchord, ""); - retval->barticks = 0; - p = getenv(ABC_ENV_NORANDOMPICK); - if( p ) { - if( isdigit(*p) ) - retval->pickrandom = atoi(p); - if( *p == '-' ) { -#ifdef NEWMIKMOD - retval->pickrandom = atoi(p+1); - sprintf(buf,"-%ld",retval->pickrandom+1); -#else - retval->pickrandom = atoi(p+1)-1; // xmms preloads the file - sprintf(buf,"-%ld",retval->pickrandom+2); -#endif - setenv(ABC_ENV_NORANDOMPICK, buf, 1); - } - } - else { - srandom((uint32_t)time(0)); // initialize random generator with seed - retval->pickrandom = 1+(int)(10000.0*random()/(RAND_MAX+1.0)); - // can handle pickin' from songbooks with 10.000 songs -#ifdef NEWMIKMOD - sprintf(buf,"-%ld",retval->pickrandom+1); // next in sequence -#else - sprintf(buf,"-%ld",retval->pickrandom); // xmms preloads the file -#endif - setenv(ABC_ENV_NORANDOMPICK, buf, 1); - } - return retval; -} - -#ifndef NEWMIKMOD -static void ABC_CleanupTrack(ABCTRACK *tp) -{ - ABCEVENT *ep, *en; - if( tp ) { - for( ep=tp->head; ep; ep = en ) { - en=ep->next; - free(ep); - } - tp->head = NULL; - } -} - -static void ABC_CleanupMacro(ABCMACRO *m) -{ - if( m->name ) - free(m->name); - if( m->subst ) - free(m->subst); - free(m); -} -#endif - -// ===================================================================================== -static void ABC_CleanupTracks(ABCHANDLE *handle) -// ===================================================================================== -{ -#ifdef NEWMIKMOD - if(handle && handle->trackhandle) { - _mmalloc_close(handle->trackhandle); - handle->trackhandle = 0; - } -#else - ABCTRACK *tp, *tn; - if(handle) { - for( tp=handle->track; tp; tp = tn ) { - tn=tp->next; - ABC_CleanupTrack(tp); - } - handle->track = NULL; - } -#endif -} - -// ===================================================================================== -static void ABC_CleanupMacros(ABCHANDLE *handle) -// ===================================================================================== -{ -#ifdef NEWMIKMOD - if(handle && handle->macrohandle) { - _mmalloc_close(handle->macrohandle); - handle->macrohandle = 0; - } -#else - ABCMACRO *mp, *mn; - if(handle) { - for( mp=handle->macro; mp; mp = mn ) { - mn=mp->next; - ABC_CleanupMacro(mp); - } - for( mp=handle->umacro; mp; mp = mn ) { - mn=mp->next; - ABC_CleanupMacro(mp); - } - handle->macro = NULL; - handle->umacro = NULL; - } -#endif -} - -// ===================================================================================== -static void ABC_Cleanup(ABCHANDLE *handle) -// ===================================================================================== -{ -#ifdef NEWMIKMOD - if(handle && handle->allochandle) { -#else - if(handle) { -#endif - ABC_CleanupMacros(handle); - ABC_CleanupTracks(handle); -#ifdef NEWMIKMOD - _mmalloc_close(handle->allochandle); - handle->allochandle = 0; - handle->len = 0; -#else - if( handle->line ) - free(handle->line); - if( handle->beatstring ) - free(handle->beatstring); - free(handle); -#endif - } -} - -static int abc_is_global_event(ABCEVENT *e) -{ - return e->flg == 1 && (e->cmd == cmdtempo || e->cmd == cmdpartbrk); -} - -static ABCEVENT *abc_next_global(ABCEVENT *e) -{ - for( ; e && !abc_is_global_event(e); e=e->next ) ; - return e; -} - -static ABCEVENT *abc_next_note(ABCEVENT *e) -{ - for( ; e && e->flg == 1; e=e->next ) ; - return e; -} - -// ============================================================================= -#ifdef NEWMIKMOD -static void ABC_ReadPatterns(UNIMOD *of, ABCHANDLE *h, int numpat) -// ============================================================================= -{ - int pat,row,i,ch,trillbits; - BYTE n,ins,vol; - ABCTRACK *t; - ABCEVENT *e, *en, *ef, *el; - uint32_t tt1, tt2; - UNITRK_EFFECT eff; - - // initialize start points of event list in tracks - for( t = h->track; t; t = t->next ) t->capostart = t->head; - trillbits = 0; // trill effect admininstration: one bit per channel, max 32 channnels - for( pat = 0; pat < numpat; pat++ ) { - utrk_reset(of->ut); - for( row = 0; row < 64; row++ ) { - tt1 = abcticks((pat * 64 + row ) * h->speed); - tt2 = tt1 + abcticks(h->speed); - ch = 0; - for( e=abc_next_global(h->track->capostart); e && e->tracktick < tt2; e=abc_next_global(e->next) ) { - if( e && e->tracktick >= tt1 ) { // we have a tempo event in this row - switch( e->cmd ) { - case cmdtempo: - eff.effect = UNI_GLOB_TEMPO; - eff.param.u = e->lpar; - eff.framedly = UFD_RUNONCE; - utrk_write_global(of->ut, &eff, PTMEM_TEMPO); - break; - case cmdpartbrk: - eff.effect = UNI_GLOB_PATBREAK; - eff.param.u = 0; - eff.framedly = UFD_RUNONCE; - utrk_write_global(of->ut, &eff, UNIMEM_NONE); - break; - } - } - } - for( t = h->track; t; t = t->next ) { - for( e=abc_next_note(t->capostart); e && e->tracktick < tt1; e=abc_next_note(e->next) ) - t->capostart = e; - i = 0; - ef = NULL; - en = e; - el = e; - for( ; e && e->tracktick < tt2; e=abc_next_note(e->next) ) { // we have a note event in this row - t->capostart = e; - i++; - if( e->par[volume] ) { - if( !ef ) ef = e; - el = e; - } - } - if( i ) { - trillbits &= ~(1<ut, ch); - if( i == 1 || ef == el || !ef ) { // only one event in this row - if( ef ) e = ef; - else e = en; - el = t->capostart; - i = e->par[note] + ((e->par[octave])*12); - if( t->chan == 10 ) { - n = pat_gm_drumnote(i) + 23; - ins = pat_gmtosmp(pat_gm_drumnr(i)); - } - else { - n = pat_modnote(i); - ins = e->par[smpno]; - } - eff.framedly = modticks(e->tracktick - tt1); - vol = e->par[volume]; - if( e->par[effect] == accent ) { - vol += vol / 10; - if( vol > 127 ) vol = 127; - } - if (vol <= 0) {} - else if( el->par[volume] == 0 ) { - eff.framedly = modticks(el->tracktick - tt1); - eff.param.u = 0; - eff.param.byte_a = n; - eff.param.byte_b = ins; - eff.effect = UNI_NOTEKILL; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - else { - switch( e->par[effect] ) { - case trill: - eff.effect = UNI_VIBRATO_DEPTH; - eff.param.u = 12; // depth 1.5 - utrk_write_local(of->ut, &eff, PTMEM_VIBRATO_DEPTH); - eff.effect = UNI_VIBRATO_SPEED; - eff.param.u = 48; // speed 12 - utrk_write_local(of->ut, &eff, PTMEM_VIBRATO_SPEED); - trillbits |= (1<speed/2)|UFD_RUNONCE; - eff.param.s = 2; - utrk_write_local(of->ut, &eff, (e->par[effoper])? PTMEM_PITCHSLIDEUP: PTMEM_PITCHSLIDEDN); - break; - default: - break; - } - if( eff.framedly ) { - eff.param.u = 0; - eff.param.byte_a = n; - eff.param.byte_b = ins; - eff.effect = UNI_NOTEDELAY; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - } - utrk_write_inst(of->ut, ins); - utrk_write_note(of->ut, n); // <- normal note - pt_write_effect(of->ut, 0xc, vol); - } - else { - // two notes in one row, use FINEPITCHSLIDE runonce effect - // start first note on first tick and framedly runonce on seconds note tick - // use volume and instrument of last note - if( t->chan == 10 ) { - i = el->par[note] + ((el->par[octave])*12); - n = pat_gm_drumnote(i) + 23; - ins = pat_gmtosmp(pat_gm_drumnr(i)); - i = n; // cannot change instrument here.. - } - else { - i = ef->par[note] + ((ef->par[octave])*12); - n = pat_modnote(i); - ins = el->par[smpno]; - i = pat_modnote(el->par[note] + ((el->par[octave])*12)); - } - vol = el->par[volume]; - eff.effect = UNI_PITCHSLIDE; - eff.framedly = modticks(el->tracktick - tt1)|UFD_RUNONCE; - eff.param.s = ((i > n)?i-n:n-i); - utrk_write_inst(of->ut, ins); - utrk_write_note(of->ut, n); // <- normal note - pt_write_effect(of->ut, 0xc, vol); - utrk_write_local(of->ut, &eff, (i > n)? PTMEM_PITCHSLIDEUP: PTMEM_PITCHSLIDEDN); - } - } - else { // no new notes, keep on trilling... - if( trillbits & (1<ut, ch); - eff.effect = UNI_VIBRATO_DEPTH; - eff.param.u = 12; // depth 1.5 - utrk_write_local(of->ut, &eff, PTMEM_VIBRATO_DEPTH); - eff.effect = UNI_VIBRATO_SPEED; - eff.param.u = 60; // speed 15 - utrk_write_local(of->ut, &eff, PTMEM_VIBRATO_SPEED); - } - } - ch++; - } - utrk_newline(of->ut); - } - if(!utrk_dup_pattern(of->ut,of)) return; - } -} - -#else - -static int ABC_ReadPatterns(MODCOMMAND *pattern[], WORD psize[], ABCHANDLE *h, int numpat, int channels) -// ===================================================================================== -{ - int pat,row,i,ch,trillbits; - BYTE n,ins,vol; - ABCTRACK *t; - ABCEVENT *e, *en, *ef, *el; - uint32_t tt1, tt2; - MODCOMMAND *m; - int patbrk, tempo; - if( numpat > MAX_PATTERNS ) numpat = MAX_PATTERNS; - - // initialize start points of event list in tracks - for( t = h->track; t; t = t->next ) t->capostart = t->head; - trillbits = 0; // trill effect admininstration: one bit per channel, max 32 channnels - for( pat = 0; pat < numpat; pat++ ) { - pattern[pat] = CSoundFile::AllocatePattern(64, channels); - if( !pattern[pat] ) return 0; - psize[pat] = 64; - for( row = 0; row < 64; row++ ) { - tt1 = abcticks((pat * 64 + row ) * h->speed); - tt2 = tt1 + abcticks(h->speed); - ch = 0; - tempo = 0; - patbrk = 0; - for( e=abc_next_global(h->track->capostart); e && e->tracktick < tt2; e=abc_next_global(e->next) ) { - if( e && e->tracktick >= tt1 ) { // we have a tempo event in this row - switch( e->cmd ) { - case cmdtempo: - tempo = e->lpar; - break; - case cmdpartbrk: - patbrk = 1; - break; - } - } - } - for( t = h->track; t; t = t->next ) { - for( e=abc_next_note(t->capostart); e && e->tracktick < tt1; e=abc_next_note(e->next) ) ; - i = 0; - ef = NULL; - en = e; - el = e; - for( ; e && e->tracktick < tt2; e=abc_next_note(e->next) ) { // we have a note event in this row - t->capostart = e; - i++; - if( e->par[volume] ) { - if( !ef ) ef = e; - el = e; - } - } - m = &pattern[pat][row * channels + ch]; - m->param = 0; - m->command = CMD_NONE; - if( i ) { - trillbits &= ~(1<capostart; - i = e->par[note] + ((e->par[octave])*12); - if( t->chan == 10 ) { - n = pat_gm_drumnote(i) + 23; - ins = pat_gmtosmp(pat_gm_drumnr(i)); - } - else { - n = pat_modnote(i); - ins = e->par[smpno]; - } - vol = e->par[volume]/2; - if( e->par[volume] > 0 ) { - if( e->par[effect] == accent ) vol += vol / 20; - if( vol > 64 ) vol = 64; - if( el->par[volume] == 0 ) { // note cut - m->param = el->tracktick - tt1; - m->command = CMD_S3MCMDEX; - m->param |= 0xC0; - } - else { - switch( e->par[effect] ) { - case trill: - m->command = CMD_VIBRATO; - m->param = 0xC2; // speed 12 depth 2 - trillbits |= (1<command = CMD_XFINEPORTAUPDOWN; - m->param |= (e->par[effoper])? 0x12: 0x22; - break; - default: - m->param = modticks(e->tracktick - tt1); - if( m->param ) { // note delay - m->command = CMD_S3MCMDEX; - m->param |= 0xD0; - } - break; - } - } - } - m->instr = ins; - m->note = n; // <- normal note - m->volcmd = VOLCMD_VOLUME; - m->vol = vol; - } - else { - // two notes in one row, use FINEPITCHSLIDE runonce effect - // start first note on first tick and framedly runonce on seconds note tick - // use volume and instrument of last note - if( t->chan == 10 ) { - i = el->par[note] + ((el->par[octave])*12); - n = pat_gm_drumnote(i) + 23; - ins = pat_gmtosmp(pat_gm_drumnr(i)); - i = n; // cannot change instrument here.. - } - else { - i = ef->par[note] + ((ef->par[octave])*12); - n = pat_modnote(i); - ins = el->par[smpno]; - i = pat_modnote(el->par[note] + ((el->par[octave])*12)); - } - vol = el->par[volume]/2; - if( vol > 64 ) vol = 64; - m->instr = ins; - m->note = n; // <- normal note - m->volcmd = VOLCMD_VOLUME; - m->vol = vol; - m->param = ((i > n)?i-n:n-i); - if( m->param < 16 ) { - if( m->param ) { - m->command = CMD_XFINEPORTAUPDOWN; - m->param |= (i > n)? 0x10: 0x20; - } - else { // retrigger same note... - m->command = CMD_RETRIG; - m->param = modticks(el->tracktick - tt1); - } - } - else - m->command = (i > n)? CMD_PORTAMENTOUP: CMD_PORTAMENTODOWN; - } - } - else { // no new notes, keep on trilling... - if( trillbits & (1<command = CMD_VIBRATO; - m->param = 0; // inherited from first effect - m->instr = 0; - m->note = 0; - m->volcmd = 0; - m->vol = 0; - } - } - if( m->param == 0 && m->command == CMD_NONE ) { - if( tempo ) { - m->command = CMD_TEMPO; - m->param = tempo; - tempo = 0; - } - else { - if( patbrk ) { - m->command = CMD_PATTERNBREAK; - patbrk = 0; - } - } - } - ch++; - } - if( tempo || patbrk ) return 1; - } - } - return 0; -} - -#endif - -static int ABC_Key(const char *p) -{ - int i,j; - char c[8] = {0}; - const char *q; - while( isspace(*p) ) p++; - i = 0; - q = p; - for( i=0; i<8 && *p && *p != ']'; p++ ) { - if( isspace(*p) ) { - while( isspace(*p) ) p++; - if( strncasecmp(p, "min", 3) && strncasecmp(p, "maj", 3) ) - break; - } - c[i] = *p; - i++; - } - c[i] = '\0'; - if( !strcmp(c,"Hp") || !strcmp(c,"HP") ) // highland pipes - strcpy(c,"Bm"); // two sharps at c and f - if( !strcasecmp(c+1, "minor") ) i=2; - if( !strcasecmp(c+2, "minor") ) i=3; - if( !strcasecmp(c+1, "major") ) i=1; - if( !strcasecmp(c+2, "major") ) i=2; - if( !strcasecmp(c+1, "min") ) i=2; - if( !strcasecmp(c+2, "min") ) i=3; - if( !strcasecmp(c+1, "maj") ) i=1; - if( !strcasecmp(c+2, "maj") ) i=2; - for( ; i<6; i++ ) - c[i] = ' '; - c[i] = '\0'; - for( i=0; keySigs[i]; i++ ) { - for( j=10; j<46; j+=6 ) - if( !strncasecmp(keySigs[i]+j, c, 6) ) - return i; - } - abc_message("Failure: Unrecognised K: field %s", q); - return 7; -} - -static char *abc_skip_word(char *p) -{ - while( isspace(*p) ) p++; - while( *p && !isspace(*p) && *p != ']') p++; - while( isspace(*p) ) p++; - return p; -} - -static uint32_t abc_tracktime(ABCTRACK *tp) -{ - uint32_t tracktime; - if( tp->tail ) tracktime = tp->tail->tracktick; - else tracktime = 0; - if( tracktime < global_songstart ) - tracktime = global_songstart; - return tracktime; -} - -static void abc_addchordname(const char *s, int len, const int *notes) -// adds chord name and note set to list of known chords -{ - int i, j; - if(strlen(s) > 7) { - abc_message("Failure: Chord name cannot exceed 7 characters, %s", s); - return; - } - if(len > 6) { - abc_message("Failure: Named chord cannot have more than 6 notes, %s", s); - return; - } - for( i=0; i < chordsnamed; i++ ) { - if(strcmp(s, chordname[i]) == 0) { - /* change chord */ - chordlen[i] = len; - for(j = 0; j < len; j++) chordnotes[i][j] = notes[j]; - return; - } - } - if(chordsnamed > MAXCHORDNAMES - 1) - abc_message("Failure: Too many Guitar Chord Names used, %s", s); - else { - strcpy(chordname[chordsnamed], s); - chordlen[chordsnamed] = len; - for(j = 0; j < len; j++) chordnotes[chordsnamed][j] = notes[j]; - chordsnamed++; - } -} - -static void abc_setup_chordnames() -// set up named guitar chords -{ - static const int list_Maj[3] = { 0, 4, 7 }; - static const int list_m[3] = { 0, 3, 7 }; - static const int list_7[4] = { 0, 4, 7, 10 }; - static const int list_m7[4] = { 0, 3, 7, 10 }; - static const int list_maj7[4] = { 0, 4, 7, 11 }; - static const int list_M7[4] = { 0, 4, 7, 11 }; - static const int list_6[4] = { 0, 4, 7, 9 }; - static const int list_m6[4] = { 0, 3, 7, 9 }; - static const int list_aug[3] = { 0, 4, 8 }; - static const int list_plus[3] = { 0, 4, 8 }; - static const int list_aug7[4] = { 0, 4, 8, 10 }; - static const int list_dim[3] = { 0, 3, 6 }; - static const int list_dim7[4] = { 0, 3, 6, 9 }; - static const int list_9[5] = { 0, 4, 7, 10, 2 }; - static const int list_m9[5] = { 0, 3, 7, 10, 2 }; - static const int list_maj9[5] = { 0, 4, 7, 11, 2 }; - static const int list_M9[5] = { 0, 4, 7, 11, 2 }; - static const int list_11[6] = { 0, 4, 7, 10, 2, 5 }; - static const int list_dim9[5] = { 0, 4, 7, 10, 13 }; - static const int list_sus[3] = { 0, 5, 7 }; - static const int list_sus9[3] = { 0, 2, 7 }; - static const int list_7sus[4] = { 0, 5, 7, 10 }; - static const int list_7sus4[4] = { 0, 5, 7, 10 }; - static const int list_7sus9[4] = { 0, 2, 7, 10 }; - static const int list_9sus4[5] = { 0, 5, 10, 14, 19 }; - static const int list_5[2] = { 0, 7 }; - static const int list_13[6] = { 0, 4, 7, 10, 16, 21 }; - - chordsnamed = 0; - abc_addchordname("", 3, list_Maj); - abc_addchordname("m", 3, list_m); - abc_addchordname("7", 4, list_7); - abc_addchordname("m7", 4, list_m7); - abc_addchordname("maj7", 4, list_maj7); - abc_addchordname("M7", 4, list_M7); - abc_addchordname("6", 4, list_6); - abc_addchordname("m6", 4, list_m6); - abc_addchordname("aug", 3, list_aug); - abc_addchordname("+", 3, list_plus); - abc_addchordname("aug7", 4, list_aug7); - abc_addchordname("7+", 4, list_aug7); - abc_addchordname("dim", 3, list_dim); - abc_addchordname("dim7", 4, list_dim7); - abc_addchordname("9", 5, list_9); - abc_addchordname("m9", 5, list_m9); - abc_addchordname("maj9", 5, list_maj9); - abc_addchordname("M9", 5, list_M9); - abc_addchordname("11", 6, list_11); - abc_addchordname("dim9", 5, list_dim9); - abc_addchordname("sus", 3, list_sus); - abc_addchordname("sus9", 3, list_sus9); - abc_addchordname("7sus", 4, list_7sus); - abc_addchordname("7sus4", 4, list_7sus4); - abc_addchordname("7sus9", 4, list_7sus9); - abc_addchordname("9sus4", 5, list_9sus4); - abc_addchordname("5", 2, list_5); - abc_addchordname("13", 6, list_13); -} - -static int abc_MIDI_getnumber(const char *p) -{ - int n; - while( isspace(*p) ) p++; - abc_getnumber(p, &n); - if( n < 0 ) n = 0; - if( n > 127 ) n = 127; - return n; -} - -static int abc_MIDI_getprog(const char *p) -{ - int n; - while( isspace(*p) ) p++; - abc_getnumber(p, &n); - if( n < 1 ) n = 1; - if( n > 128 ) n = 128; - return n; -} - -// MIDI drone -static void abc_MIDI_drone(const char *p, int *gm, int *ptch, int *vol) -{ - int i; - while( isspace(*p) ) p++; - p += abc_getnumber(p, &i); - i++; // adjust for 1..128 - if( i>0 && i < 129 ) - *gm = i; - else - *gm = 71; // bassoon - while( isspace(*p) ) p++; - p += abc_getnumber(p, &i); - if( i>0 && i < 127 ) - ptch[0] = i; - else - ptch[0] = 45; - while( isspace(*p) ) p++; - p += abc_getnumber(p, &i); - if( i>0 && i < 127 ) - ptch[1] = i; - else - ptch[1] = 33; - while( isspace(*p) ) p++; - p += abc_getnumber(p, &i); - if( i>0 && i < 127 ) - vol[0] = i; - else - vol[0] = 80; - while( isspace(*p) ) p++; - p += abc_getnumber(p, &i); - if( i>0 && i < 127 ) - vol[1] = i; - else - vol[1] = 80; -} - -static void abc_chan_to_tracks(ABCHANDLE *h, int tno, int ch) -{ - ABCTRACK *tp; - if( tno>0 && tno<33 ) { - for( tp=h->track; tp; tp=tp->next ) { - if( tp->vno == tno && (tp->vpos < GCHORDBPOS || tp->vpos > DRONEPOS2) ) - tp->chan = ch; - } - } -} - -// %%MIDI channel int1 -// channel numbers are 1-16 -static void abc_MIDI_channel(const char *p, ABCTRACK *tp, ABCHANDLE *h) -{ - int i1, i2; - i1 = tp? tp->vno: 1; - for( ; *p && isspace(*p); p++ ) ; - if( isdigit(*p) ) { - p += abc_getnumber(p, &i2); - if( i2 >= 1 && i2 <= 16 ) - abc_chan_to_tracks(h, i1, i2); // we start at 1 - } -} - -static void abc_instr_to_tracks(ABCHANDLE *h, int tno, int gm) -{ - ABCTRACK *tp; - if( tno>0 && tno<33 && gm>0 && gm<129 ) { - for( tp=h->track; tp; tp=tp->next ) { - if( tp->vno == tno && (tp->vpos < GCHORDBPOS || tp->vpos > DRONEPOS2) ) - tp->instr = gm; - } - } -} - -// %%MIDI program [int1] -// instrument numbers are 0-127 -static void abc_MIDI_program(const char *p, ABCTRACK *tp, ABCHANDLE *h) -{ - int i1, i2; - i1 = tp? tp->vno: 1; - for( ; *p && isspace(*p); p++ ) ; - if( isdigit(*p) ) { - p += abc_getnumber(p, &i2); - for( ; *p && isspace(*p); p++ ) ; - if( isdigit(*p) ) { - i1 = i2; - p += abc_getnumber(p, &i2); - } - abc_instr_to_tracks(h, i1, i2 + 1); // we start at 1 - } -} - -static void abc_mute_voice(ABCHANDLE *h, ABCTRACK *tp, int m) -{ - ABCTRACK *t; - for( t=h->track; t; t=t->next ) { - if( t->vno == tp->vno ) t->mute = m; - } -} - -// %%MIDI voice [] [instrument= [bank=]] [mute] -// instrument numbers are 1-128 -static void abc_MIDI_voice(const char *p, ABCTRACK *tp, ABCHANDLE *h) -{ - int i1, i2; - for( ; *p && isspace(*p); p++ ) ; - if( strncmp(p,"instrument=",11) && strncmp(p,"mute",4) ) { - tp = abc_locate_track(h, p, 0); - for( ; *p && !isspace(*p); p++ ) ; - for( ; *p && isspace(*p); p++ ) ; - } - i1 = tp? tp->vno: 1; - i2 = 0; - if( !strncmp(p,"instrument=",11) && isdigit(p[11]) ) { - p += 11; - p += abc_getnumber(p, &i2); - for( ; *p && isspace(*p); p++ ) ; - if( !strncmp(p,"bank=",5) && isdigit(p[5]) ) { - for( ; *p && !isspace(*p); p++ ) ; - for( ; *p && isspace(*p); p++ ) ; - } - } - if( tp ) abc_mute_voice(h,tp,0); - if( !strncmp(p,"mute",4) && (p[4]=='\0' || p[4]=='%' || isspace(p[4])) ) { - if( tp ) abc_mute_voice(h,tp,1); - } - abc_instr_to_tracks(h, i1, i2); // starts already at 1 (draft 4.0) -} - -// %%MIDI chordname ... -static void abc_MIDI_chordname(const char *p) -{ - char name[20]; - int i, notes[6]; - - for( ; *p && isspace(*p); p++ ) ; - i = 0; - while ((i < 19) && (*p != ' ') && (*p != '\0')) { - name[i] = *p; - p = p + 1; - i = i + 1; - } - name[i] = '\0'; - if(*p != ' ') { - abc_message("Failure: Bad format for chordname command, %s", p); - } - else { - i = 0; - while ((i <= 6) && isspace(*p)) { - for( ; *p && isspace(*p); p++ ) ; - p += abc_getnumber(p, ¬es[i]); - i = i + 1; - } - abc_addchordname(name, i, notes); - } -} - -// %%MIDI drum ... ... -// instrument numbers are 0-127 -static int abc_MIDI_drum(const char *p, ABCHANDLE *h) -{ - char *q; - int i,n,m; - while( isspace(*p) ) p++; - if( !strncmp(p,"on",2) && (isspace(p[2]) || p[2] == '\0') ) return 2; - if( !strncmp(p,"off",3) && (isspace(p[3]) || p[3] == '\0') ) return 1; - n = 0; - for( q = h->drum; *p && !isspace(*p); p++ ) { - if( !strchr("dz0123456789",*p) ) break; - *q++ = *p; - if( !isdigit(*p) ) { - if( !isdigit(p[1]) ) *q++ = '1'; - n++; // count the silences too.... - } - } - *q = '\0'; - q = h->drumins; - for( i = 0; idrum[i*2] == 'd' ) { - while( isspace(*p) ) p++; - if( !isdigit(*p) ) { - m = 0; - while( !isspace(*p) ) p++; - } - else - p += abc_getnumber(p,&m); - q[i] = m + 1; // we start at 1 - } - else q[i] = 0; - } - q = h->drumvol; - for( i = 0; idrum[i*2] == 'd' ) { - while( isspace(*p) ) p++; - if( !isdigit(*p) ) { - m = 0; - while( !isspace(*p) ) p++; - } - else - p += abc_getnumber(p,&m); - q[i] = m; - } - else q[i] = 0; - } - return 0; -} - -// %%MIDI gchord -static int abc_MIDI_gchord(const char *p, ABCHANDLE *h) -{ - char *q; - while( isspace(*p) ) p++; - if( !strncmp(p,"on",2) && (isspace(p[2]) || p[2] == '\0') ) return 2; - if( !strncmp(p,"off",3) && (isspace(p[3]) || p[3] == '\0') ) return 1; - for( q = h->gchord; *p && !isspace(*p); p++ ) { - if( !strchr("fbcz0123456789ghijGHIJ",*p) ) break; - *q++ = *p; - if( !isdigit(*p) && !isdigit(p[1]) ) *q++ = '1'; - } - *q = '\0'; - return 0; -} - -static void abc_metric_gchord(ABCHANDLE *h, int mlen, int mdiv) -{ - switch( 16 * mlen + mdiv ) { - case 0x24: - case 0x44: - case 0x22: - abc_MIDI_gchord("fzczfzcz", h); - break; - case 0x64: - case 0x32: - abc_MIDI_gchord("fzczczfzczcz", h); - break; - case 0x34: - case 0x38: - abc_MIDI_gchord("fzczcz", h); - break; - case 0x68: - abc_MIDI_gchord("fzcfzc", h); - break; - case 0x98: - abc_MIDI_gchord("fzcfzcfzc", h); - break; - case 0xc8: - abc_MIDI_gchord("fzcfzcfzcfzc", h); - break; - default: - if( mlen % 3 == 0 ) - abc_MIDI_gchord("fzcfzcfzcfzcfzcfzcfzcfzcfzc", h); - else - abc_MIDI_gchord("fzczfzczfzczfzczfzczfzczfzcz", h); - if( mdiv == 8 ) h->gchord[mlen*2] = '\0'; - else h->gchord[mlen*4] = '\0'; - break; - } -} - -static void abc_MIDI_legato(const char *p, ABCTRACK *tp) -{ - for( ; *p && isspace(*p); p++ ) ; - if( !strncmp(p,"off",3) ) tp->legato = 0; - else tp->legato = 1; -} - -static void abc_M_field(const char *p, int *mlen, int *mdiv) -{ - if( !strncmp(p,"none",4) ) { - *mlen = 1; - *mdiv = 1; - return; - } - if( !strncmp(p,"C|",2) ) { - *mlen = 2; - *mdiv = 2; - return; - } - if( *p == 'C' ) { - *mlen = 4; - *mdiv = 4; - return; - } - p += abc_getexpr(p,mlen); - sscanf(p," / %d", mdiv); -} - -static int abc_drum_steps(const char *dch) -{ - const char *p; - int i=0; - for( p=dch; *p; p++ ) { - if( isdigit(*p) ) i += *p - '0'; - } - return i; -} - -static void abc_add_drum(ABCHANDLE *h, uint32_t tracktime, uint32_t bartime) -{ - ABCEVENT *e; - ABCTRACK *tp; - uint32_t etime, ctime , rtime, stime; - int i, g, steps, gnote, gsteps, nnum; - steps = abc_drum_steps(h->drum); - ctime = h->barticks; - // look up the last event in tpr drumtrack - tp = abc_locate_track(h, h->tpr->v, DRUMPOS); - e = tp->tail; - etime = e? e->tracktick: bartime; - if( etime > tracktime ) return; - if( etime < bartime ) rtime = h->barticks - ((bartime - etime) % h->barticks); - else rtime = (etime - bartime) % h->barticks; - stime = ctime*steps; - rtime *= steps; - rtime += stime; - gsteps = strlen(h->drum)/2; - g = 0; - while( rtime > stime ) { - rtime -= ctime*(h->drum[g*2+1] - '0'); - if( ++g == gsteps ) g = 0; - } - stime = (tracktime - etime) * steps; - rtime = 0; - while( rtime < stime ) { - gnote = h->drum[g*2]; - i = h->drum[g*2+1] - '0'; - if(gnote=='d') { - tp->instr = pat_gm_drumnr(h->drumins[g]-1); - nnum = pat_gm_drumnote(h->drumins[g]); - abc_add_drumnote(h, tp, etime + rtime/steps, nnum, h->drumvol[g]); - abc_add_noteoff(h,tp,etime + ( rtime + ctime * i )/steps); - } - if( ++g == gsteps ) g = 0; - rtime += ctime * i; - } -} - -static int abc_gchord_steps(const char *gch) -{ - const char *p; - int i=0; - for( p=gch; *p; p++ ) - if( isdigit(*p) ) i += *p - '0'; - return i; -} - -static void abc_add_gchord(ABCHANDLE *h, uint32_t tracktime, uint32_t bartime) -{ - ABCEVENT *e, *c; - ABCTRACK *tp; - uint32_t etime, ctime , rtime, stime; - int i, g, steps, gnote, gcnum, gsteps, nnum, glen; - // look up the last chord event in tpc - c = 0; - for( e = h->tpc->head; e; e = e->next ) - if( e->flg == 1 && e->cmd == cmdchord ) - c = e; - if( !c ) return; - gcnum = c->par[chordnum]; - steps = abc_gchord_steps(h->gchord); - ctime = h->barticks; - etime = 0; - for( i = GCHORDBPOS; i < DRUMPOS; i++ ) { - tp = abc_locate_track(h, h->tpc->v, i); - e = tp->tail; - if( !e ) e = c; - stime = e->tracktick; - if( stime > etime ) etime = stime; - } - if( etime > tracktime ) return; - if( etime < bartime ) rtime = h->barticks - ((bartime - etime) % h->barticks); - else rtime = (etime - bartime) % h->barticks; - stime = ctime * steps; - rtime *= steps; - rtime += stime; - gsteps = strlen(h->gchord); - g = 0; - while( rtime > stime ) { - glen = h->gchord[2*g+1] - '0'; - rtime -= ctime * glen; - if( ++g == gsteps ) g = 0; - } - stime = (tracktime - etime) * steps; - rtime = 0; - while( rtime < stime ) { - gnote = h->gchord[2*g]; - glen = h->gchord[2*g+1] - '0'; - if( ++g == gsteps ) g = 0; - nnum = 0; - switch(gnote) { - case 'b': - tp = abc_locate_track(h, h->tpc->v, GCHORDFPOS); - tp->instr = h->abcbassprog; - nnum = c->par[chordnote]+chordnotes[gcnum][0]+24; - abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcbassvol); - abc_add_noteoff(h,tp,etime + ( rtime + ctime * glen )/steps); - case 'c': - for( i = 1; i < chordlen[gcnum]; i++ ) { - tp = abc_locate_track(h, h->tpc->v, i+GCHORDFPOS); - tp->instr = h->abcchordprog; - nnum = c->par[chordnote]+chordnotes[gcnum][i]+24; - abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcchordvol); - abc_add_noteoff(h,tp,etime + ( rtime + ctime * glen )/steps); - } - rtime += ctime * glen; - break; - case 'f': - tp = abc_locate_track(h, h->tpc->v, GCHORDFPOS); - tp->instr = h->abcbassprog; - nnum = c->par[chordbase]+12; - abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcbassvol); - rtime += ctime * glen; - abc_add_noteoff(h,tp,etime + rtime/steps); - break; - case 'g': - case 'h': - case 'i': - case 'j': - case 'G': - case 'H': - case 'I': - case 'J': - i = toupper(gnote) - 'G'; - nnum = 0; - if( i < chordlen[gcnum] ) { - tp = abc_locate_track(h, h->tpc->v, GCHORDFPOS+i+1); - tp->instr = h->abcchordprog; - nnum = c->par[chordnote]+chordnotes[gcnum][i]+24; - if( isupper(gnote) ) nnum -= 12; - abc_add_chordnote(h, tp, etime + rtime/steps, nnum, h->abcchordvol); - } - rtime += ctime * glen; - if( nnum ) abc_add_noteoff(h,tp,etime + rtime/steps); - break; - case 'z': - rtime += ctime * glen; - break; - } - } -} - -// %%MIDI beat a b c n -// -// controls the way note velocities are selected. The first note in a bar has -// velocity a. Other "strong" notes have velocity b and all the rest have velocity -// c. a, b and c must be in the range 0-128. The parameter n determines which -// notes are "strong". If the time signature is x/y, then each note is given -// a position number k = 0, 1, 2 .. x-1 within each bar. Note that the units for -// n are not the unit note length. If k is a multiple of n, then the note is -// "strong". The volume specifiers !ppp! to !fff! are equivalent to the -// following : -// -// !ppp! = %%MIDI beat 30 20 10 1 -// !pp! = %%MIDI beat 45 35 20 1 -// !p! = %%MIDI beat 60 50 35 1 -// !mp! = %%MIDI beat 75 65 50 1 -// !mf! = %%MIDI beat 90 80 65 1 -// !f! = %%MIDI beat 105 95 80 1 -// !ff! = %%MIDI beat 120 110 95 1 -// !fff! = %%MIDI beat 127 125 110 1 -static void abc_MIDI_beat(ABCHANDLE *h, const char *p) -{ - int i,j; - h->beat[0] = 127; - h->beat[1] = 125; - h->beat[2] = 110; - h->beat[3] = 1; - for( j=0; j<4; j++ ) { - while( isspace(*p) ) p++; - if( *p ) { - p += abc_getnumber(p, &i); - if( i < 0 ) i = 0; - if( i > 127 ) i = 127; - h->beat[j] = i; - } - } - if( h->beat[3] == 0 ) h->beat[3] = 1; // BB Ruud says: do not let you make mad -} - -// -// %%MIDI beatstring -// -// This provides an alternative way of specifying where the strong and weak -// stresses fall within a bar. 'f' means velocity a (normally strong), 'm' -// means velocity b (medium velocity) and 'p' means velocity c (soft velocity). -// For example, if the time signature is 7/8 with stresses on the first, fourth -// and sixth notes in the bar, we could use the following -// -// %%MIDI beatstring fppmpmp -static void abc_MIDI_beatstring(ABCHANDLE *h, const char *p) -{ - while( isspace(*p) ) p++; - if( h->beatstring ) _mm_free(h->allochandle, h->beatstring); - if( strlen(p) ) - h->beatstring = DupStr(h->allochandle,p,strlen(p)+1); - else - h->beatstring = NULL; -} - -static int abc_beat_vol(ABCHANDLE *h, int abcvol, int barpos) -{ - int vol; - if( h->beatstring ) { - vol = (h->beat[2] * 9) / 10; - if( barpos < (int)strlen(h->beatstring) ) { - switch(h->beatstring[barpos]) { - case 'f': - vol = h->beat[0]; - break; - case 'm': - vol = h->beat[1]; - break; - case 'p': - vol = h->beat[2]; - break; - default: - break; - } - } - } - else { - if( (barpos % h->beat[3]) == 0 ) { - if( barpos ) - vol = h->beat[1]; - else - vol = h->beat[0]; - } - else - vol = h->beat[2]; - } - vol *= abcvol; - vol /= 128; - return vol; -} - -static void abc_init_partpat(BYTE partp[27][2]) -{ - int i; - for( i=0; i<27; i++ ) { - partp[i][0] = 0xff; - partp[i][1] = 0; - } -} - -static int abc_partpat_to_orderlist(BYTE partp[27][2], const char *abcparts, ABCHANDLE *h, BYTE **list, int orderlen) -{ - int t, partsused; - const char *p; - BYTE *orderlist = *list; - static int ordersize = 0; - if( *list == NULL ) { - ordersize = 128; - orderlist = (BYTE *)_mm_calloc(h->ho, ordersize, sizeof(BYTE)); - *list = orderlist; - } - if( abcparts ) { - partsused = 0; - for( p = abcparts; *p; p++ ) { - for( t = partp[*p - 'A'][0]; t < partp[*p - 'A'][1]; t++ ) { - if( orderlen == ordersize ) { - ordersize <<= 1; - orderlist = (BYTE *)_mm_recalloc(h->ho, orderlist, ordersize, sizeof(BYTE)); - *list = orderlist; - } - orderlist[orderlen] = t; - orderlen++; - partsused++; - } - } - if( partsused ) return orderlen; - } - // some fool wrote a P: string in the header but didn't use P: in the body - for( t = partp[26][0]; t < partp[26][1]; t++ ) { - if( orderlen == ordersize ) { - ordersize <<= 1; - orderlist = (BYTE *)_mm_recalloc(h->ho, orderlist, ordersize, sizeof(BYTE)); - *list = orderlist; - } - orderlist[orderlen] = t; - orderlen++; - } - return orderlen; -} - -static void abc_globalslide(ABCHANDLE *h, uint32_t tracktime, int slide) -{ - ABCTRACK *tp; - ABCEVENT *e; - int hslide; - hslide = h->track? h->track->slidevol: slide; - for( tp=h->track; tp; tp = tp->next ) { - if( slide ) { - tp->slidevoltime = tracktime; - if( slide == 2 ) - tp->slidevol = 0; - } - if( tp->slidevol > -2 && slide < 2 ) - tp->slidevol = slide; - } - if( h->track && h->track->tail - && hslide != slide && slide == -2 - && h->track->tail->tracktick >= tracktime ) { - // need to update jumptypes in mastertrack from tracktime on... - for( e=h->track->head; e; e=e->next ) { - if( e->flg == 1 && e->cmd == cmdjump && e->tracktick >= tracktime ) { - switch( e->par[jumptype] ) { - case jumpnormal: - case jumpfade: - e->par[jumptype] = jumpfade; - break; - case jumpdacapo: - case jumpdcfade: - e->par[jumptype] = jumpdcfade; - break; - case jumpdasegno: - case jumpdsfade: - e->par[jumptype] = jumpdsfade; - break; - } - } - } - } -} - -static void abc_recalculate_tracktime(ABCHANDLE *h) { - ABCTRACK *ttp; - h->tracktime = 0; - for( ttp=h->track; ttp; ttp=ttp->next ) - if( ttp->tail && ttp->tail->tracktick > h->tracktime ) - h->tracktime = ttp->tail->tracktick; -} - -static void abc_MIDI_command(ABCHANDLE *h, char *p, char delim) { - int t; - // interpret some of the possibilitys - if( !strncmp(p,"bassprog",8) && isspace(p[8]) ) h->abcbassprog = abc_MIDI_getprog(p+8)+1; - if( !strncmp(p,"bassvol",7) && isspace(p[7]) ) h->abcbassvol = abc_MIDI_getnumber(p+7); - if( !strncmp(p,"beat",4) && isspace(p[4]) ) abc_MIDI_beat(h, p+4); - if( !strncmp(p,"beatstring",10) && isspace(p[10]) ) abc_MIDI_beatstring(h, p+4); - if( !strncmp(p,"chordname",9) && isspace(p[9]) ) abc_MIDI_chordname(p+9); - if( !strncmp(p,"chordprog",9) && isspace(p[9]) ) h->abcchordprog = abc_MIDI_getprog(p+9)+1; - if( !strncmp(p,"chordvol",8) && isspace(p[8]) ) h->abcchordvol = abc_MIDI_getnumber(p+8); - if( !strncmp(p,"drone",5) && isspace(p[5]) ) abc_MIDI_drone(p+5, &h->dronegm, h->dronepitch, h->dronevol); - if( !strncmp(p,"droneoff",8) && (p[8]=='\0' || p[8]==delim || isspace(p[8])) ) h->droneon = 0; - if( !strncmp(p,"droneon",7) && (p[7]=='\0' || p[7]==delim || isspace(p[7])) ) h->droneon = 1; - t = h->drumon; - if( !strncmp(p,"drum",4) && isspace(p[4]) ) { - h->drumon = abc_MIDI_drum(p+4, h); - if( h->drumon ) --h->drumon; - else h->drumon = t; - } - if( !strncmp(p,"drumoff",7) && (p[7]=='\0' || p[7]==delim || isspace(p[7])) ) h->drumon = 0; - if( !strncmp(p,"drumon",6) && (p[6]=='\0' || p[6]==delim || isspace(p[6])) ) h->drumon = 1; - if( t != h->drumon ) { - if( h->drumon && !h->tpr ) h->tpr = h->track; - if( h->tpr ) abc_add_drum_sync(h, h->tpr, h->tracktime); // don't start drumming from the beginning of time! - if( h->tpr && !h->drumon ) h->tpr = NULL; - } - t = h->gchordon; - if( !strncmp(p,"gchord",6) && (p[6]=='\0' || p[6]==delim || isspace(p[6])) ) { - h->gchordon = abc_MIDI_gchord(p+6, h); - if( h->gchordon ) --h->gchordon; - else h->gchordon = t; - } - if( !strncmp(p,"gchordoff",9) && (p[9]=='\0' || p[9]==delim || isspace(p[9])) ) h->gchordon = 0; - if( !strncmp(p,"gchordon",8) && (p[8]=='\0' || p[8]==delim || isspace(p[8])) ) h->gchordon = 1; - if( t != h->gchordon ) { - if( h->tpc ) abc_add_gchord_syncs(h, h->tpc, h->tracktime); - } - if( !strncmp(p,"channel",7) && isspace(p[7]) ) - abc_MIDI_channel(p+8, h->tp = abc_check_track(h, h->tp), h); - if( !strncmp(p,"program",7) && isspace(p[7]) ) - abc_MIDI_program(p+8, h->tp = abc_check_track(h, h->tp), h); - if( !strncmp(p,"voice",5) && isspace(p[5]) ) - abc_MIDI_voice(p+6, h->tp = abc_check_track(h, h->tp), h); - if( !strncmp(p,"legato",6) && (p[6]=='\0' || p[6]==delim || isspace(p[6])) ) - abc_MIDI_legato(p+6, h->tp = abc_check_track(h, h->tp)); -} - -// continuate line that ends with a backslash, can't do this in abc_gets because voice lines -// can have comment lines in between that must be parsed properly, for example: -// [V:1] cdef gabc' |\ << continuation backslash -// %%MIDI program 25 -// c'bag fedc | -// informational lines can have this too, so it is rather convoluted code... -static char *abc_continuated(ABCHANDLE *h, MMFILE *mmf, char *p) { - char *pm, *p1, *p2 = 0; - int continued; - pm = p; - while( pm[strlen(pm)-1]=='\\' ) { - p1 = strdup(pm); - if( p2 ) free(p2); - continued = 1; - while( continued ) { - continued = 0; - pm = abc_gets(h, mmf); - if( !pm ) { - abc_message("line not properly continued\n%s", p1); - return p1; - } - while( *pm && isspace(*pm) ) ++pm; - if( !strncmp(pm,"%%",2) ) { - for( p2 = pm+2; *p2 && isspace(*p2); p2++ ) ; - if( !strncmp(p2,"MIDI",4) && (p2[4]=='=' || isspace(p2[4])) ) { - for( p2+=5; *p2 && isspace(*p2); p2++ ) ; - if( *p2 == '=' ) - for( p2+=1; *p2 && isspace(*p2); p2++ ) ; - abc_MIDI_command(h,p2,'%'); - } - continued = 1; - } - } - p2 = (char *)malloc(strlen(p1)+strlen(pm)); - if( !p2 ) { - abc_message("macro line too long\n%s", p1); - return p1; - } - p1[strlen(p1)-1] = '\0'; // strip off the backslash - strcpy(p2,p1); - strcat(p2,pm); - pm = p2; - free(p1); - } - return pm; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -BOOL ABC_Load(ABCHANDLE *h, UNIMOD *of, MMSTREAM *mmfile) -#else -BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength) -#endif -{ - static int avoid_reentry = 0; -#ifdef NEWMIKMOD -#define m_nDefaultTempo of->inittempo -#else - ABCHANDLE *h; - uint32_t numpat; - MMFILE mm, *mmfile; -#endif - uint32_t t; - char *line, *p, *pp, ch, ch0=0; - char barsig[52]; // for propagated accidental key signature within bar - char *abcparts; - uint8_t partpat[27][2], *orderlist; - int orderlen; - enum { NOWHERE, INBETWEEN, INHEAD, INBODY, INSKIPFORX, INSKIPFORQUOTE } abcstate; - ABCEVENT_JUMPTYPE j; - ABCEVENT_X_EFFECT abceffect; - int abceffoper; - int abcxcount=0, abcxwanted=0, abcxnumber=1; - int abckey, abcrate, abcchord, abcvol, abcbeatvol, abcnoslurs, abcnolegato, abcfermata, abcarpeggio, abcto; - int abctempo; - int cnotelen=0, cnotediv=0, snotelen, snotediv, mnotelen, mnotediv, notelen, notediv; - // c for chords, s for standard L: setting, m for M: barlength - int abchornpipe, brokenrithm, tupletp, tupletq, tupletr; - int ktempo; - uint32_t abcgrace=0, bartime, thistime=0; - ABCTRACK *tpd, *ttp; - ABCMACRO *mp; - int mmsp; -#ifdef NEWMIKMOD - MMSTREAM *mmstack[MAXABCINCLUDES]; - h->ho = _mmalloc_create("Load_ABC_ORDERLIST", NULL); -#else - MMFILE *mmstack[MAXABCINCLUDES]; - if( !TestABC(lpStream, dwMemLength) ) return FALSE; - h = ABC_Init(); - if( !h ) return FALSE; - mmfile = &mm; - mm.mm = (char *)lpStream; - mm.sz = dwMemLength; - mm.pos = 0; -#endif - while( avoid_reentry ) sleep(1); - avoid_reentry = 1; - pat_resetsmp(); - pat_init_patnames(); - m_nDefaultTempo = 0; - global_voiceno = 0; - abckey = 0; - h->tracktime = 0; - global_songstart = 0; - h->speed = 6; - abcrate = 240; - global_tempo_factor = 2; - global_tempo_divider = 1; - abctempo = 0; - ktempo = 0; - abceffect = none; - abceffoper = 0; - abcvol = 120; - h->abcchordvol = abcvol; - h->abcbassvol = abcvol; - h->abcchordprog = 25; // acoustic guitar - h->abcbassprog = 33; // acoustic bass - abcparts = 0; - abcnoslurs = 1; - abcnolegato = 1; - abcfermata = 0; - abcarpeggio = 0; - abcto = 0; - snotelen = 0; - snotediv = 0; - mnotelen = 1; - mnotediv = 1; - abchornpipe = 0; - brokenrithm = 0; - tupletp = 0; - tupletq = 0; - tupletr = 0; - h->ktrans = 0; - h->drumon = 0; - h->gchordon = 1; - h->droneon = 0; - h->tracktime = 0; - bartime = 0; - h->tp = NULL; - h->tpc = NULL; - h->tpr = NULL; - tpd = NULL; - h->dronegm = 71; - h->dronepitch[0] = 45; - h->dronepitch[1] = 33; - h->dronevol[0] = 80; - h->dronevol[1] = 80; - abc_new_umacro(h, "v = +downbow+"); - abc_new_umacro(h, "u = +upbow+"); - abc_new_umacro(h, "O = +coda+"); - abc_new_umacro(h, "S = +segno+"); - abc_new_umacro(h, "P = +uppermordent+"); - abc_new_umacro(h, "M = +lowermordent+"); - abc_new_umacro(h, "L = +emphasis+"); - abc_new_umacro(h, "H = +fermata+"); - abc_new_umacro(h, "T = +trill+"); - abc_new_umacro(h, "~ = +roll+"); - abc_setup_chordnames(); - abc_init_partpat(partpat); - abc_MIDI_beat(h, ""); // reset beat array - abc_MIDI_beatstring(h, ""); // reset beatstring - orderlist = NULL; - orderlen = 0; - mmsp = 1; - mmstack[0] = mmfile; - mmfseek(mmfile,0,SEEK_SET); - abcstate = NOWHERE; - if( h->pickrandom ) { - abcstate = INSKIPFORX; - abcxcount = 0; - mmfseek(mmfile,0,SEEK_SET); - while( (line=abc_gets(h, mmfile)) ) { - for( p=line; isspace(*p); p++ ) ; - if( !strncmp(p,"X:",2) ) abcxcount++; - } - if( abcxcount == 0 ) - abcstate = NOWHERE; - else - abcxwanted = (h->pickrandom - 1) % abcxcount; - abcxcount = 0; - mmfseek(mmfile,0,SEEK_SET); - } - while( mmsp > 0 ) { - mmsp--; - while((line=abc_gets(h, mmstack[mmsp]))) { - for( p=line; isspace(*p); p++ ) ; - switch(abcstate) { - case INSKIPFORX: - if( !strncmp(p,"X:",2) ) { - if( abcxcount++ != abcxwanted ) - break; - } - // fall through - case INBETWEEN: - if( !strncmp(p,"X:",2) ) { - abcstate = INHEAD; -#ifdef NEWMIKMOD - of->songname = NULL; -#else - memset(m_szNames[0], 0, 32); -#endif - for( p+=2; isspace(*p); p++ ) ; - abcxnumber = atoi(p); - abchornpipe = 0; - h->droneon = 0; - h->dronegm = 71; - h->dronepitch[0] = 45; - h->dronepitch[1] = 33; - h->dronevol[0] = 80; - h->dronevol[1] = 80; - for( ttp = h->track; ttp; ttp=ttp->next ) { - ttp->vno = 0; // mark track unused - ttp->capostart = NULL; - } - h->tp = NULL; // forget old voices - h->tpc = NULL; - h->tpr = NULL; - global_voiceno = 0; - abc_set_parts(&abcparts, 0); - abcgrace = 0; - h->ktrans = 0; - ktempo = 0; - h->gchordon = 1; - h->drumon = 0; - global_songstart = h->tracktime; - abc_MIDI_beat(h, ""); // reset beat array - abc_MIDI_beatstring(h, ""); // reset beatstring - strcpy(h->gchord, ""); // reset gchord string - abcnolegato = 1; // reset legato switch - } - break; - case NOWHERE: - if( p[0] != '\0' && p[1] == ':' ) { - abcstate = INHEAD; - abc_set_parts(&abcparts, 0); - strcpy(h->gchord, ""); - if( h->drumon && h->tpr ) abc_add_drum_sync(h, h->tpr, h->tracktime); - if( h->tpc && !h->gchordon ) abc_add_gchord_syncs(h, h->tpc, h->tracktime); - h->gchordon = 1; - h->drumon = 0; - } - else - break; - case INHEAD: - if( !strncmp(p,"L:",2) ) { - sscanf(p+2," %d / %d", &snotelen, &snotediv); - break; - } - if( !strncmp(p,"M:",2) ) { - abc_M_field(p+2, &mnotelen, &mnotediv); - break; - } - if( !strncmp(p,"P:",2) ) { - abc_set_parts(&abcparts, p+2); - break; - } - if( !strncmp(p,"Q:",2) ) { - abctempo = abc_extract_tempo(p+2,0); - ktempo = 1; - if( h->track ) { - // make h->tracktime start of a new age... - abc_add_partbreak(h, h->track, h->tracktime); - abc_add_tempo_event(h, h->track, h->tracktime, abctempo); - } - if( m_nDefaultTempo == 0 ) m_nDefaultTempo = abctempo; - break; - } - if( !strncmp(p,"T:",2) ) { - char buf[200]; - if( strchr(p,'%') ) *strchr(p,'%') = '\0'; - for( t=strlen(p)-1; isspace(p[t]); t-- ) - p[t]='\0'; - for( t=2; isspace(p[t]); t++ ) ; -#ifdef NEWMIKMOD - if( of->songname ) - strcpy(buf,of->songname); - else - strcpy(buf,""); -#else - strcpy(buf,m_szNames[0]); -#endif - if( strlen(buf) + strlen(p+t) > 199 ) p[t+199-strlen(buf)] = '\0'; // chop it of - if( strlen(buf) ) strcat(buf," "); // add a space - strcat(buf, p+t); -#ifdef NEWMIKMOD - of->songname = DupStr(of->allochandle, buf, strlen(buf)); -#else - if( strlen(buf) > 31 ) buf[31] = '\0'; // chop it of - strcpy(m_szNames[0], buf); -#endif - break; - } - if( !strncmp(p,"R:",2) ) { - for( p+=2; isspace(*p); p++ ) ; - if( !strncmp(p,"hornpipe",8) && (isspace(p[8]) || p[8]=='\0') ) abchornpipe = 1; - else abchornpipe = 0; - break; - } - if( !strncmp(p,"V:",2) ) { - for( t=2; p[t]==' '; t++ ) ; - h->tp = abc_locate_track(h, p+t, 0); - abcvol = h->tp->volume; - abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - break; - } - if( !strncmp(p,"K:",2) ) { - abcstate = INBODY; - abckey = ABC_Key(p+2); - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - p = abc_skip_word(p+2); - h->ktrans = abc_transpose(p); - *p = '%'; // force skip rest of line - if( snotelen == 0 ) { // calculate default notelen from meter M: - if( mnotediv == 0 ) mnotediv = mnotelen = 1; // do'nt get nuked - snotelen = 100 * mnotelen / mnotediv; - if( snotelen > 74 ) - snotediv = 8; - else - snotediv = 16; - snotelen = 1; - } - abceffect = none; - abceffoper = 0; - if( !(snotelen == 1 && snotediv == 8) ) abchornpipe = 0; // no matter what they said at R: - brokenrithm = 0; - global_part = ' '; - abcgrace = 0; - abcnoslurs = abcnolegato; - abcto = 0; - h->tpc = NULL; // reset chord track - tpd = NULL; // reset drone track - h->tpr = NULL; // reset drum track - if( !strlen(h->gchord) ) abc_metric_gchord(h, mnotelen, mnotediv); - h->barticks = notelen_notediv_to_ticks(h->speed, mnotelen, mnotediv); - if( abctempo && !ktempo ) { // did not set tempo in this songpiece so reset to abcrate - abctempo = 0; - global_tempo_factor = 2; - global_tempo_divider = 1; - if( h->track ) { - // make h->tracktime start of a new age... - abc_add_partbreak(h, h->track, h->tracktime); - abc_add_tempo_event(h, h->track, h->tracktime, abcrate); - } - if( m_nDefaultTempo == 0 ) m_nDefaultTempo = abcrate; - } - abc_init_partpat(partpat); - partpat[26][0] = abc_patno(h, h->tracktime); - partpat[26][1] = 0; - abc_globalslide(h, h->tracktime, 2); // reset all volumeslides - break; - } - if( !strlen(p) ) - abcstate = INBETWEEN; - break; - case INSKIPFORQUOTE: - while( *p && *p != '"' ) - p++; - if( *p == '\0' ) - break; - abcstate = INBODY; - // fall through - case INBODY: - if( !strlen(p) && h->track ) { // end of this song - abcstate = h->pickrandom? INSKIPFORX: INBETWEEN; - // last but not least shut off all pending events - abc_recalculate_tracktime(h); - for( ttp=h->track; ttp; ttp=ttp->next ) - abc_add_noteoff(h,ttp,h->tracktime); - abc_add_partbreak(h, h->track, h->tracktime); - t = abc_patno(h, h->tracktime); - if( abc_pattracktime(h, h->tracktime) % abcticks(64 * h->speed) ) t++; - if( global_part == ' ' ) { - partpat[26][1] = t; - if( abcparts ) { - for( t=0; t<26; t++ ) - if( partpat[t][0] < partpat[t][1] ) break; - if( t == 26 ) { - abc_message("parts (%s) set but not used", abcparts); - abc_set_parts(&abcparts, 0); // forget the parts array - } - } - } - else - partpat[global_part - 'A'][1] = t; - if( !abcparts ) abc_song_to_parts(h, &abcparts, partpat); - orderlen = abc_partpat_to_orderlist(partpat, abcparts, h, &orderlist, orderlen); - } - if( !strncmp(p,"V:",2) ) { - for( t=2; p[t]==' '; t++ ) ; - h->tp = abc_locate_track(h, p+t, 0); - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - abcgrace = 0; - brokenrithm = 0; - h->tracktime = abc_tracktime(h->tp); - bartime = h->tracktime; // it is not friendly to break voices in the middle of a track... - abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - *p = '%'; // make me skip the rest of the line.... - } - if( !strncmp(p,"K:",2) ) { - abckey = ABC_Key(p+2); - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - p = abc_skip_word(p+2); - h->ktrans = abc_transpose(p); - *p = '%'; // make me skip the rest of the line.... - } - if( !strncmp(p,"L:",2) ) { - sscanf(p+2," %d / %d", &snotelen, &snotediv); - *p = '%'; // make me skip the rest of the line.... - } - if( !strncmp(p,"M:",2) ) { - abc_M_field(p+2, &mnotelen, &mnotediv); - h->barticks = notelen_notediv_to_ticks(h->speed, mnotelen, mnotediv); - *p = '%'; // make me skip the rest of the line.... - } - if( !strncmp(p,"Q:",2) ) { - abctempo = abc_extract_tempo(p+2,ch0=='\\'); - if( !h->track ) { - h->tp = abc_check_track(h, h->track); - h->tp->vno = 0; // mark reuseable (temporarely, until first notes come up) - } - abc_add_tempo_event(h, h->track, h->tracktime, abctempo); - *p = '%'; // make me skip the rest of the line.... - } - if( !strncmp(p,"T:",2) ) { - char buf[200]; - if( strchr(p,'%') ) *strchr(p,'%') = '\0'; - for( t=strlen(p)-1; isspace(p[t]); t-- ) - p[t]='\0'; - for( t=2; isspace(p[t]); t++ ) ; -#ifdef NEWMIKMOD - if( of->songname ) - strcpy(buf,of->songname); - else - strcpy(buf,""); -#else - strcpy(buf,m_szNames[0]); -#endif - if( strlen(buf) + strlen(p+t) > 198 ) p[t+198-strlen(buf)] = '\0'; // chop it of - if( strlen(buf) ) strcat(buf," "); // add a space - strcat(buf, p+t); -#ifdef NEWMIKMOD - of->songname = DupStr(of->allochandle, buf, strlen(buf)); -#else - if( strlen(buf) > 31 ) buf[31] = '\0'; // chop it of - strcpy(m_szNames[0], buf); -#endif - *p = '%'; // make me skip the rest of the line.... - } - break; - } - if( !strncmp(p,"m:",2) ) { - if( abcstate != INSKIPFORX ) { - char *pm; - pm = abc_continuated(h, mmstack[mmsp], p); - abc_new_macro(h, pm+2); - if( pm != p ) { - free(pm); - if( h->tp ) abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - } - } - *p = '%'; // skip rest of line - } - if( !strncmp(p,"U:",2) ) { - abc_new_umacro(h, p+2); - *p = '%'; // skip rest of line - } - if( !strncmp(p,"w:",2) ) { // inline lyrics - *p = '%'; // skip rest of line - } - if( !strncmp(p,"W:",2) ) { // lyrics at end of song body - *p = '%'; // skip rest of line - } - if( !strncmp(p,"d:",2) ) { // oldstyle decorations - abc_message("warning: old style decorations not handled\n%s", p); - *p = '%'; // skip rest of line - } - if( !strncmp(p,"s:",2) ) { // newstyle decorations (symbols) - abc_message("warning: new style decorations not handled\n%s", p); - *p = '%'; // skip rest of line - } - if( !strncmp(p,"I:",2) && abcstate != INSKIPFORX ) { // handle like oldstyle '%%command' lines - p[0]= '%'; - p[1]= '%'; - } - if( !strncmp(p,"%%",2) ) { - for( p+=2; *p && isspace(*p); p++ ) ; - if( !strncmp(p,"abc-include",11) && isspace(p[11]) ) { - for( t=12; isspace(p[t]); t++ ) ; - if( p[t] ) { - mmsp++; - if( mmsp == MAXABCINCLUDES ) { - mmsp--; - abc_message("failure: too many abc-include's, %s", &p[t]); - } else { - mmstack[mmsp] = mmfopen(&p[t], "r"); - if( !mmstack[mmsp] ) { - mmsp--; - abc_message("failure: abc-include file %s not found", &p[t]); - } - } - } - else abc_message("failure: abc-include missing file name, %s", p); - } - if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(p[4])) && abcstate != INSKIPFORX ) { - for( p+=5; *p && isspace(*p); p++ ) ; - if( *p == '=' ) - for( p+=1; *p && isspace(*p); p++ ) ; - abc_MIDI_command(h,p,'%'); - if( h->tp ) abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - } - if(*p) *p = '%'; // skip rest of line - } - if( abcstate == INBODY ) { - if( *p == 'P' && p[1] == ':' ) { // a line with a part indication - if( abcparts != NULL ) { - // make h->tracktime start of a new age... - if( !h->track ) { - h->tp = abc_check_track(h, h->track); - h->tp->vno = 0; // mark reuseable (temporarely, until first notes come up) - } - h->tracktime = h->track? abc_tracktime(h->track): 0; // global parts are voice independent - abc_add_partbreak(h, h->track, h->tracktime); - t = abc_patno(h, h->tracktime); - if( global_part == ' ' ) { - partpat[26][1] = t; - if( abcparts ) { - for( t=0; t<26; t++ ) - if( partpat[t][0] < partpat[t][1] ) break; - if( t == 26 ) { - abc_message("parts (%s) set but not used", abcparts); - abc_set_parts(&abcparts, 0); // forget the parts array - } - } - } - else - partpat[global_part - 'A'][1] = t; - // give every new coming abcevent the desired part indication - while( p[2]==' ' || p[2]=='.' ) p++; // skip blancs and dots - if( isupper(p[2]) ) - global_part = p[2]; - else - global_part = ' '; - if( global_part == ' ' ) - partpat[26][0] = t; - else - partpat[global_part - 'A'][0] = t; - } - *p = '%'; // make me skip the rest of the line.... - } - if( h->droneon && !tpd ) { - tpd = h->track; - if( tpd ) { - tpd = abc_locate_track(h, tpd->v, DRONEPOS1); - tpd->instr = h->dronegm; - abc_add_dronenote(h, tpd, h->tracktime, h->dronepitch[0], h->dronevol[0]); - tpd = abc_locate_track(h, tpd->v, DRONEPOS2); - tpd->instr = h->dronegm; - abc_add_dronenote(h, tpd, h->tracktime, h->dronepitch[1], h->dronevol[1]); - } - } - if( tpd && !h->droneon ) { - tpd = abc_locate_track(h, tpd->v, DRONEPOS1); - abc_add_noteoff(h, tpd, h->tracktime); - tpd = abc_locate_track(h, tpd->v, DRONEPOS2); - abc_add_noteoff(h, tpd, h->tracktime); - tpd = NULL; - } - if( h->drumon && !h->tpr ) { - h->tpr = h->track; - if( h->tpr ) abc_add_drum_sync(h, h->tpr, h->tracktime); // don't start drumming from the beginning of time! - } - if( h->tpr && !h->drumon ) h->tpr = NULL; - if( *p && *p != '%' ) { // skip uninteresting lines - // plough thru the songline gathering mos.... - ch0 = ' '; - pp = 0; - while( (ch = *p++) ) { - if( !pp && isalpha(ch) && *p != ':' ) { // maybe a macro - for( mp=h->umacro; mp; mp=mp->next ) { - if( ch == mp->name[0] ) { - pp = p; - p = mp->subst; - ch = *p; - if( ch ) p++; - break; - } - } - } - switch(ch) { - case '%': - abcto = 0; - while( *p ) p++; - break; - case '[': // chord follows or some inline field - abcto = 0; - if( *p=='|' ) break; // [| a thick-thin bar line, loop around and let case '|' handle it - if( !strncmp(p,"V:",2) ) { // inline voice change - for( t=2; isspace(p[t]); t++ ) ; - h->tp = abc_locate_track(h, p+t, 0); - for( ; *p && *p != ']'; p++ ) ; - abcgrace = 0; - brokenrithm = 0; - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - h->tracktime = abc_tracktime(h->tp); - bartime = h->tracktime; // it is not wise to break voices in the middle of a track... - abcvol = h->tp->volume; - abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - break; - } - if( !strncmp(p,"K:",2) ) { - abckey = ABC_Key(p+2); - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - p = abc_skip_word(p+2); - h->ktrans = abc_transpose(p); - for( ; *p && *p != ']'; p++ ) ; - break; - } - if( !strncmp(p,"M:",2) ) { - abc_M_field(p+2, &mnotelen, &mnotediv); - for( ; *p && *p != ']'; p++ ) ; - h->barticks = notelen_notediv_to_ticks(h->speed, mnotelen, mnotediv); - break; - } - if( !strncmp(p,"P:",2) ) { // a [P:X] field inline - if( abcparts != NULL ) { - // make h->tracktime start of a new age... - if( h->track ) - abc_add_partbreak(h, h->track, h->tracktime); - t = abc_patno(h, h->tracktime); - if( global_part == ' ' ) - partpat[26][1] = t; - else - partpat[global_part - 'A'][1] = t; - // give every new coming abcevent the desired part indication - while( isspace(p[2]) || p[2]=='.' ) p++; // skip blancs and dots - if( isupper(p[2]) ) - global_part = p[2]; - else - global_part = ' '; - if( global_part == ' ' ) - partpat[26][0] = t; - else - partpat[global_part - 'A'][0] = t; - } - for( ; *p && *p != ']'; p++ ) ; - break; - } - if( !strncmp(p,"Q:",2) ) { - abctempo = abc_extract_tempo(p+2,1); - for( ; *p && *p != ']'; p++ ) ; - if( h->track ) - abc_add_tempo_event(h, h->track, h->tracktime, abctempo); - break; - } - if( !strncmp(p,"I:",2) ) { // interpret some of the possibilitys - for( p += 2; isspace(*p); p++ ) ; - if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(p[4])) ) { // interpret some of the possibilitys - for( p += 4; isspace(*p); p++ ) ; - if( *p == '=' ) - for( p += 1; isspace(*p); p++ ) ; - abc_MIDI_command(h, p, ']'); - if( h->tp ) abcnolegato = !h->tp->legato; - if( !abcnolegato ) abcnoslurs = 0; - } - for( ; *p && *p != ']'; p++ ) ; // skip rest of inline field - } - if( *p && p[1] == ':' ) { // some other kind of inline field - for( ; *p && *p != ']'; p++ ) ; - break; - } - if( *p && strchr("abcdefgABCDEFG^_=",*p) ) { - int cnl[8],cnd[8],vnl,nl0=0,nd0=0; // for chords with notes of varying length - abcchord = 0; - vnl = 0; - h->tp = abc_check_track(h, h->tp); - abc_track_clear_tiedvpos(h); - abcbeatvol = abc_beat_vol(h, abcvol, (h->tracktime - bartime)/notelen_notediv_to_ticks(h->speed,1,mnotediv)); - while( (ch=*p++) && (ch != ']') ) { - h->tp = abc_locate_track(h, h->tp->v, abcchord? abcchord+DRONEPOS2: 0); - p += abc_add_noteon(h, ch, p, h->tracktime, barsig, abcbeatvol, abceffect, abceffoper); - p += abc_notelen(p, ¬elen, ¬ediv); - if( *p == '-' ) { - p++; - if( h->tp->tail && h->tp->tail->flg != 1 ) - h->tp->tienote = h->tp->tail; - } - if( abcchord<8 ) { - cnl[abcchord] = notelen; - cnd[abcchord] = notediv; - } - if( abcchord==0 ) { - cnotelen = notelen; - cnotediv = notediv; - nl0 = notelen; - nd0 = notediv; - } - else { - if( cnotelen != notelen || cnotediv != notediv ) { - vnl = 1; - // update to longest duration - if( cnotelen * notediv < notelen * cnotediv ) { - cnotelen = notelen; - cnotediv = notediv; - abc_track_untie_short_chordnotes(h); - } - if( cnotelen * notediv > notelen * cnotediv ) { - if( h->tp->tienote ) { - abc_message("short notes in chord can not be tied:\n%s", h->line); - h->tp->tienote = 0; // short chord notes cannot be tied... - } - } - // update to shortest duration - if( nl0 * notediv > notelen * nd0 ) { - nl0 = notelen; - nd0 = notediv; - } - } - } - abcchord++; - } - p += abc_notelen(p, ¬elen, ¬ediv); - if( (ch = *p) == '-' ) p++; // tied chord... - if( abcarpeggio ) { // update starttime in the noteon events... - thistime = notelen_notediv_to_ticks(h->speed, nl0*notelen*snotelen, nd0*notediv*snotediv)/abcchord; - if( thistime > abcticks(h->speed) ) thistime = abcticks(h->speed); - for( nl0=1; nl0tp = abc_locate_track(h, h->tp->v, nl0+DRONEPOS2); - if( h->tp->tail ) - h->tp->tail->tracktick = h->tracktime + thistime * nl0; - } - } - notelen *= cnotelen; - notediv *= cnotediv; - tupletr = abc_tuplet(¬elen, ¬ediv, tupletp, tupletq, tupletr); - while( isspace(*p) ) p++; // allow spacing in broken rithm notation - p += abc_brokenrithm(p, ¬elen, ¬ediv, &brokenrithm, abchornpipe); - thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv); - if( abcfermata ) { - thistime <<= 1; - abcfermata = 0; - } - if( thistime > abcgrace ) { - thistime -= abcgrace; - abcgrace = 0; - } - else { - abcgrace -= thistime; - thistime = abcticks(h->speed); - abcgrace += abcticks(h->speed); - } - h->tracktime += thistime; - while( abcchord>0 ) { - abcchord--; - h->tp = abc_locate_track(h, h->tp->v, abcchord? abcchord+DRONEPOS2: 0); - if( vnl && (abcchord < 8) && (cnl[abcchord] != cnotelen || cnd[abcchord] != cnotediv) ) { - abc_add_noteoff(h, h->tp, - h->tracktime - thistime - + (thistime * cnl[abcchord] * cnotediv)/(cnd[abcchord] * cnotelen) ); - } - else { - if( ch=='-' && h->tp->tail && h->tp->tail->flg != 1 ) - h->tp->tienote = h->tp->tail; // copy noteon event to tienote in track - if( thistime > abcticks(h->speed) ) - abc_add_noteoff(h, h->tp, h->tracktime - abcnoslurs); - else - abc_add_noteoff(h, h->tp, h->tracktime); - } - } - if( h->gchordon && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - abcarpeggio = 0; - if( abceffoper != 255 ) abceffect = none; - break; - } - if( isdigit(*p) ) { // different endings in repeats [i,j,n-r,s,... - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - p += abc_getnumber(p, ¬elen); - abc_add_variant_start(h, h->tp, h->tracktime, notelen); - while( *p==',' || *p=='-' ) { - if( *p==',' ) { - p++; - p += abc_getnumber(p, ¬elen); - abc_add_variant_choise(h->tp, notelen); - } - else { - p++; - p += abc_getnumber(p, ¬ediv); - while( notelen < notediv ) { - notelen++; - abc_add_variant_choise(h->tp, notelen); - } - } - } - break; - } - // collect the notes in the chord - break; - case '(': // slurs follow or some tuplet (duplet, triplet etc.) - abcto = 0; - if( isdigit(*p) ) { - p += abc_getnumber(p,&tupletp); - tupletr = tupletp; // ABC draft 2.0 (4.13): if r is not given it defaults to p - switch( tupletp ) { // ABC draft 2.0 (4.13): q defaults depending on p and time signature - case 2: case 4: case 8: - tupletq = 3; - break; - case 3: case 6: - tupletq = 2; - break; - default: - if( snotediv == 8 ) - tupletq = 3; - else - tupletq = 2; - break; - } - if( *p==':' ) { - p++; - if( isdigit(*p) ) p += abc_getnumber(p,&tupletq); - if( *p==':' ) { - p++; - if( isdigit(*p) ) p += abc_getnumber(p,&tupletr); - } - } - } - else - abcnoslurs=0; - break; - case ')': // end of slurs - abcto = 0; - abcnoslurs = abcnolegato; - break; - case '{': // grace notes follow - abcto = 0; - h->tp = abc_check_track(h, h->tp); - abc_track_clear_tiedvpos(h); - abcgrace = 0; - abcbeatvol = abc_beat_vol(h, abcvol, (h->tracktime - bartime)/notelen_notediv_to_ticks(h->speed,1,mnotediv)); - while( (ch=*p++) && (ch != '}') ) { - p += abc_add_noteon(h, ch, p, h->tracktime+abcgrace, barsig, abcbeatvol, none, 0); - p += abc_notelen(p, ¬elen, ¬ediv); - if( *p=='-' ) { - p++; - if( h->tp->tail->flg != 1 ) - h->tp->tienote = h->tp->tail; - } - notediv *= 4; // grace notes factor 4 shorter (1/8 => 1/32) - abcgrace += notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv); - abc_add_noteoff(h, h->tp, h->tracktime + abcgrace); - } - h->tracktime += abcgrace; - abc_add_sync(h, h->tp, h->tracktime); - if( h->gchordon && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - break; - case '|': // bar symbols - abcto = 0; - if( h->gchordon && h->tp && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - bartime = h->tracktime; - if( h->tp && h->tp->vpos ) h->tp = abc_locate_track(h, h->tp->v, 0); // reset from voice overlay - if( isdigit(*p) ) { // different endings in repeats |i,j,n-r,s,... - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - p += abc_getnumber(p, ¬elen); - abc_add_variant_start(h, h->tp, h->tracktime, notelen); - while( *p==',' || *p=='-' ) { - if( *p==',' ) { - p++; - p += abc_getnumber(p, ¬elen); - abc_add_variant_choise(h->tp, notelen); - } - else { - p++; - p += abc_getnumber(p, ¬ediv); - while( notelen < notediv ) { - notelen++; - abc_add_variant_choise(h->tp, notelen); - } - } - } - break; - } - if( *p==':' ) { // repeat start - p++; - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_setloop(h, h->tp, h->tracktime); - } - break; - case '&': // voice overlay - abcto = 0; - h->tracktime = bartime; - h->tp = abc_check_track(h, h->tp); - t = h->tp->vpos; - h->tp = abc_locate_track(h, h->tp->v, t? t+1: DRONEPOS2+1); - break; - case ']': // staff break, end of song - abcto = 0; - break; - case ':': // repeat jump - abcto = 0; - h->tp = abc_check_track(h, h->tp); - j = (h->tp->slidevol == -2)? jumpfade: jumpnormal; - abc_add_setjumploop(h, h->tp, h->tracktime, j); - abc_add_partbreak(h, h->tp, h->tracktime); - if( *p==':' ) { // repeat start without intermediate bar symbol - p++; - abc_add_setloop(h, h->tp, h->tracktime); - } - break; - case '"': // chord notation - if( !strchr("_^<>@", *p) && !isdigit(*p) ) { // if it's not a annotation string - h->tp = abc_check_track(h, h->tp); - if( !h->tpc ) h->tpc = abc_locate_track(h, h->tp->v, 0); - if( h->tp == h->tpc ) abc_add_chord(p, h, h->tpc, h->tracktime); // only do chords for one voice - } - abcto = 0; - while( (ch=*p++) && (ch != '"') ) { - if( !strncasecmp(p,"fade",4) && h->track && h->track->slidevol > -2 ) - abc_globalslide(h, h->tracktime, -2); // set volumeslide to fade away... - if( !strncasecmp(p,"to coda",7) ) { - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_tocoda(h, h->tp, h->tracktime); - p+=7; - abcto = -1; - } - else - if( !isspace(*p) ) abcto = 0; - if( !strncasecmp(p,"to",2) && (isspace(p[2]) || p[2] == '"') ) abcto = 1; - } - if( !ch ) abcstate = INSKIPFORQUOTE; - break; - case '\\': // skip the rest of this line, should be the end of the line anyway - while( *p ) p++; - ch = '\\'; // remember for invoice tempo changes.... - break; - case '!': // line break, or deprecated old style decoration - case '+': // decorations new style - if( !strncmp(p,"coda",4) && p[4] == ch ) { - h->tp = abc_check_track(h, h->tp); - if( abcto ) { - if( abcto > 0 ) { - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_tocoda(h, h->tp, h->tracktime); - } - } - else { - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_coda(h, h->tp, h->tracktime); - } - p += 5; - abcto = 0; - break; - } - abcto = 0; - if( !strncmp(p,"arpeggio",8) && p[8] == ch ) { - abcarpeggio = 1; - p += 9; - break; - } - if( !strncmp(p,"crescendo(",10) && p[10] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 1); - p += 11; - break; - } - if( !strncmp(p,"crescendo)",10) && p[10] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 0); - p += 11; - break; - } - if( !strncmp(p,"<(",2) && p[2] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 1); - p += 3; - break; - } - if( !strncmp(p,"<)",2) && p[2] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 0); - p += 3; - break; - } - if( !strncmp(p,"dimimuendo(",11) && p[11] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, -1); - p += 12; - break; - } - if( !strncmp(p,"diminuendo)",11) && p[11] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 0); - p += 12; - break; - } - if( !strncmp(p,">(",2) && p[2] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, -1); - p += 3; - break; - } - if( !strncmp(p,">)",2) && p[2] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_globalslide(h, h->tracktime, 0); - p += 3; - break; - } - if( !strncmp(p,"upbow",5) && p[5] == ch ) { - abceffect = bow; - abceffoper = 1; - p += 6; - break; - } - if( !strncmp(p,"downbow",7) && p[7] == ch ) { - abceffect = bow; - abceffoper = 0; - p += 8; - break; - } - if( !strncmp(p,"trill",5) && p[5] == ch ) { - abceffect = trill; - abceffoper = 0; - p += 6; - break; - } - if( !strncmp(p,"trill(",6) && p[6] == ch ) { - abceffect = trill; - abceffoper = 255; - p += 7; - break; - } - if( !strncmp(p,"trill)",6) && p[6] == ch ) { - abceffect = none; - abceffoper = 0; - p += 7; - break; - } - if( !strncmp(p,"accent",6) && p[6] == ch ) { - abceffect = accent; - abceffoper = 0; - p += 7; - break; - } - if( !strncmp(p,"emphasis",8) && p[8] == ch ) { - abceffect = accent; - abceffoper = 0; - p += 9; - break; - } - if( !strncmp(p,">",1) && p[1] == ch ) { - abceffect = accent; - abceffoper = 0; - p += 2; - break; - } - if( !strncmp(p,"fermata",7) && p[7] == ch ) { - abcfermata = 1; - p += 8; - break; - } - if( !strncmp(p,"fine",4) && p[4] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_fine(h, h->tp, h->tracktime); - p += 5; - break; - } - if( !strncmp(p,"segno",5) && p[5] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_segno(h, h->tp, h->tracktime); - p += 6; - break; - } - if( !strncmp(p,"tocoda",6) && p[6] == ch ) { - h->tp = abc_check_track(h, h->tp); - abc_add_partbreak(h, h->tp, h->tracktime); - abc_add_tocoda(h, h->tp, h->tracktime); - p += 7; - break; - } - if( !strncmp(p,"D.C.",4) && p[4] == ch ) { - h->tp = abc_check_track(h, h->tp); - j = (h->tp->slidevol == -2)? jumpdcfade: jumpdacapo; - abc_add_setjumploop(h, h->tp, h->tracktime, j); - abc_add_partbreak(h, h->tp, h->tracktime); - p += 5; - break; - } - if( !strncmp(p,"D.S.",4) && p[4] == ch ) { - h->tp = abc_check_track(h, h->tp); - j = (h->tp->slidevol == -2)? jumpdsfade: jumpdasegno; - abc_add_setjumploop(h, h->tp, h->tracktime, j); - abc_add_partbreak(h, h->tp, h->tracktime); - p += 5; - break; - } - if( !strncmp(p,"dacapo",6) && p[6] == ch ) { - h->tp = abc_check_track(h, h->tp); - j = (h->tp->slidevol == -2)? jumpdcfade: jumpdacapo; - abc_add_setjumploop(h, h->tp, h->tracktime, j); - abc_add_partbreak(h, h->tp, h->tracktime); - p += 7; - break; - } - if( !strncmp(p,"dacoda",6) && p[6] == ch ) { - h->tp = abc_check_track(h, h->tp); - j = (h->tp->slidevol == -2)? jumpdcfade: jumpdacapo; - abc_add_setjumploop(h, h->tp, h->tracktime, j); - abc_add_partbreak(h, h->tp, h->tracktime); - p += 7; - break; - } - if( ch == '!' ) { - for( t=0; p[t] && strchr("|[:]!",p[t])==0 && !isspace(p[t]); t++ ) ; - if( p[t] == '!' ) { // volume and other decorations, deprecated - h->tp = abc_check_track(h, h->tp); - abcvol = abc_parse_decorations(h, h->tp, p); - p = &p[t+1]; - } - } - else { - h->tp = abc_check_track(h, h->tp); - abcvol = abc_parse_decorations(h, h->tp, p); - while( (ch=*p++) && (ch != '+') ) - ; - } - break; - case '`': // back quotes are for readability - break; - case '.': // staccato marks - break; - default: // some kinda note must follow - if( strchr("abcdefgABCDEFG^_=X",ch) ) { - h->tp = abc_check_track(h, h->tp); - abc_track_clear_tiedvpos(h); - abcbeatvol = abc_beat_vol(h, abcvol, (h->tracktime - bartime)/notelen_notediv_to_ticks(h->speed,1,mnotediv)); - p += abc_add_noteon(h, ch, p, h->tracktime, barsig, abcbeatvol, abceffect, abceffoper); - if( abceffoper != 255 ) abceffect = none; - p += abc_notelen(p, ¬elen, ¬ediv); - if( *p=='-' ) { - p++; - if( h->tp->tail && h->tp->tail->flg != 1 ) - h->tp->tienote = h->tp->tail; - } - tupletr = abc_tuplet(¬elen, ¬ediv, tupletp, tupletq, tupletr); - while( isspace(*p) ) p++; // allow spacing in broken rithm notation - p += abc_brokenrithm(p, ¬elen, ¬ediv, &brokenrithm, abchornpipe); - thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv); - if( abcfermata ) { - thistime <<= 1; - abcfermata = 0; - } - if( thistime > abcgrace ) { - thistime -= abcgrace; - abcgrace = 0; - } - else { - abcgrace -= thistime; - thistime = abcticks(h->speed); - abcgrace += abcticks(h->speed); - } - h->tracktime += thistime; - if( thistime > abcticks(h->speed) ) - abc_add_noteoff(h, h->tp, h->tracktime - abcnoslurs - (( ch0 == '.')? thistime / 2: 0)); - else - abc_add_noteoff(h, h->tp, h->tracktime); - abc_add_sync(h, h->tp, h->tracktime); - if( h->gchordon && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - abcarpeggio = 0; - break; - } - if( strchr("zx",ch) ) { - h->tp = abc_check_track(h, h->tp); - abc_track_clear_tiednote(h); - p += abc_notelen(p, ¬elen, ¬ediv); - tupletr = abc_tuplet(¬elen, ¬ediv, tupletp, tupletq, tupletr); - while( isspace(*p) ) p++; // allow spacing in broken rithm notation - p += abc_brokenrithm(p, ¬elen, ¬ediv, &brokenrithm, abchornpipe); - thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv); - if( abcfermata ) { - thistime <<= 1; - abcfermata = 0; - } - if( thistime > abcgrace ) { - thistime -= abcgrace; - abcgrace = 0; - } - else { - abcgrace -= thistime; - thistime = abcticks(h->speed); - abcgrace += abcticks(h->speed); - } - h->tracktime += thistime; - abc_add_sync(h, h->tp, h->tracktime); - if( h->gchordon && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - abcarpeggio = 0; - break; - } - if( strchr("Z",ch) ) { - h->tp = abc_check_track(h, h->tp); - abc_track_clear_tiednote(h); - p += abc_notelen(p, ¬elen, ¬ediv); - thistime = notelen_notediv_to_ticks(h->speed, notelen*mnotelen, notediv*mnotediv); - if( abcfermata ) { - thistime <<= 1; - abcfermata = 0; - } - if( thistime > abcgrace ) { - thistime -= abcgrace; - abcgrace = 0; - } - else { - abcgrace -= thistime; - thistime = abcticks(h->speed); - abcgrace += abcticks(h->speed); - } - h->tracktime += thistime; - sprintf(barsig, "%s%s", sig[abckey], sig[abckey]); // reset the key signature - abc_add_sync(h, h->tp, h->tracktime); - if( h->gchordon && (h->tp == h->tpc) ) - abc_add_gchord(h, h->tracktime, bartime); - if( h->drumon && (h->tp == h->tpr) ) - abc_add_drum(h, h->tracktime, bartime); - abcarpeggio = 0; - break; - } - if( isalpha(ch) && *p==':' ) { - // some unprocessed field line? - while( *p ) p++; // skip it - break; - } - break; - } - ch0 = ch; // remember previous char, can be staccato dot... - if( pp ) { // did we have a U: macro substitution? - if( !*p ) { - p = pp; - pp = 0; - } - } - } - } - } - } - if( mmsp ) mmfclose(mmstack[mmsp]); - } - ABC_CleanupMacros(h); // we dont need them anymore - if( !h->track ) { - char buf[10]; - sprintf(buf,"%u",abcxnumber); - abc_message("abc X:%s has no body", buf); - h->track = abc_check_track(h, h->track); // for sanity... - } - if( abcstate == INBODY ) { - // last but not least shut off all pending events - abc_recalculate_tracktime(h); - for( ttp=h->track; ttp; ttp=ttp->next ) - abc_add_noteoff(h,ttp,h->tracktime); - abc_add_partbreak(h, h->track, h->tracktime); - t = abc_patno(h, h->tracktime); - if( abc_pattracktime(h, h->tracktime) % abcticks(64 * h->speed) ) t++; - if( global_part == ' ' ) { - partpat[26][1] = t; - if( abcparts ) { - for( t=0; t<26; t++ ) - if( partpat[t][0] < partpat[t][1] ) break; - if( t == 26 ) { - abc_message("parts (%s) set but not used", abcparts); - abc_set_parts(&abcparts, 0); // forget the parts array - } - } - } - else - partpat[global_part - 'A'][1] = t; - if( !abcparts ) abc_song_to_parts(h, &abcparts, partpat); - orderlen = abc_partpat_to_orderlist(partpat, abcparts, h, &orderlist, orderlen); - } - abc_synchronise_tracks(h); // distribute all control events - abc_recalculate_tracktime(h); -/* - - abctrack: - tracktick long - note byte - octave byte - instrument byte - effects byte - - tick = tracktick modulo speed - row = (tracktick div speed) modulo 64 - pat = (tracktick div speed) div 64 - ord = calculated - -*/ - if( (p=getenv(ABC_ENV_DUMPTRACKS)) ) { - printf("P:%s\n",abcparts); - for( t=0; t<26; t++ ) - if( partpat[t][1] >= partpat[t][0] ) - printf(" %c ",t+'A'); - if( partpat[26][1] >= partpat[26][0] ) - printf("All"); - printf("\n"); - for( t=0; t<27; t++ ) - if( partpat[t][1] >= partpat[t][0] ) - printf("%3d ",partpat[t][0]); - printf("\n"); - for( t=0; t<27; t++ ) - if( partpat[t][1] >= partpat[t][0] ) - printf("%3d ",partpat[t][1]); - printf("\n"); - for( t=0; (int)tmemsize = PTMEM_LAST; // Number of memory slots to reserve! - of->modtype = _mm_strdup(of->allochandle, ABC_Version); - of->numpat = 1+(modticks(h->tracktime) / h->speed / 64); - of->numpos = orderlen; - of->reppos = 0; - of->initspeed = h->speed; - of->numchn = abc_numtracks(h); - of->numtrk = of->numpat * of->numchn; - of->initvolume = 64; - of->pansep = 128; - // orderlist - if(!AllocPositions(of, orderlen)) { - avoid_reentry = 0; - return FALSE; - } - for(t=0; tpositions[t] = orderlist[t]; - _mmalloc_close(h->ho); // get rid of orderlist memory -#else - m_nType = MOD_TYPE_ABC; - numpat = 1+(modticks(h->tracktime) / h->speed / 64); - if( numpat > MAX_PATTERNS ) - numpat = MAX_PATTERNS; - m_nDefaultSpeed = h->speed; - m_nChannels = abc_numtracks(h); - m_dwSongFlags = SONG_LINEARSLIDES; - m_nMinPeriod = 28 << 2; - m_nMaxPeriod = 1712 << 3; - // orderlist - for(t=0; t < (uint32_t)orderlen; t++){ - if( t >= MAX_ORDERS ) - break; - Order[t] = orderlist[t]; - } - free(orderlist); // get rid of orderlist memory -#endif -#ifdef NEWMIKMOD - // ============================== - // Load the pattern info now! - if(!AllocTracks(of)) return 0; - if(!AllocPatterns(of)) return 0; - of->ut = utrk_init(of->numchn, h->allochandle); - utrk_memory_reset(of->ut); - utrk_local_memflag(of->ut, PTMEM_PORTAMENTO, TRUE, FALSE); - ABC_ReadPatterns(of, h, of->numpat); - // load instruments after building the patterns (chan == 10 track handling) - if( !PAT_Load_Instruments(of) ) { - avoid_reentry = 0; - return FALSE; - } - // ============================================================ - // set panning positions - for(t=0; tnumchn; t++) { - of->panning[t] = PAN_LEFT+((t+2)%5)*((PAN_RIGHT - PAN_LEFT)/5); // 0x30 = std s3m val - } -#else - // ============================== - // Load the pattern info now! - if( ABC_ReadPatterns(Patterns, PatternSize, h, numpat, m_nChannels) ) { - // :^( need one more channel to handle the global events ;^b - m_nChannels++; - h->tp = abc_locate_track(h, "", 99); - abc_add_sync(h, h->tp, h->tracktime); - for( t=0; t MAX_BASECHANNELS ) - m_nChannels = MAX_BASECHANNELS; - for(t=0; t -*/ - -/////////////////////////////////////////////////// -// -// AMF module loader -// -// There is 2 types of AMF files: -// - ASYLUM Music Format -// - Advanced Music Format(DSM) -// -/////////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#define AMFLOG - -//#pragma warning(disable:4244) - -#pragma pack(1) - -typedef struct _AMFFILEHEADER -{ - UCHAR szAMF[3]; - UCHAR version; - CHAR title[32]; - UCHAR numsamples; - UCHAR numorders; - USHORT numtracks; - UCHAR numchannels; -} AMFFILEHEADER; - -typedef struct _AMFSAMPLE -{ - UCHAR type; - CHAR samplename[32]; - CHAR filename[13]; - ULONG offset; - ULONG length; - USHORT c2spd; - UCHAR volume; -} AMFSAMPLE; - - -#pragma pack() - - -#ifdef AMFLOG -extern void Log(LPCSTR, ...); -#endif - -VOID AMF_Unpack(MODCOMMAND *pPat, const BYTE *pTrack, UINT nRows, UINT nChannels) -//------------------------------------------------------------------------------- -{ - UINT lastinstr = 0; - UINT nTrkSize = bswapLE16(*(USHORT *)pTrack); - nTrkSize += (UINT)pTrack[2] << 16; - pTrack += 3; - while (nTrkSize--) - { - UINT row = pTrack[0]; - UINT cmd = pTrack[1]; - UINT arg = pTrack[2]; - if (row >= nRows) break; - MODCOMMAND *m = pPat + row * nChannels; - if (cmd < 0x7F) // note+vol - { - m->note = cmd+1; - if (!m->instr) m->instr = lastinstr; - m->volcmd = VOLCMD_VOLUME; - m->vol = arg; - } else - if (cmd == 0x7F) // duplicate row - { - signed char rdelta = (signed char)arg; - int rowsrc = (int)row + (int)rdelta; - if ((rowsrc >= 0) && (rowsrc < (int)nRows)) memcpy(m, &pPat[rowsrc*nChannels],sizeof(pPat[rowsrc*nChannels])); - } else - if (cmd == 0x80) // instrument - { - m->instr = arg+1; - lastinstr = m->instr; - } else - if (cmd == 0x83) // volume - { - m->volcmd = VOLCMD_VOLUME; - m->vol = arg; - } else - // effect - { - UINT command = cmd & 0x7F; - UINT param = arg; - switch(command) - { - // 0x01: Set Speed - case 0x01: command = CMD_SPEED; break; - // 0x02: Volume Slide - // 0x0A: Tone Porta + Vol Slide - // 0x0B: Vibrato + Vol Slide - case 0x02: command = CMD_VOLUMESLIDE; - case 0x0A: if (command == 0x0A) command = CMD_TONEPORTAVOL; - case 0x0B: if (command == 0x0B) command = CMD_VIBRATOVOL; - if (param & 0x80) param = (-(signed char)param)&0x0F; - else param = (param&0x0F)<<4; - break; - // 0x04: Porta Up/Down - case 0x04: if (param & 0x80) { command = CMD_PORTAMENTOUP; param = (-(signed char)param)&0x7F; } - else { command = CMD_PORTAMENTODOWN; } break; - // 0x06: Tone Portamento - case 0x06: command = CMD_TONEPORTAMENTO; break; - // 0x07: Tremor - case 0x07: command = CMD_TREMOR; break; - // 0x08: Arpeggio - case 0x08: command = CMD_ARPEGGIO; break; - // 0x09: Vibrato - case 0x09: command = CMD_VIBRATO; break; - // 0x0C: Pattern Break - case 0x0C: command = CMD_PATTERNBREAK; break; - // 0x0D: Position Jump - case 0x0D: command = CMD_POSITIONJUMP; break; - // 0x0F: Retrig - case 0x0F: command = CMD_RETRIG; break; - // 0x10: Offset - case 0x10: command = CMD_OFFSET; break; - // 0x11: Fine Volume Slide - case 0x11: if (param) { command = CMD_VOLUMESLIDE; - if (param & 0x80) param = 0xF0|((-(signed char)param)&0x0F); - else param = 0x0F|((param&0x0F)<<4); - } else command = 0; break; - // 0x12: Fine Portamento - // 0x16: Extra Fine Portamento - case 0x12: - case 0x16: if (param) { int mask = (command == 0x16) ? 0xE0 : 0xF0; - command = (param & 0x80) ? CMD_PORTAMENTOUP : CMD_PORTAMENTODOWN; - if (param & 0x80) param = mask|((-(signed char)param)&0x0F); - else param |= mask; - } else command = 0; break; - // 0x13: Note Delay - case 0x13: command = CMD_S3MCMDEX; param = 0xD0|(param & 0x0F); break; - // 0x14: Note Cut - case 0x14: command = CMD_S3MCMDEX; param = 0xC0|(param & 0x0F); break; - // 0x15: Set Tempo - case 0x15: command = CMD_TEMPO; break; - // 0x17: Panning - case 0x17: param = (param+64)&0x7F; - if (m->command) { if (!m->volcmd) { m->volcmd = VOLCMD_PANNING; m->vol = param/2; } command = 0; } - else { command = CMD_PANNING8; } - // Unknown effects - default: command = param = 0; - } - if (command) - { - m->command = command; - m->param = param; - } - } - pTrack += 3; - } -} - - - -BOOL CSoundFile::ReadAMF(LPCBYTE lpStream, const DWORD dwMemLength) -//----------------------------------------------------------- -{ - const AMFFILEHEADER *pfh = (AMFFILEHEADER *)lpStream; - DWORD dwMemPos; - - if ((!lpStream) || (dwMemLength < 2048)) return FALSE; - if ((!strncmp((LPCTSTR)lpStream, "ASYLUM Music Format V1.0", 25)) && (dwMemLength > 4096)) - { - UINT numorders, numpats, numsamples; - - dwMemPos = 32; - numpats = lpStream[dwMemPos+3]; - numorders = lpStream[dwMemPos+4]; - numsamples = 64; - dwMemPos += 6; - if ((!numpats) || (numpats > MAX_PATTERNS) || (!numorders) - || (numpats*64*32 + 294 + 37*64 >= dwMemLength)) return FALSE; - m_nType = MOD_TYPE_AMF0; - m_nChannels = 8; - m_nInstruments = 0; - m_nSamples = 31; - m_nDefaultTempo = 125; - m_nDefaultSpeed = 6; - for (UINT iOrd=0; iOrdnFineTune = MOD2XMFineTune(lpStream[dwMemPos+22]); - psmp->nVolume = lpStream[dwMemPos+23]; - psmp->nGlobalVol = 64; - if (psmp->nVolume > 0x40) psmp->nVolume = 0x40; - psmp->nVolume <<= 2; - psmp->nLength = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+25))); - psmp->nLoopStart = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+29))); - psmp->nLoopEnd = psmp->nLoopStart + bswapLE32(*((LPDWORD)(lpStream+dwMemPos+33))); - if ((psmp->nLoopEnd > psmp->nLoopStart) && (psmp->nLoopEnd <= psmp->nLength)) - { - psmp->uFlags = CHN_LOOP; - } else - { - psmp->nLoopStart = psmp->nLoopEnd = 0; - } - if ((psmp->nLength) && (iSmp>31)) m_nSamples = iSmp+1; - dwMemPos += 37; - } - for (UINT iPat=0; iPatnote = 0; - - if (pin[0]) - { - p->note = pin[0] + 13; - } - p->instr = pin[1]; - p->command = pin[2]; - p->param = pin[3]; - if (p->command > 0x0F) - { - #ifdef AMFLOG - Log("0x%02X.0x%02X ?", p->command, p->param); - #endif - p->command = 0; - } - ConvertModCommand(p); - pin += 4; - p++; - } - dwMemPos += 64*32; - } - // Read samples - for (UINT iData=0; iDatanLength) - { - if (dwMemPos > dwMemLength) return FALSE; - dwMemPos += ReadSample(psmp, RS_PCM8S, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); - } - } - return TRUE; - } - //////////////////////////// - // DSM/AMF - USHORT *ptracks[MAX_PATTERNS]; - DWORD sampleseekpos[MAX_SAMPLES]; - - if ((pfh->szAMF[0] != 'A') || (pfh->szAMF[1] != 'M') || (pfh->szAMF[2] != 'F') - || (pfh->version < 10) || (pfh->version > 14) || (!bswapLE16(pfh->numtracks)) - || (!pfh->numorders) || (pfh->numorders > MAX_PATTERNS) - || (!pfh->numsamples) || (pfh->numsamples > MAX_SAMPLES) - || (pfh->numchannels < 4) || (pfh->numchannels > 32)) - return FALSE; - memcpy(m_szNames[0], pfh->title, 32); - m_szNames[0][31] = '\0'; - dwMemPos = sizeof(AMFFILEHEADER); - m_nType = MOD_TYPE_AMF; - m_nChannels = pfh->numchannels; - m_nSamples = pfh->numsamples; - m_nInstruments = 0; - // Setup Channel Pan Positions - if (pfh->version >= 11) - { - signed char *panpos = (signed char *)(lpStream + dwMemPos); - UINT nchannels = (pfh->version >= 13) ? 32 : 16; - for (UINT i=0; i 256) { pan = 128; ChnSettings[i].dwFlags |= CHN_SURROUND; } - ChnSettings[i].nPan = pan; - } - dwMemPos += nchannels; - } else - { - for (UINT i=0; i<16; i++) - { - ChnSettings[i].nPan = (lpStream[dwMemPos+i] & 1) ? 0x30 : 0xD0; - } - dwMemPos += 16; - } - // Get Tempo/Speed - m_nDefaultTempo = 125; - m_nDefaultSpeed = 6; - if (pfh->version >= 13) - { - if (lpStream[dwMemPos] >= 32) m_nDefaultTempo = lpStream[dwMemPos]; - if (lpStream[dwMemPos+1] <= 32) m_nDefaultSpeed = lpStream[dwMemPos+1]; - dwMemPos += 2; - } - // Setup sequence list - for (UINT iOrd=0; iOrdnumorders) - { - Order[iOrd] = iOrd; - PatternSize[iOrd] = 64; - if (pfh->version >= 14) - { - PatternSize[iOrd] = bswapLE16(*(USHORT *)(lpStream+dwMemPos)); - dwMemPos += 2; - } - ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos); - dwMemPos += m_nChannels * sizeof(USHORT); - } - } - if (dwMemPos + m_nSamples * (sizeof(AMFSAMPLE)+8) > dwMemLength) return TRUE; - // Read Samples - UINT maxsampleseekpos = 0; - for (UINT iIns=0; iInssamplename, 32); - m_szNames[iIns+1][31] = '\0'; - memcpy(pins->name, psh->filename, 13); - pins->name[12] = '\0'; - pins->nLength = bswapLE32(psh->length); - pins->nC4Speed = bswapLE16(psh->c2spd); - pins->nGlobalVol = 64; - pins->nVolume = psh->volume * 4; - if (pfh->version >= 11) - { - pins->nLoopStart = bswapLE32(*(DWORD *)(lpStream+dwMemPos)); - pins->nLoopEnd = bswapLE32(*(DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - } else - { - pins->nLoopStart = bswapLE16(*(WORD *)(lpStream+dwMemPos)); - pins->nLoopEnd = pins->nLength; - dwMemPos += 2; - } - sampleseekpos[iIns] = 0; - if ((psh->type) && (bswapLE32(psh->offset) < dwMemLength-1)) - { - sampleseekpos[iIns] = bswapLE32(psh->offset); - if (bswapLE32(psh->offset) > maxsampleseekpos) - maxsampleseekpos = bswapLE32(psh->offset); - if ((pins->nLoopEnd > pins->nLoopStart + 2) - && (pins->nLoopEnd <= pins->nLength)) pins->uFlags |= CHN_LOOP; - } - } - // Read Track Mapping Table - USHORT *pTrackMap = (USHORT *)(lpStream+dwMemPos); - UINT realtrackcnt = 0; - dwMemPos += pfh->numtracks * sizeof(USHORT); - for (UINT iTrkMap=0; iTrkMapnumtracks; iTrkMap++) - { - if (realtrackcnt < pTrackMap[iTrkMap]) realtrackcnt = pTrackMap[iTrkMap]; - } - // Store tracks positions - BYTE **pTrackData = new BYTE *[realtrackcnt]; - memset(pTrackData, 0, sizeof(pTrackData)); - for (UINT iTrack=0; iTracknumorders; iPat++) - { - MODCOMMAND *p = AllocatePattern(PatternSize[iPat], m_nChannels); - if (!p) break; - Patterns[iPat] = p; - for (UINT iChn=0; iChnnumtracks)) - { - UINT realtrk = bswapLE16(pTrackMap[nTrack-1]); - if (realtrk) - { - realtrk--; - if ((realtrk < realtrackcnt) && (pTrackData[realtrk])) - { - AMF_Unpack(p+iChn, pTrackData[realtrk], PatternSize[iPat], m_nChannels); - } - } - } - } - } - delete[] pTrackData; - // Read Sample Data - for (UINT iSeek=1; iSeek<=maxsampleseekpos; iSeek++) - { - if (dwMemPos >= dwMemLength) break; - for (UINT iSmp=0; iSmp -*/ - -////////////////////////////////////////////// -// AMS module loader // -////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#pragma pack(1) - -typedef struct AMSFILEHEADER -{ - char szHeader[7]; // "Extreme" // changed from CHAR - BYTE verlo, verhi; // 0x??,0x01 - BYTE chncfg; - BYTE samples; - WORD patterns; - WORD orders; - BYTE vmidi; - WORD extra; -} AMSFILEHEADER; - -typedef struct AMSSAMPLEHEADER -{ - DWORD length; - DWORD loopstart; - DWORD loopend; - BYTE finetune_and_pan; - WORD samplerate; // C-2 = 8363 - BYTE volume; // 0-127 - BYTE infobyte; -} AMSSAMPLEHEADER; - - -#pragma pack() - - - -BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength) -//----------------------------------------------------------- -{ - BYTE pkinf[MAX_SAMPLES]; - AMSFILEHEADER *pfh = (AMSFILEHEADER *)lpStream; - DWORD dwMemPos; - UINT tmp, tmp2; - - if ((!lpStream) || (dwMemLength < 1024)) return FALSE; - if ((pfh->verhi != 0x01) || (strncmp(pfh->szHeader, "Extreme", 7)) - || (!pfh->patterns) || (!pfh->orders) || (!pfh->samples) || (pfh->samples >= MAX_SAMPLES) - || (pfh->patterns > MAX_PATTERNS) || (pfh->orders > MAX_ORDERS)) - { - return ReadAMS2(lpStream, dwMemLength); - } - dwMemPos = sizeof(AMSFILEHEADER) + pfh->extra; - if (dwMemPos + pfh->samples * sizeof(AMSSAMPLEHEADER) + 256 >= dwMemLength) return FALSE; - m_nType = MOD_TYPE_AMS; - m_nInstruments = 0; - m_nChannels = (pfh->chncfg & 0x1F) + 1; - m_nSamples = pfh->samples; - for (UINT nSmp=1; nSmp<=m_nSamples; nSmp++, dwMemPos += sizeof(AMSSAMPLEHEADER)) - { - AMSSAMPLEHEADER *psh = (AMSSAMPLEHEADER *)(lpStream + dwMemPos); - MODINSTRUMENT *pins = &Ins[nSmp]; - pins->nLength = psh->length; - pins->nLoopStart = psh->loopstart; - pins->nLoopEnd = psh->loopend; - pins->nGlobalVol = 64; - pins->nVolume = psh->volume << 1; - pins->nC4Speed = psh->samplerate; - pins->nPan = (psh->finetune_and_pan & 0xF0); - if (pins->nPan < 0x80) pins->nPan += 0x10; - pins->nFineTune = MOD2XMFineTune(psh->finetune_and_pan & 0x0F); - pins->uFlags = (psh->infobyte & 0x80) ? CHN_16BIT : 0; - if ((pins->nLoopEnd <= pins->nLength) && (pins->nLoopStart+4 <= pins->nLoopEnd)) pins->uFlags |= CHN_LOOP; - pkinf[nSmp] = psh->infobyte; - } - // Read Song Name - tmp = lpStream[dwMemPos++]; - if (dwMemPos + tmp + 1 >= dwMemLength) return TRUE; - tmp2 = (tmp < 32) ? tmp : 31; - if (tmp2) memcpy(m_szNames[0], lpStream+dwMemPos, tmp2); - m_szNames[0][tmp2] = 0; - dwMemPos += tmp; - // Read sample names - for (UINT sNam=1; sNam<=m_nSamples; sNam++) - { - if (dwMemPos + 32 >= dwMemLength) return TRUE; - tmp = lpStream[dwMemPos++]; - tmp2 = (tmp < 32) ? tmp : 31; - if (tmp2) memcpy(m_szNames[sNam], lpStream+dwMemPos, tmp2); - dwMemPos += tmp; - } - // Skip Channel names - for (UINT cNam=0; cNam= dwMemLength) return TRUE; - tmp = lpStream[dwMemPos++]; - dwMemPos += tmp; - } - // Read Pattern Names - m_lpszPatternNames = new char[pfh->patterns * 32]; // changed from CHAR - if (!m_lpszPatternNames) return TRUE; - m_nPatternNames = pfh->patterns; - memset(m_lpszPatternNames, 0, m_nPatternNames * 32); - for (UINT pNam=0; pNam < m_nPatternNames; pNam++) - { - if (dwMemPos + 32 >= dwMemLength) return TRUE; - tmp = lpStream[dwMemPos++]; - tmp2 = (tmp < 32) ? tmp : 31; - if (tmp2) memcpy(m_lpszPatternNames+pNam*32, lpStream+dwMemPos, tmp2); - dwMemPos += tmp; - } - // Read Song Comments - tmp = *((WORD *)(lpStream+dwMemPos)); - dwMemPos += 2; - if (dwMemPos + tmp >= dwMemLength) return TRUE; - if (tmp) - { - m_lpszSongComments = new char[tmp+1]; // changed from CHAR - if (!m_lpszSongComments) return TRUE; - memset(m_lpszSongComments, 0, tmp+1); - memcpy(m_lpszSongComments, lpStream + dwMemPos, tmp); - dwMemPos += tmp; - } - // Read Order List - for (UINT iOrd=0; iOrdorders; iOrd++, dwMemPos += 2) - { - UINT n = *((WORD *)(lpStream+dwMemPos)); - Order[iOrd] = (BYTE)n; - } - // Read Patterns - for (UINT iPat=0; iPatpatterns; iPat++) - { - if (dwMemPos + 4 >= dwMemLength) return TRUE; - UINT len = *((DWORD *)(lpStream + dwMemPos)); - dwMemPos += 4; - if ((len >= dwMemLength) || (dwMemPos + len > dwMemLength)) return TRUE; - PatternSize[iPat] = 64; - MODCOMMAND *m = AllocatePattern(PatternSize[iPat], m_nChannels); - if (!m) return TRUE; - Patterns[iPat] = m; - const BYTE *p = lpStream + dwMemPos; - UINT row = 0, i = 0; - while ((row < PatternSize[iPat]) && (i+2 < len)) - { - BYTE b0 = p[i++]; - BYTE b1 = p[i++]; - BYTE b2 = 0; - UINT ch = b0 & 0x3F; - // Note+Instr - if (!(b0 & 0x40)) - { - b2 = p[i++]; - if (ch < m_nChannels) - { - if (b1 & 0x7F) m[ch].note = (b1 & 0x7F) + 25; - m[ch].instr = b2; - } - if (b1 & 0x80) - { - b0 |= 0x40; - b1 = p[i++]; - } - } - // Effect - if (b0 & 0x40) - { - anothercommand: - if (b1 & 0x40) - { - if (ch < m_nChannels) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = b1 & 0x3F; - } - } else - { - b2 = p[i++]; - if (ch < m_nChannels) - { - UINT cmd = b1 & 0x3F; - if (cmd == 0x0C) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = b2 >> 1; - } else - if (cmd == 0x0E) - { - if (!m[ch].command) - { - UINT command = CMD_S3MCMDEX; - UINT param = b2; - switch(param & 0xF0) - { - case 0x00: if (param & 0x08) { param &= 0x07; param |= 0x90; } else {command=param=0;} break; - case 0x10: command = CMD_PORTAMENTOUP; param |= 0xF0; break; - case 0x20: command = CMD_PORTAMENTODOWN; param |= 0xF0; break; - case 0x30: param = (param & 0x0F) | 0x10; break; - case 0x40: param = (param & 0x0F) | 0x30; break; - case 0x50: param = (param & 0x0F) | 0x20; break; - case 0x60: param = (param & 0x0F) | 0xB0; break; - case 0x70: param = (param & 0x0F) | 0x40; break; - case 0x90: command = CMD_RETRIG; param &= 0x0F; break; - case 0xA0: if (param & 0x0F) { command = CMD_VOLUMESLIDE; param = (param << 4) | 0x0F; } else command=param=0; break; - case 0xB0: if (param & 0x0F) { command = CMD_VOLUMESLIDE; param |= 0xF0; } else command=param=0; break; - } - m[ch].command = command; - m[ch].param = param; - } - } else - { - m[ch].command = cmd; - m[ch].param = b2; - ConvertModCommand(&m[ch]); - } - } - } - if (b1 & 0x80) - { - b1 = p[i++]; - if (i <= len) goto anothercommand; - } - } - if (b0 & 0x80) - { - row++; - m += m_nChannels; - } - } - dwMemPos += len; - } - // Read Samples - for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Ins[iSmp].nLength) - { - if (dwMemPos >= dwMemLength - 9) return TRUE; - UINT flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8; - dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); - } - return TRUE; -} - - -///////////////////////////////////////////////////////////////////// -// AMS 2.2 loader - -#pragma pack(1) - -typedef struct AMS2FILEHEADER -{ - DWORD dwHdr1; // AMShdr - WORD wHdr2; - BYTE b1A; // 0x1A - BYTE titlelen; // 30-bytes max - CHAR szTitle[30]; // [titlelen] -} AMS2FILEHEADER; - -typedef struct AMS2SONGHEADER -{ - WORD version; - BYTE instruments; - WORD patterns; - WORD orders; - WORD bpm; - BYTE speed; - BYTE channels; - BYTE commands; - BYTE rows; - WORD flags; -} AMS2SONGHEADER; - -typedef struct AMS2INSTRUMENT -{ - BYTE samples; - BYTE notemap[NOTE_MAX]; -} AMS2INSTRUMENT; - -typedef struct AMS2ENVELOPE -{ - BYTE speed; - BYTE sustain; - BYTE loopbegin; - BYTE loopend; - BYTE points; - BYTE info[3]; -} AMS2ENVELOPE; - -typedef struct AMS2SAMPLE -{ - DWORD length; - DWORD loopstart; - DWORD loopend; - WORD frequency; - BYTE finetune; - WORD c4speed; - CHAR transpose; - BYTE volume; - BYTE flags; -} AMS2SAMPLE; - - -#pragma pack() - - -BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength) -//------------------------------------------------------------ -{ - const AMS2FILEHEADER *pfh = (AMS2FILEHEADER *)lpStream; - AMS2SONGHEADER *psh; - DWORD dwMemPos; - BYTE smpmap[16]; - BYTE packedsamples[MAX_SAMPLES]; - - if ((pfh->dwHdr1 != 0x68534D41) || (pfh->wHdr2 != 0x7264) - || (pfh->b1A != 0x1A) || (pfh->titlelen > 30)) return FALSE; - dwMemPos = pfh->titlelen + 8; - psh = (AMS2SONGHEADER *)(lpStream + dwMemPos); - if (((psh->version & 0xFF00) != 0x0200) || (!psh->instruments) - || (psh->instruments >= MAX_INSTRUMENTS) || (!psh->patterns) || (!psh->orders)) return FALSE; - dwMemPos += sizeof(AMS2SONGHEADER); - if (pfh->titlelen) - { - memcpy(m_szNames, pfh->szTitle, pfh->titlelen); - m_szNames[0][pfh->titlelen] = 0; - } - m_nType = MOD_TYPE_AMS; - m_nChannels = 32; - m_nDefaultTempo = psh->bpm >> 8; - m_nDefaultSpeed = psh->speed; - m_nInstruments = psh->instruments; - m_nSamples = 0; - if (psh->flags & 0x40) m_dwSongFlags |= SONG_LINEARSLIDES; - for (UINT nIns=1; nIns<=m_nInstruments; nIns++) - { - UINT insnamelen = lpStream[dwMemPos]; - CHAR *pinsname = (CHAR *)(lpStream+dwMemPos+1); - dwMemPos += insnamelen + 1; - AMS2INSTRUMENT *pins = (AMS2INSTRUMENT *)(lpStream + dwMemPos); - dwMemPos += sizeof(AMS2INSTRUMENT); - if (dwMemPos + 1024 >= dwMemLength) return TRUE; - AMS2ENVELOPE *volenv, *panenv, *pitchenv; - volenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); - dwMemPos += 5 + volenv->points*3; - panenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); - dwMemPos += 5 + panenv->points*3; - pitchenv = (AMS2ENVELOPE *)(lpStream+dwMemPos); - dwMemPos += 5 + pitchenv->points*3; - INSTRUMENTHEADER *penv = new INSTRUMENTHEADER; - if (!penv) return TRUE; - memset(smpmap, 0, sizeof(smpmap)); - memset(penv, 0, sizeof(INSTRUMENTHEADER)); - for (UINT ismpmap=0; ismpmapsamples; ismpmap++) - { - if ((ismpmap >= 16) || (m_nSamples+1 >= MAX_SAMPLES)) break; - m_nSamples++; - smpmap[ismpmap] = m_nSamples; - } - penv->nGlobalVol = 64; - penv->nPan = 128; - penv->nPPC = 60; - Headers[nIns] = penv; - if (insnamelen) - { - if (insnamelen > 31) insnamelen = 31; - memcpy(penv->name, pinsname, insnamelen); - penv->name[insnamelen] = 0; - } - for (UINT inotemap=0; inotemapNoteMap[inotemap] = inotemap+1; - penv->Keyboard[inotemap] = smpmap[pins->notemap[inotemap] & 0x0F]; - } - // Volume Envelope - { - UINT pos = 0; - penv->nVolEnv = (volenv->points > 16) ? 16 : volenv->points; - penv->nVolSustainBegin = penv->nVolSustainEnd = volenv->sustain; - penv->nVolLoopStart = volenv->loopbegin; - penv->nVolLoopEnd = volenv->loopend; - for (UINT i=0; inVolEnv; i++) - { - penv->VolEnv[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1); - pos += volenv->info[i*3] + ((volenv->info[i*3+1] & 1) << 8); - penv->VolPoints[i] = (WORD)pos; - } - } - penv->nFadeOut = (((lpStream[dwMemPos+2] & 0x0F) << 8) | (lpStream[dwMemPos+1])) << 3; - UINT envflags = lpStream[dwMemPos+3]; - if (envflags & 0x01) penv->dwFlags |= ENV_VOLLOOP; - if (envflags & 0x02) penv->dwFlags |= ENV_VOLSUSTAIN; - if (envflags & 0x04) penv->dwFlags |= ENV_VOLUME; - dwMemPos += 5; - // Read Samples - for (UINT ismp=0; ismpsamples; ismp++) - { - MODINSTRUMENT *psmp = ((ismp < 16) && (smpmap[ismp])) ? &Ins[smpmap[ismp]] : NULL; - UINT smpnamelen = lpStream[dwMemPos]; - if ((psmp) && (smpnamelen) && (smpnamelen <= 22)) - { - memcpy(m_szNames[smpmap[ismp]], lpStream+dwMemPos+1, smpnamelen); - } - dwMemPos += smpnamelen + 1; - if (psmp) - { - AMS2SAMPLE *pams = (AMS2SAMPLE *)(lpStream+dwMemPos); - psmp->nGlobalVol = 64; - psmp->nPan = 128; - psmp->nLength = pams->length; - psmp->nLoopStart = pams->loopstart; - psmp->nLoopEnd = pams->loopend; - psmp->nC4Speed = pams->c4speed; - psmp->RelativeTone = pams->transpose; - psmp->nVolume = pams->volume / 2; - packedsamples[smpmap[ismp]] = pams->flags; - if (pams->flags & 0x04) psmp->uFlags |= CHN_16BIT; - if (pams->flags & 0x08) psmp->uFlags |= CHN_LOOP; - if (pams->flags & 0x10) psmp->uFlags |= CHN_PINGPONGLOOP; - } - dwMemPos += sizeof(AMS2SAMPLE); - } - } - if (dwMemPos + 256 >= dwMemLength) return TRUE; - // Comments - { - UINT composernamelen = lpStream[dwMemPos]; - if (composernamelen) - { - m_lpszSongComments = new char[composernamelen+1]; // changed from CHAR - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos+1, composernamelen); - m_lpszSongComments[composernamelen] = 0; - } - } - dwMemPos += composernamelen + 1; - // channel names - for (UINT i=0; i<32; i++) - { - UINT chnnamlen = lpStream[dwMemPos]; - if ((chnnamlen) && (chnnamlen < MAX_CHANNELNAME)) - { - memcpy(ChnSettings[i].szName, lpStream+dwMemPos+1, chnnamlen); - } - dwMemPos += chnnamlen + 1; - if (dwMemPos + chnnamlen + 256 >= dwMemLength) return TRUE; - } - // packed comments (ignored) - UINT songtextlen = *((LPDWORD)(lpStream+dwMemPos)); - dwMemPos += songtextlen; - if (dwMemPos + 256 >= dwMemLength) return TRUE; - } - // Order List - { - for (UINT i=0; i= dwMemLength) return TRUE; - if (i < psh->orders) - { - Order[i] = lpStream[dwMemPos]; - dwMemPos += 2; - } - } - } - // Pattern Data - for (UINT ipat=0; ipatpatterns; ipat++) - { - if (dwMemPos+8 >= dwMemLength) return TRUE; - UINT packedlen = *((LPDWORD)(lpStream+dwMemPos)); - UINT numrows = 1 + (UINT)(lpStream[dwMemPos+4]); - //UINT patchn = 1 + (UINT)(lpStream[dwMemPos+5] & 0x1F); - //UINT patcmds = 1 + (UINT)(lpStream[dwMemPos+5] >> 5); - UINT patnamlen = lpStream[dwMemPos+6]; - dwMemPos += 4; - if ((ipat < MAX_PATTERNS) && (packedlen < dwMemLength-dwMemPos) && (numrows >= 8)) - { - if ((patnamlen) && (patnamlen < MAX_PATTERNNAME)) - { - char s[MAX_PATTERNNAME]; // changed from CHAR - memcpy(s, lpStream+dwMemPos+3, patnamlen); - s[patnamlen] = 0; - SetPatternName(ipat, s); - } - PatternSize[ipat] = numrows; - Patterns[ipat] = AllocatePattern(numrows, m_nChannels); - if (!Patterns[ipat]) return TRUE; - // Unpack Pattern Data - LPCBYTE psrc = lpStream + dwMemPos; - UINT pos = 3 + patnamlen; - UINT row = 0; - while ((pos < packedlen) && (row < numrows)) - { - MODCOMMAND *m = Patterns[ipat] + row * m_nChannels; - UINT byte1 = psrc[pos++]; - UINT ch = byte1 & 0x1F; - // Read Note + Instr - if (!(byte1 & 0x40)) - { - UINT byte2 = psrc[pos++]; - UINT note = byte2 & 0x7F; - if (note) m[ch].note = (note > 1) ? (note-1) : 0xFF; - m[ch].instr = psrc[pos++]; - // Read Effect - while (byte2 & 0x80) - { - byte2 = psrc[pos++]; - if (byte2 & 0x40) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = byte2 & 0x3F; - } else - { - UINT command = byte2 & 0x3F; - UINT param = psrc[pos++]; - if (command == 0x0C) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = param / 2; - } else - if (command < 0x10) - { - m[ch].command = command; - m[ch].param = param; - ConvertModCommand(&m[ch]); - } else - { - // TODO: AMS effects - } - } - } - } - if (byte1 & 0x80) row++; - } - } - dwMemPos += packedlen; - } - // Read Samples - for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Ins[iSmp].nLength) - { - if (dwMemPos >= dwMemLength - 9) return TRUE; - UINT flags; - if (packedsamples[iSmp] & 0x03) - { - flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8; - } else - { - flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; - } - dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); - } - return TRUE; -} - - -///////////////////////////////////////////////////////////////////// -// AMS Sample unpacking - -void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter) -{ - UINT tmplen = dmax; - signed char *amstmp = new signed char[tmplen]; - - if (!amstmp) return; - // Unpack Loop - { - signed char *p = amstmp; - UINT i=0, j=0; - while ((i < inputlen) && (j < tmplen)) - { - signed char ch = psrc[i++]; - if (ch == packcharacter) - { - BYTE ch2 = psrc[i++]; - if (ch2) - { - ch = psrc[i++]; - while (ch2--) - { - p[j++] = ch; - if (j >= tmplen) break; - } - } else p[j++] = packcharacter; - } else p[j++] = ch; - } - } - // Bit Unpack Loop - { - signed char *p = amstmp; - UINT bitcount = 0x80, dh; - UINT k=0; - for (UINT i=0; i> ((dh+8-count) & 7)) & 0xFF; - bitcount = ((bitcount|(bitcount<<8)) >> 1) & 0xFF; - pdest[k++] |= bl; - if (k >= dmax) - { - k = 0; - dh++; - } - } - bitcount = ((bitcount|(bitcount<<8)) >> dh) & 0xFF; - } - } - // Delta Unpack - { - signed char old = 0; - for (UINT i=0; i, - * Adam Goode (endian and char fixes for PPC) -*/ - -/////////////////////////////////////////////////////////////// -// -// DigiBooster Pro Module Loader (*.dbm) -// -// Note: this loader doesn't handle multiple songs -// -/////////////////////////////////////////////////////////////// - -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#define DBM_FILE_MAGIC 0x304d4244 -#define DBM_ID_NAME 0x454d414e -#define DBM_NAMELEN 0x2c000000 -#define DBM_ID_INFO 0x4f464e49 -#define DBM_INFOLEN 0x0a000000 -#define DBM_ID_SONG 0x474e4f53 -#define DBM_ID_INST 0x54534e49 -#define DBM_ID_VENV 0x564e4556 -#define DBM_ID_PATT 0x54544150 -#define DBM_ID_SMPL 0x4c504d53 - -#pragma pack(1) - -typedef struct DBMFILEHEADER -{ - DWORD dbm_id; // "DBM0" = 0x304d4244 - WORD trkver; // Tracker version: 02.15 - WORD reserved; - DWORD name_id; // "NAME" = 0x454d414e - DWORD name_len; // name length: always 44 - CHAR songname[44]; - DWORD info_id; // "INFO" = 0x4f464e49 - DWORD info_len; // 0x0a000000 - WORD instruments; - WORD samples; - WORD songs; - WORD patterns; - WORD channels; - DWORD song_id; // "SONG" = 0x474e4f53 - DWORD song_len; - CHAR songname2[44]; - WORD orders; -// WORD orderlist[0]; // orderlist[orders] in words -} DBMFILEHEADER; - -typedef struct DBMINSTRUMENT -{ - CHAR name[30]; - WORD sampleno; - WORD volume; - DWORD finetune; - DWORD loopstart; - DWORD looplen; - WORD panning; - WORD flags; -} DBMINSTRUMENT; - -typedef struct DBMENVELOPE -{ - WORD instrument; - BYTE flags; - BYTE numpoints; - BYTE sustain1; - BYTE loopbegin; - BYTE loopend; - BYTE sustain2; - WORD volenv[2*32]; -} DBMENVELOPE; - -typedef struct DBMPATTERN -{ - WORD rows; - DWORD packedsize; - BYTE patterndata[2]; // [packedsize] -} DBMPATTERN; - -typedef struct DBMSAMPLE -{ - DWORD flags; - DWORD samplesize; - BYTE sampledata[2]; // [samplesize] -} DBMSAMPLE; - -#pragma pack() - - -BOOL CSoundFile::ReadDBM(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - const DBMFILEHEADER *pfh = (DBMFILEHEADER *)lpStream; - DWORD dwMemPos; - UINT nOrders, nSamples, nInstruments, nPatterns; - - if ((!lpStream) || (dwMemLength <= sizeof(DBMFILEHEADER)) || (!pfh->channels) - || (pfh->dbm_id != bswapLE32(DBM_FILE_MAGIC)) || (!pfh->songs) || (pfh->song_id != bswapLE32(DBM_ID_SONG)) - || (pfh->name_id != bswapLE32(DBM_ID_NAME)) || (pfh->name_len != bswapLE32(DBM_NAMELEN)) - || (pfh->info_id != bswapLE32(DBM_ID_INFO)) || (pfh->info_len != bswapLE32(DBM_INFOLEN))) return FALSE; - dwMemPos = sizeof(DBMFILEHEADER); - nOrders = bswapBE16(pfh->orders); - if (dwMemPos + 2 * nOrders + 8*3 >= dwMemLength) return FALSE; - nInstruments = bswapBE16(pfh->instruments); - nSamples = bswapBE16(pfh->samples); - nPatterns = bswapBE16(pfh->patterns); - m_nType = MOD_TYPE_DBM; - m_nChannels = bswapBE16(pfh->channels); - if (m_nChannels < 4) m_nChannels = 4; - if (m_nChannels > 64) m_nChannels = 64; - memcpy(m_szNames[0], (pfh->songname[0]) ? pfh->songname : pfh->songname2, 32); - m_szNames[0][31] = 0; - for (UINT iOrd=0; iOrd < nOrders; iOrd++) - { - Order[iOrd] = lpStream[dwMemPos+iOrd*2+1]; - if (iOrd >= MAX_ORDERS-2) break; - } - dwMemPos += 2*nOrders; - while (dwMemPos + 10 < dwMemLength) - { - DWORD chunk_id = ((LPDWORD)(lpStream+dwMemPos))[0]; - DWORD chunk_size = bswapBE32(((LPDWORD)(lpStream+dwMemPos))[1]); - DWORD chunk_pos; - - dwMemPos += 8; - chunk_pos = dwMemPos; - if ((dwMemPos + chunk_size > dwMemLength) || (chunk_size > dwMemLength)) break; - dwMemPos += chunk_size; - // Instruments - if (chunk_id == bswapLE32(DBM_ID_INST)) - { - if (nInstruments >= MAX_INSTRUMENTS) nInstruments = MAX_INSTRUMENTS-1; - for (UINT iIns=0; iIns dwMemPos) break; - if ((penv = new INSTRUMENTHEADER) == NULL) break; - pih = (DBMINSTRUMENT *)(lpStream+chunk_pos); - nsmp = bswapBE16(pih->sampleno); - psmp = ((nsmp) && (nsmp < MAX_SAMPLES)) ? &Ins[nsmp] : NULL; - memset(penv, 0, sizeof(INSTRUMENTHEADER)); - memcpy(penv->name, pih->name, 30); - if (psmp) - { - memcpy(m_szNames[nsmp], pih->name, 30); - m_szNames[nsmp][30] = 0; - } - Headers[iIns+1] = penv; - penv->nFadeOut = 1024; // ??? - penv->nGlobalVol = 64; - penv->nPan = bswapBE16(pih->panning); - if ((penv->nPan) && (penv->nPan < 256)) - penv->dwFlags = ENV_SETPANNING; - else - penv->nPan = 128; - penv->nPPC = 5*12; - for (UINT i=0; iKeyboard[i] = nsmp; - penv->NoteMap[i] = i+1; - } - // Sample Info - if (psmp) - { - DWORD sflags = bswapBE16(pih->flags); - psmp->nVolume = bswapBE16(pih->volume) * 4; - if ((!psmp->nVolume) || (psmp->nVolume > 256)) psmp->nVolume = 256; - psmp->nGlobalVol = 64; - psmp->nC4Speed = bswapBE32(pih->finetune); - int f2t = FrequencyToTranspose(psmp->nC4Speed); - psmp->RelativeTone = f2t >> 7; - psmp->nFineTune = f2t & 0x7F; - if ((pih->looplen) && (sflags & 3)) - { - psmp->nLoopStart = bswapBE32(pih->loopstart); - psmp->nLoopEnd = psmp->nLoopStart + bswapBE32(pih->looplen); - psmp->uFlags |= CHN_LOOP; - psmp->uFlags &= ~CHN_PINGPONGLOOP; - if (sflags & 2) psmp->uFlags |= CHN_PINGPONGLOOP; - } - } - chunk_pos += sizeof(DBMINSTRUMENT); - m_nInstruments = iIns+1; - } - } else - // Volume Envelopes - if (chunk_id == bswapLE32(DBM_ID_VENV)) - { - UINT nEnvelopes = lpStream[chunk_pos+1]; - - chunk_pos += 2; - for (UINT iEnv=0; iEnv dwMemPos) break; - peh = (DBMENVELOPE *)(lpStream+chunk_pos); - nins = bswapBE16(peh->instrument); - if ((nins) && (nins < MAX_INSTRUMENTS) && (Headers[nins]) && (peh->numpoints)) - { - INSTRUMENTHEADER *penv = Headers[nins]; - - if (peh->flags & 1) penv->dwFlags |= ENV_VOLUME; - if (peh->flags & 2) penv->dwFlags |= ENV_VOLSUSTAIN; - if (peh->flags & 4) penv->dwFlags |= ENV_VOLLOOP; - penv->nVolEnv = peh->numpoints + 1; - if (penv->nVolEnv > MAX_ENVPOINTS) penv->nVolEnv = MAX_ENVPOINTS; - penv->nVolLoopStart = peh->loopbegin; - penv->nVolLoopEnd = peh->loopend; - penv->nVolSustainBegin = penv->nVolSustainEnd = peh->sustain1; - for (UINT i=0; inVolEnv; i++) - { - penv->VolPoints[i] = bswapBE16(peh->volenv[i*2]); - penv->VolEnv[i] = (BYTE)bswapBE16(peh->volenv[i*2+1]); - } - } - chunk_pos += sizeof(DBMENVELOPE); - } - } else - // Packed Pattern Data - if (chunk_id == bswapLE32(DBM_ID_PATT)) - { - if (nPatterns > MAX_PATTERNS) nPatterns = MAX_PATTERNS; - for (UINT iPat=0; iPat dwMemPos) break; - pph = (DBMPATTERN *)(lpStream+chunk_pos); - pksize = bswapBE32(pph->packedsize); - if ((chunk_pos + pksize + 6 > dwMemPos) || (pksize > dwMemPos)) break; - nRows = bswapBE16(pph->rows); - if ((nRows >= 4) && (nRows <= 256)) - { - MODCOMMAND *m = AllocatePattern(nRows, m_nChannels); - if (m) - { - LPBYTE pkdata = (LPBYTE)&pph->patterndata; - UINT row = 0; - UINT i = 0; - - PatternSize[iPat] = nRows; - Patterns[iPat] = m; - while ((i+3> 4)*12) + (note & 0x0F) + 13; - } - m[ch].note = note; - } - if (b & 0x02) m[ch].instr = pkdata[i++]; - if (b & 0x3C) - { - UINT cmd1 = 0xFF, param1 = 0, cmd2 = 0xFF, param2 = 0; - if (b & 0x04) cmd1 = (UINT)pkdata[i++]; - if (b & 0x08) param1 = pkdata[i++]; - if (b & 0x10) cmd2 = (UINT)pkdata[i++]; - if (b & 0x20) param2 = pkdata[i++]; - if (cmd1 == 0x0C) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = param1; - cmd1 = 0xFF; - } else - if (cmd2 == 0x0C) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = param2; - cmd2 = 0xFF; - } - if ((cmd1 > 0x13) || ((cmd1 >= 0x10) && (cmd2 < 0x10))) - { - cmd1 = cmd2; - param1 = param2; - cmd2 = 0xFF; - } - if (cmd1 <= 0x13) - { - m[ch].command = cmd1; - m[ch].param = param1; - ConvertModCommand(&m[ch]); - } - } - } else - { - if (b & 0x01) i++; - if (b & 0x02) i++; - if (b & 0x04) i++; - if (b & 0x08) i++; - if (b & 0x10) i++; - if (b & 0x20) i++; - } - } else - { - row++; - m += m_nChannels; - } - } - } - } - chunk_pos += 6 + pksize; - } - } else - // Reading Sample Data - if (chunk_id == bswapLE32(DBM_ID_SMPL)) - { - if (nSamples >= MAX_SAMPLES) nSamples = MAX_SAMPLES-1; - m_nSamples = nSamples; - for (UINT iSmp=1; iSmp<=nSamples; iSmp++) - { - MODINSTRUMENT *pins; - DBMSAMPLE *psh; - DWORD samplesize; - DWORD sampleflags; - - if (chunk_pos + sizeof(DBMSAMPLE) >= dwMemPos) break; - psh = (DBMSAMPLE *)(lpStream+chunk_pos); - chunk_pos += 8; - samplesize = bswapBE32(psh->samplesize); - sampleflags = bswapBE32(psh->flags); - pins = &Ins[iSmp]; - pins->nLength = samplesize; - if (sampleflags & 2) - { - pins->uFlags |= CHN_16BIT; - samplesize <<= 1; - } - if ((chunk_pos+samplesize > dwMemPos) || (samplesize > dwMemLength)) break; - if (sampleflags & 3) - { - ReadSample(pins, (pins->uFlags & CHN_16BIT) ? RS_PCM16M : RS_PCM8S, - (LPSTR)(psh->sampledata), samplesize); - } - chunk_pos += samplesize; - } - } - } - return TRUE; -} - diff --git a/jni/load_dmf.cpp b/jni/load_dmf.cpp deleted file mode 100644 index 6d83de3..0000000 --- a/jni/load_dmf.cpp +++ /dev/null @@ -1,606 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -/////////////////////////////////////////////////////// -// DMF DELUSION DIGITAL MUSIC FILEFORMAT (X-Tracker) // -/////////////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#define DMFLOG - -//#pragma warning(disable:4244) - -#pragma pack(1) - -typedef struct DMFHEADER -{ - DWORD id; // "DDMF" = 0x464d4444 - BYTE version; // 4 - CHAR trackername[8]; // "XTRACKER" - CHAR songname[30]; - CHAR composer[20]; - BYTE date[3]; -} DMFHEADER; - -typedef struct DMFINFO -{ - DWORD id; // "INFO" - DWORD infosize; -} DMFINFO; - -typedef struct DMFSEQU -{ - DWORD id; // "SEQU" - DWORD seqsize; - WORD loopstart; - WORD loopend; - WORD sequ[2]; -} DMFSEQU; - -typedef struct DMFPATT -{ - DWORD id; // "PATT" - DWORD patsize; - WORD numpat; // 1-1024 - BYTE tracks; - BYTE firstpatinfo; -} DMFPATT; - -typedef struct DMFTRACK -{ - BYTE tracks; - BYTE beat; // [hi|lo] -> hi=ticks per beat, lo=beats per measure - WORD ticks; // max 512 - DWORD jmpsize; -} DMFTRACK; - -typedef struct DMFSMPI -{ - DWORD id; - DWORD size; - BYTE samples; -} DMFSMPI; - -typedef struct DMFSAMPLE -{ - DWORD len; - DWORD loopstart; - DWORD loopend; - WORD c3speed; - BYTE volume; - BYTE flags; -} DMFSAMPLE; - -#pragma pack() - - -#ifdef DMFLOG -extern void Log(LPCSTR s, ...); -#endif - - -BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - const DMFHEADER *pfh = (DMFHEADER *)lpStream; - DMFINFO *psi; - DMFSEQU *sequ; - DWORD dwMemPos; - BYTE infobyte[32]; - BYTE smplflags[MAX_SAMPLES]; - - if ((!lpStream) || (dwMemLength < 1024)) return FALSE; - if ((pfh->id != 0x464d4444) || (!pfh->version) || (pfh->version & 0xF0)) return FALSE; - dwMemPos = 66; - memcpy(m_szNames[0], pfh->songname, 30); - m_szNames[0][30] = 0; - m_nType = MOD_TYPE_DMF; - m_nChannels = 0; -#ifdef DMFLOG - Log("DMF version %d: \"%s\": %d bytes (0x%04X)\n", pfh->version, m_szNames[0], dwMemLength, dwMemLength); -#endif - while (dwMemPos + 7 < dwMemLength) - { - DWORD id = *((LPDWORD)(lpStream+dwMemPos)); - - switch(id) - { - // "INFO" - case 0x4f464e49: - // "CMSG" - case 0x47534d43: - psi = (DMFINFO *)(lpStream+dwMemPos); - if (id == 0x47534d43) dwMemPos++; - if ((psi->infosize > dwMemLength) || (psi->infosize + dwMemPos + 8 > dwMemLength)) goto dmfexit; - if ((psi->infosize >= 8) && (!m_lpszSongComments)) - { - m_lpszSongComments = new char[psi->infosize]; // changed from CHAR - if (m_lpszSongComments) - { - for (UINT i=0; iinfosize-1; i++) - { - CHAR c = lpStream[dwMemPos+8+i]; - if ((i % 40) == 39) - m_lpszSongComments[i] = 0x0d; - else - m_lpszSongComments[i] = (c < ' ') ? ' ' : c; - } - m_lpszSongComments[psi->infosize-1] = 0; - } - } - dwMemPos += psi->infosize + 8 - 1; - break; - - // "SEQU" - case 0x55514553: - sequ = (DMFSEQU *)(lpStream+dwMemPos); - if ((sequ->seqsize >= dwMemLength) || (dwMemPos + sequ->seqsize + 12 > dwMemLength)) goto dmfexit; - { - UINT nseq = sequ->seqsize >> 1; - if (nseq >= MAX_ORDERS-1) nseq = MAX_ORDERS-1; - if (sequ->loopstart < nseq) m_nRestartPos = sequ->loopstart; - for (UINT i=0; isequ[i]; - } - dwMemPos += sequ->seqsize + 8; - break; - - // "PATT" - case 0x54544150: - if (!m_nChannels) - { - DMFPATT *patt = (DMFPATT *)(lpStream+dwMemPos); - UINT numpat; - DWORD dwPos = dwMemPos + 11; - if ((patt->patsize >= dwMemLength) || (dwMemPos + patt->patsize + 8 > dwMemLength)) goto dmfexit; - numpat = patt->numpat; - if (numpat > MAX_PATTERNS) numpat = MAX_PATTERNS; - m_nChannels = patt->tracks; - if (m_nChannels < patt->firstpatinfo) m_nChannels = patt->firstpatinfo; - if (m_nChannels > 32) m_nChannels = 32; - if (m_nChannels < 4) m_nChannels = 4; - for (UINT npat=0; npattracks, pt->ticks); - #endif - UINT tracks = pt->tracks; - if (tracks > 32) tracks = 32; - UINT ticks = pt->ticks; - if (ticks > 256) ticks = 256; - if (ticks < 16) ticks = 16; - dwPos += 8; - if ((pt->jmpsize >= dwMemLength) || (dwPos + pt->jmpsize + 4 >= dwMemLength)) break; - PatternSize[npat] = (WORD)ticks; - MODCOMMAND *m = AllocatePattern(PatternSize[npat], m_nChannels); - if (!m) goto dmfexit; - Patterns[npat] = m; - DWORD d = dwPos; - dwPos += pt->jmpsize; - UINT ttype = 1; - UINT tempo = 125; - UINT glbinfobyte = 0; - UINT pbeat = (pt->beat & 0xf0) ? pt->beat>>4 : 8; - BOOL tempochange = (pt->beat & 0xf0) ? TRUE : FALSE; - memset(infobyte, 0, sizeof(infobyte)); - for (UINT row=0; row>4; tempochange = ttype; break; - #ifdef DMFLOG - default: if (info) Log("GLB: %02X.%02X\n", info, infoval); - #endif - } - } else - { - glbinfobyte--; - } - // Parse channels - for (UINT i=0; i>2; - } - // Effect 1 - if (info & 0x08) - { - BYTE efx = lpStream[d++]; - BYTE eval = lpStream[d++]; - switch(efx) - { - // 1: Key Off - case 1: if (!cmd.note) cmd.note = 0xFE; break; - // 2: Set Loop - // 4: Sample Delay - case 4: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break; - // 5: Retrig - case 5: if (eval&0xe0) { cmd.command = CMD_RETRIG; cmd.param = (eval>>5); } break; - // 6: Offset - case 6: cmd.command = CMD_OFFSET; cmd.param = eval; break; - #ifdef DMFLOG - default: Log("FX1: %02X.%02X\n", efx, eval); - #endif - } - } - // Effect 2 - if (info & 0x04) - { - BYTE efx = lpStream[d++]; - BYTE eval = lpStream[d++]; - switch(efx) - { - // 1: Finetune - case 1: if (eval&0xf0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>4)|0x20; } break; - // 2: Note Delay - case 2: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break; - // 3: Arpeggio - case 3: if (eval) { cmd.command = CMD_ARPEGGIO; cmd.param = eval; } break; - // 4: Portamento Up - case 4: cmd.command = CMD_PORTAMENTOUP; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break; - // 5: Portamento Down - case 5: cmd.command = CMD_PORTAMENTODOWN; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break; - // 6: Tone Portamento - case 6: cmd.command = CMD_TONEPORTAMENTO; cmd.param = eval; break; - // 8: Vibrato - case 8: cmd.command = CMD_VIBRATO; cmd.param = eval; break; - // 12: Note cut - case 12: if (eval & 0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xc0; } - else if (!cmd.note) { cmd.note = 0xfe; } break; - #ifdef DMFLOG - default: Log("FX2: %02X.%02X\n", efx, eval); - #endif - } - } - // Effect 3 - if (info & 0x02) - { - BYTE efx = lpStream[d++]; - BYTE eval = lpStream[d++]; - switch(efx) - { - // 1: Vol Slide Up - case 1: if (eval == 0xff) break; - eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_VOLUMESLIDE; cmd.param = eval<<4; break; - // 2: Vol Slide Down - case 2: if (eval == 0xff) break; - eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_VOLUMESLIDE; cmd.param = eval; break; - // 7: Set Pan - case 7: if (!cmd.volcmd) { cmd.volcmd = VOLCMD_PANNING; cmd.vol = (eval+3)>>2; } - else { cmd.command = CMD_PANNING8; cmd.param = eval; } break; - // 8: Pan Slide Left - case 8: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_PANNINGSLIDE; cmd.param = eval<<4; break; - // 9: Pan Slide Right - case 9: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_PANNINGSLIDE; cmd.param = eval; break; - #ifdef DMFLOG - default: Log("FX3: %02X.%02X\n", efx, eval); - #endif - - } - } - // Store effect - if (i < m_nChannels) p[i] = cmd; - if (d > dwPos) - { - #ifdef DMFLOG - Log("Unexpected EOP: row=%d\n", row); - #endif - break; - } - } else - { - infobyte[i]--; - } - - // Find free channel for tempo change - if (tempochange) - { - tempochange = FALSE; - UINT speed=6, modtempo=tempo; - UINT rpm = ((ttype) && (pbeat)) ? tempo*pbeat : (tempo+1)*15; - for (speed=30; speed>1; speed--) - { - modtempo = rpm*speed/24; - if (modtempo <= 200) break; - if ((speed < 6) && (modtempo < 256)) break; - } - #ifdef DMFLOG - Log("Tempo change: ttype=%d pbeat=%d tempo=%3d -> speed=%d tempo=%d\n", - ttype, pbeat, tempo, speed, modtempo); - #endif - for (UINT ich=0; ich= 32) && (modtempo < 256)) - { - p[ich].command = CMD_TEMPO; - p[ich].param = (BYTE)modtempo; - modtempo = 0; - } else - { - break; - } - } - } - if (d >= dwPos) break; - } - #ifdef DMFLOG - Log(" %d/%d bytes remaining\n", dwPos-d, pt->jmpsize); - #endif - if (dwPos + 8 >= dwMemLength) break; - } - dwMemPos += patt->patsize + 8; - } - break; - - // "SMPI": Sample Info - case 0x49504d53: - { - DMFSMPI *pds = (DMFSMPI *)(lpStream+dwMemPos); - if (pds->size <= dwMemLength - dwMemPos) - { - DWORD dwPos = dwMemPos + 9; - m_nSamples = pds->samples; - if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; - for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) - { - UINT namelen = lpStream[dwPos]; - smplflags[iSmp] = 0; - if (dwPos+namelen+1+sizeof(DMFSAMPLE) > dwMemPos+pds->size+8) break; - if (namelen) - { - UINT rlen = (namelen < 32) ? namelen : 31; - memcpy(m_szNames[iSmp], lpStream+dwPos+1, rlen); - m_szNames[iSmp][rlen] = 0; - } - dwPos += namelen + 1; - DMFSAMPLE *psh = (DMFSAMPLE *)(lpStream+dwPos); - MODINSTRUMENT *psmp = &Ins[iSmp]; - psmp->nLength = psh->len; - psmp->nLoopStart = psh->loopstart; - psmp->nLoopEnd = psh->loopend; - psmp->nC4Speed = psh->c3speed; - psmp->nGlobalVol = 64; - psmp->nVolume = (psh->volume) ? ((WORD)psh->volume)+1 : (WORD)256; - psmp->uFlags = (psh->flags & 2) ? CHN_16BIT : 0; - if (psmp->uFlags & CHN_16BIT) psmp->nLength >>= 1; - if (psh->flags & 1) psmp->uFlags |= CHN_LOOP; - smplflags[iSmp] = psh->flags; - dwPos += (pfh->version < 8) ? 22 : 30; - #ifdef DMFLOG - Log("SMPI %d/%d: len=%d flags=0x%02X\n", iSmp, m_nSamples, psmp->nLength, psh->flags); - #endif - } - } - dwMemPos += pds->size + 8; - } - break; - - // "SMPD": Sample Data - case 0x44504d53: - { - DWORD dwPos = dwMemPos + 8; - UINT ismpd = 0; - for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) - { - ismpd++; - DWORD pksize; - if (dwPos + 4 >= dwMemLength) - { - #ifdef DMFLOG - Log("Unexpected EOF at sample %d/%d! (pos=%d)\n", iSmp, m_nSamples, dwPos); - #endif - break; - } - pksize = *((LPDWORD)(lpStream+dwPos)); - #ifdef DMFLOG - Log("sample %d: pos=0x%X pksize=%d ", iSmp, dwPos, pksize); - Log("len=%d flags=0x%X [%08X]\n", Ins[iSmp].nLength, smplflags[ismpd], *((LPDWORD)(lpStream+dwPos+4))); - #endif - dwPos += 4; - if (pksize > dwMemLength - dwPos) - { - #ifdef DMFLOG - Log("WARNING: pksize=%d, but only %d bytes left\n", pksize, dwMemLength-dwPos); - #endif - pksize = dwMemLength - dwPos; - } - if ((pksize) && (iSmp <= m_nSamples)) - { - UINT flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; - if (smplflags[ismpd] & 4) flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_DMF16 : RS_DMF8; - ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwPos), pksize); - } - dwPos += pksize; - } - dwMemPos = dwPos; - } - break; - - // "ENDE": end of file - case 0x45444e45: - goto dmfexit; - - // Unrecognized id, or "ENDE" field - default: - dwMemPos += 4; - break; - } - } -dmfexit: - if (!m_nChannels) - { - if (!m_nSamples) - { - m_nType = MOD_TYPE_NONE; - return FALSE; - } - m_nChannels = 4; - } - return TRUE; -} - - -/////////////////////////////////////////////////////////////////////// -// DMF Compression - -#pragma pack(1) - -typedef struct DMF_HNODE -{ - short int left, right; - BYTE value; -} DMF_HNODE; - -typedef struct DMF_HTREE -{ - LPBYTE ibuf, ibufmax; - DWORD bitbuf; - UINT bitnum; - UINT lastnode, nodecount; - DMF_HNODE nodes[256]; -} DMF_HTREE; - -#pragma pack() - - -// DMF Huffman ReadBits -BYTE DMFReadBits(DMF_HTREE *tree, UINT nbits) -//------------------------------------------- -{ - BYTE x = 0, bitv = 1; - while (nbits--) - { - if (tree->bitnum) - { - tree->bitnum--; - } else - { - tree->bitbuf = (tree->ibuf < tree->ibufmax) ? *(tree->ibuf++) : 0; - tree->bitnum = 7; - } - if (tree->bitbuf & 1) x |= bitv; - bitv <<= 1; - tree->bitbuf >>= 1; - } - return x; -} - -// -// tree: [8-bit value][12-bit index][12-bit index] = 32-bit -// - -void DMFNewNode(DMF_HTREE *tree) -//------------------------------ -{ - BYTE isleft, isright; - UINT actnode; - - actnode = tree->nodecount; - if (actnode > 255) return; - tree->nodes[actnode].value = DMFReadBits(tree, 7); - isleft = DMFReadBits(tree, 1); - isright = DMFReadBits(tree, 1); - actnode = tree->lastnode; - if (actnode > 255) return; - tree->nodecount++; - tree->lastnode = tree->nodecount; - if (isleft) - { - tree->nodes[actnode].left = tree->lastnode; - DMFNewNode(tree); - } else - { - tree->nodes[actnode].left = -1; - } - tree->lastnode = tree->nodecount; - if (isright) - { - tree->nodes[actnode].right = tree->lastnode; - DMFNewNode(tree); - } else - { - tree->nodes[actnode].right = -1; - } -} - - -int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen) -//---------------------------------------------------------------------- -{ - DMF_HTREE tree; - UINT actnode; - BYTE value, sign, delta = 0; - - memset(&tree, 0, sizeof(tree)); - tree.ibuf = ibuf; - tree.ibufmax = ibufmax; - DMFNewNode(&tree); - value = 0; - for (UINT i=0; i 255) break; - delta = tree.nodes[actnode].value; - if ((tree.ibuf >= tree.ibufmax) && (!tree.bitnum)) break; - } while ((tree.nodes[actnode].left >= 0) && (tree.nodes[actnode].right >= 0)); - if (sign) delta ^= 0xFF; - value += delta; - psample[i] = (i) ? value : 0; - } -#ifdef DMFLOG -// Log("DMFUnpack: %d remaining bytes\n", tree.ibufmax-tree.ibuf); -#endif - return tree.ibuf - ibuf; -} - - diff --git a/jni/load_dsm.cpp b/jni/load_dsm.cpp deleted file mode 100644 index 03819a5..0000000 --- a/jni/load_dsm.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -////////////////////////////////////////////// -// DSIK Internal Format (DSM) module loader // -////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -#pragma pack(1) - -#define DSMID_RIFF 0x46464952 // "RIFF" -#define DSMID_DSMF 0x464d5344 // "DSMF" -#define DSMID_SONG 0x474e4f53 // "SONG" -#define DSMID_INST 0x54534e49 // "INST" -#define DSMID_PATT 0x54544150 // "PATT" - - -typedef struct DSMNOTE -{ - BYTE note,ins,vol,cmd,inf; -} DSMNOTE; - - -typedef struct DSMINST -{ - DWORD id_INST; - DWORD inst_len; - CHAR filename[13]; - BYTE flags; - BYTE flags2; - BYTE volume; - DWORD length; - DWORD loopstart; - DWORD loopend; - DWORD reserved1; - WORD c2spd; - WORD reserved2; - CHAR samplename[28]; -} DSMINST; - - -typedef struct DSMFILEHEADER -{ - DWORD id_RIFF; // "RIFF" - DWORD riff_len; - DWORD id_DSMF; // "DSMF" - DWORD id_SONG; // "SONG" - DWORD song_len; -} DSMFILEHEADER; - - -typedef struct DSMSONG -{ - CHAR songname[28]; - WORD reserved1; - WORD flags; - DWORD reserved2; - WORD numord; - WORD numsmp; - WORD numpat; - WORD numtrk; - BYTE globalvol; - BYTE mastervol; - BYTE speed; - BYTE bpm; - BYTE panpos[16]; - BYTE orders[128]; -} DSMSONG; - -typedef struct DSMPATT -{ - DWORD id_PATT; - DWORD patt_len; - BYTE dummy1; - BYTE dummy2; -} DSMPATT; - -#pragma pack() - - -BOOL CSoundFile::ReadDSM(LPCBYTE lpStream, DWORD dwMemLength) -//----------------------------------------------------------- -{ - DSMFILEHEADER *pfh = (DSMFILEHEADER *)lpStream; - DSMSONG *psong; - DWORD dwMemPos; - UINT nPat, nSmp; - - if ((!lpStream) || (dwMemLength < 1024) || (pfh->id_RIFF != DSMID_RIFF) - || (pfh->riff_len + 8 > dwMemLength) || (pfh->riff_len < 1024) - || (pfh->id_DSMF != DSMID_DSMF) || (pfh->id_SONG != DSMID_SONG) - || (pfh->song_len > dwMemLength)) return FALSE; - psong = (DSMSONG *)(lpStream + sizeof(DSMFILEHEADER)); - dwMemPos = sizeof(DSMFILEHEADER) + pfh->song_len; - m_nType = MOD_TYPE_DSM; - m_nChannels = psong->numtrk; - if (m_nChannels < 4) m_nChannels = 4; - if (m_nChannels > 16) m_nChannels = 16; - m_nSamples = psong->numsmp; - if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES - 1; - m_nDefaultSpeed = psong->speed; - m_nDefaultTempo = psong->bpm; - m_nDefaultGlobalVolume = psong->globalvol << 2; - if ((!m_nDefaultGlobalVolume) || (m_nDefaultGlobalVolume > 256)) m_nDefaultGlobalVolume = 256; - m_nSongPreAmp = psong->mastervol & 0x7F; - for (UINT iOrd=0; iOrdnumord) ? psong->orders[iOrd] : 0xFF); - } - for (UINT iPan=0; iPan<16; iPan++) - { - ChnSettings[iPan].nPan = 0x80; - if (psong->panpos[iPan] <= 0x80) - { - ChnSettings[iPan].nPan = psong->panpos[iPan] << 1; - } - } - memcpy(m_szNames[0], psong->songname, 28); - nPat = 0; - nSmp = 1; - while (dwMemPos < dwMemLength - 8) - { - DSMPATT *ppatt = (DSMPATT *)(lpStream + dwMemPos); - DSMINST *pins = (DSMINST *)(lpStream+dwMemPos); - // Reading Patterns - if (ppatt->id_PATT == DSMID_PATT) - { - dwMemPos += 8; - if (dwMemPos + ppatt->patt_len >= dwMemLength) break; - DWORD dwPos = dwMemPos; - dwMemPos += ppatt->patt_len; - MODCOMMAND *m = AllocatePattern(64, m_nChannels); - if (!m) break; - PatternSize[nPat] = 64; - Patterns[nPat] = m; - UINT row = 0; - while ((row < 64) && (dwPos + 2 <= dwMemPos)) - { - UINT flag = lpStream[dwPos++]; - if (flag) - { - UINT ch = (flag & 0x0F) % m_nChannels; - if (flag & 0x80) - { - UINT note = lpStream[dwPos++]; - if (note) - { - if (note <= 12*9) note += 12; - m[ch].note = (BYTE)note; - } - } - if (flag & 0x40) - { - m[ch].instr = lpStream[dwPos++]; - } - if (flag & 0x20) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = lpStream[dwPos++]; - } - if (flag & 0x10) - { - UINT command = lpStream[dwPos++]; - UINT param = lpStream[dwPos++]; - switch(command) - { - // 4-bit Panning - case 0x08: - switch(param & 0xF0) - { - case 0x00: param <<= 4; break; - case 0x10: command = 0x0A; param = (param & 0x0F) << 4; break; - case 0x20: command = 0x0E; param = (param & 0x0F) | 0xA0; break; - case 0x30: command = 0x0E; param = (param & 0x0F) | 0x10; break; - case 0x40: command = 0x0E; param = (param & 0x0F) | 0x20; break; - default: command = 0; - } - break; - // Portamentos - case 0x11: - case 0x12: - command &= 0x0F; - break; - // 3D Sound (?) - case 0x13: - command = 'X' - 55; - param = 0x91; - break; - default: - // Volume + Offset (?) - command = ((command & 0xF0) == 0x20) ? 0x09 : 0; - } - m[ch].command = (BYTE)command; - m[ch].param = (BYTE)param; - if (command) ConvertModCommand(&m[ch]); - } - } else - { - m += m_nChannels; - row++; - } - } - nPat++; - } else - // Reading Samples - if ((nSmp <= m_nSamples) && (pins->id_INST == DSMID_INST)) - { - if (dwMemPos + pins->inst_len >= dwMemLength - 8) break; - DWORD dwPos = dwMemPos + sizeof(DSMINST); - dwMemPos += 8 + pins->inst_len; - memcpy(m_szNames[nSmp], pins->samplename, 28); - MODINSTRUMENT *psmp = &Ins[nSmp]; - memcpy(psmp->name, pins->filename, 13); - psmp->nGlobalVol = 64; - psmp->nC4Speed = pins->c2spd; - psmp->uFlags = (WORD)((pins->flags & 1) ? CHN_LOOP : 0); - psmp->nLength = pins->length; - psmp->nLoopStart = pins->loopstart; - psmp->nLoopEnd = pins->loopend; - psmp->nVolume = (WORD)(pins->volume << 2); - if (psmp->nVolume > 256) psmp->nVolume = 256; - UINT smptype = (pins->flags & 2) ? RS_PCM8S : RS_PCM8U; - ReadSample(psmp, smptype, (LPCSTR)(lpStream+dwPos), dwMemLength - dwPos); - nSmp++; - } else - { - break; - } - } - return TRUE; -} - diff --git a/jni/load_far.cpp b/jni/load_far.cpp deleted file mode 100644 index b070a24..0000000 --- a/jni/load_far.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -//////////////////////////////////////// -// Farandole (FAR) module loader // -//////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#define FARFILEMAGIC 0xFE524146 // "FAR" - -#pragma pack(1) - -typedef struct FARHEADER1 -{ - DWORD id; // file magic FAR= - CHAR songname[40]; // songname - CHAR magic2[3]; // 13,10,26 - WORD headerlen; // remaining length of header in bytes - BYTE version; // 0xD1 - BYTE onoff[16]; - BYTE edit1[9]; - BYTE speed; - BYTE panning[16]; - BYTE edit2[4]; - WORD stlen; -} FARHEADER1; - -typedef struct FARHEADER2 -{ - BYTE orders[256]; - BYTE numpat; - BYTE snglen; - BYTE loopto; - WORD patsiz[256]; -} FARHEADER2; - -typedef struct FARSAMPLE -{ - CHAR samplename[32]; - DWORD length; - BYTE finetune; - BYTE volume; - DWORD reppos; - DWORD repend; - BYTE type; - BYTE loop; -} FARSAMPLE; - -#pragma pack() - - -BOOL CSoundFile::ReadFAR(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - const FARHEADER1 *pmh1 = (const FARHEADER1 *)lpStream; - const FARHEADER2 *pmh2; - DWORD dwMemPos = sizeof(FARHEADER1); - UINT headerlen, stlen; - BYTE samplemap[8]; - - if ((!lpStream) || (dwMemLength < 1024) || (bswapLE32(pmh1->id) != FARFILEMAGIC) - || (pmh1->magic2[0] != 13) || (pmh1->magic2[1] != 10) || (pmh1->magic2[2] != 26)) return FALSE; - headerlen = bswapLE16(pmh1->headerlen); - stlen = bswapLE16( pmh1->stlen ); - if ((headerlen >= dwMemLength) || (dwMemPos + stlen + sizeof(FARHEADER2) >= dwMemLength)) return FALSE; - // Globals - m_nType = MOD_TYPE_FAR; - m_nChannels = 16; - m_nInstruments = 0; - m_nSamples = 0; - m_nSongPreAmp = 0x20; - m_nDefaultSpeed = pmh1->speed; - m_nDefaultTempo = 80; - m_nDefaultGlobalVolume = 256; - - memcpy(m_szNames[0], pmh1->songname, 32); - // Channel Setting - for (UINT nchpan=0; nchpan<16; nchpan++) - { - ChnSettings[nchpan].dwFlags = 0; - ChnSettings[nchpan].nPan = ((pmh1->panning[nchpan] & 0x0F) << 4) + 8; - ChnSettings[nchpan].nVolume = 64; - } - // Reading comment - if (stlen) - { - UINT szLen = stlen; - if (szLen > dwMemLength - dwMemPos) szLen = dwMemLength - dwMemPos; - if ((m_lpszSongComments = new char[szLen + 1]) != NULL) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, szLen); - m_lpszSongComments[szLen] = 0; - } - dwMemPos += stlen; - } - // Reading orders - if (sizeof(FARHEADER2) > dwMemLength - dwMemPos) return TRUE; - pmh2 = (const FARHEADER2 *)(lpStream + dwMemPos); - dwMemPos += sizeof(FARHEADER2); - if (dwMemPos >= dwMemLength) return TRUE; - for (UINT iorder=0; iordersnglen) ? pmh2->orders[iorder] : 0xFF; - } - m_nRestartPos = pmh2->loopto; - // Reading Patterns - dwMemPos += headerlen - (869 + stlen); - if (dwMemPos >= dwMemLength) return TRUE; - - // end byteswap of pattern data - - WORD *patsiz = (WORD *)pmh2->patsiz; - for (UINT ipat=0; ipat<256; ipat++) if (patsiz[ipat]) - { - UINT patlen = bswapLE16(patsiz[ipat]); - if ((ipat >= MAX_PATTERNS) || (patlen < 2)) - { - dwMemPos += patlen; - continue; - } - if (dwMemPos + patlen >= dwMemLength) return TRUE; - UINT rows = (patlen - 2) >> 6; - if (!rows) - { - dwMemPos += patlen; - continue; - } - if (rows > 256) rows = 256; - if (rows < 16) rows = 16; - PatternSize[ipat] = rows; - if ((Patterns[ipat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; - MODCOMMAND *m = Patterns[ipat]; - UINT patbrk = lpStream[dwMemPos]; - const BYTE *p = lpStream + dwMemPos + 2; - UINT max = rows*16*4; - if (max > patlen-2) max = patlen-2; - for (UINT len=0; leninstr = ins + 1; - m->note = note + 36; - } - if (vol & 0x0F) - { - m->volcmd = VOLCMD_VOLUME; - m->vol = (vol & 0x0F) << 2; - if (m->vol <= 4) m->vol = 0; - } - switch(eff & 0xF0) - { - // 1.x: Portamento Up - case 0x10: - m->command = CMD_PORTAMENTOUP; - m->param = eff & 0x0F; - break; - // 2.x: Portamento Down - case 0x20: - m->command = CMD_PORTAMENTODOWN; - m->param = eff & 0x0F; - break; - // 3.x: Tone-Portamento - case 0x30: - m->command = CMD_TONEPORTAMENTO; - m->param = (eff & 0x0F) << 2; - break; - // 4.x: Retrigger - case 0x40: - m->command = CMD_RETRIG; - m->param = 6 / (1+(eff&0x0F)) + 1; - break; - // 5.x: Set Vibrato Depth - case 0x50: - m->command = CMD_VIBRATO; - m->param = (eff & 0x0F); - break; - // 6.x: Set Vibrato Speed - case 0x60: - m->command = CMD_VIBRATO; - m->param = (eff & 0x0F) << 4; - break; - // 7.x: Vol Slide Up - case 0x70: - m->command = CMD_VOLUMESLIDE; - m->param = (eff & 0x0F) << 4; - break; - // 8.x: Vol Slide Down - case 0x80: - m->command = CMD_VOLUMESLIDE; - m->param = (eff & 0x0F); - break; - // A.x: Port to vol - case 0xA0: - m->volcmd = VOLCMD_VOLUME; - m->vol = ((eff & 0x0F) << 2) + 4; - break; - // B.x: Set Balance - case 0xB0: - m->command = CMD_PANNING8; - m->param = (eff & 0x0F) << 4; - break; - // F.x: Set Speed - case 0xF0: - m->command = CMD_SPEED; - m->param = eff & 0x0F; - break; - default: - if ((patbrk) && (patbrk+1 == (len >> 6)) && (patbrk+1 != rows-1)) - { - m->command = CMD_PATTERNBREAK; - patbrk = 0; - } - } - } - dwMemPos += patlen; - } - // Reading samples - if (dwMemPos + 8 >= dwMemLength) return TRUE; - memcpy(samplemap, lpStream+dwMemPos, 8); - dwMemPos += 8; - MODINSTRUMENT *pins = &Ins[1]; - for (UINT ismp=0; ismp<64; ismp++, pins++) if (samplemap[ismp >> 3] & (1 << (ismp & 7))) - { - if (dwMemPos + sizeof(FARSAMPLE) > dwMemLength) return TRUE; - const FARSAMPLE *pfs = reinterpret_cast(lpStream + dwMemPos); - dwMemPos += sizeof(FARSAMPLE); - m_nSamples = ismp + 1; - memcpy(m_szNames[ismp+1], pfs->samplename, 32); - const DWORD length = bswapLE32( pfs->length ) ; /* endian fix - Toad */ - pins->nLength = length ; - pins->nLoopStart = bswapLE32(pfs->reppos) ; - pins->nLoopEnd = bswapLE32(pfs->repend) ; - pins->nFineTune = 0; - pins->nC4Speed = 8363*2; - pins->nGlobalVol = 64; - pins->nVolume = pfs->volume << 4; - pins->uFlags = 0; - if ((pins->nLength > 3) && (dwMemPos + 4 < dwMemLength)) - { - if (pfs->type & 1) - { - pins->uFlags |= CHN_16BIT; - pins->nLength >>= 1; - pins->nLoopStart >>= 1; - pins->nLoopEnd >>= 1; - } - if ((pfs->loop & 8) && (pins->nLoopEnd > 4)) pins->uFlags |= CHN_LOOP; - ReadSample(pins, (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S, - (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos); - } - dwMemPos += length; - } - return TRUE; -} - diff --git a/jni/load_it.cpp b/jni/load_it.cpp deleted file mode 100644 index a3cc890..0000000 --- a/jni/load_it.cpp +++ /dev/null @@ -1,1516 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque , - * Adam Goode (Endian and char fixes for PPC) - * Marco Trillo (Endian fixes for SaveIT, XM->IT Sample Converter) - * -*/ - -#include "stdafx.h" -#include "sndfile.h" -#include "it_defs.h" - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif - -BYTE autovibit2xm[8] = -{ 0, 3, 1, 4, 2, 0, 0, 0 }; - -BYTE autovibxm2it[8] = -{ 0, 2, 4, 1, 3, 0, 0, 0 }; - -////////////////////////////////////////////////////////// -// Impulse Tracker IT file support - -// for conversion of XM samples -extern WORD XMPeriodTable[96+8]; -extern UINT XMLinearTable[768]; - -static inline UINT ConvertVolParam(UINT value) -//-------------------------------------------- -{ - return (value > 9) ? 9 : value; -} - - -BOOL CSoundFile::ITInstrToMPT(const void *p, INSTRUMENTHEADER *penv, UINT trkvers) -//-------------------------------------------------------------------------------- -{ - if (trkvers < 0x0200) - { - const ITOLDINSTRUMENT *pis = (const ITOLDINSTRUMENT *)p; - memcpy(penv->name, pis->name, 26); - memcpy(penv->filename, pis->filename, 12); - penv->nFadeOut = bswapLE16(pis->fadeout) << 6; - penv->nGlobalVol = 64; - for (UINT j=0; jkeyboard[j*2]; - UINT ins = pis->keyboard[j*2+1]; - if (ins < MAX_SAMPLES) penv->Keyboard[j] = ins; - if (note < 128) penv->NoteMap[j] = note+1; - else if (note >= 0xFE) penv->NoteMap[j] = note; - } - if (pis->flags & 0x01) penv->dwFlags |= ENV_VOLUME; - if (pis->flags & 0x02) penv->dwFlags |= ENV_VOLLOOP; - if (pis->flags & 0x04) penv->dwFlags |= ENV_VOLSUSTAIN; - penv->nVolLoopStart = pis->vls; - penv->nVolLoopEnd = pis->vle; - penv->nVolSustainBegin = pis->sls; - penv->nVolSustainEnd = pis->sle; - penv->nVolEnv = 25; - for (UINT ev=0; ev<25; ev++) - { - if ((penv->VolPoints[ev] = pis->nodes[ev*2]) == 0xFF) - { - penv->nVolEnv = ev; - break; - } - penv->VolEnv[ev] = pis->nodes[ev*2+1]; - } - penv->nNNA = pis->nna; - penv->nDCT = pis->dnc; - penv->nPan = 0x80; - } else - { - const ITINSTRUMENT *pis = (const ITINSTRUMENT *)p; - memcpy(penv->name, pis->name, 26); - memcpy(penv->filename, pis->filename, 12); - penv->nMidiProgram = pis->mpr; - penv->nMidiChannel = pis->mch; - penv->wMidiBank = bswapLE16(pis->mbank); - penv->nFadeOut = bswapLE16(pis->fadeout) << 5; - penv->nGlobalVol = pis->gbv >> 1; - if (penv->nGlobalVol > 64) penv->nGlobalVol = 64; - for (UINT j=0; jkeyboard[j*2]; - UINT ins = pis->keyboard[j*2+1]; - if (ins < MAX_SAMPLES) penv->Keyboard[j] = ins; - if (note < 128) penv->NoteMap[j] = note+1; - else if (note >= 0xFE) penv->NoteMap[j] = note; - } - // Volume Envelope - if (pis->volenv.flags & 1) penv->dwFlags |= ENV_VOLUME; - if (pis->volenv.flags & 2) penv->dwFlags |= ENV_VOLLOOP; - if (pis->volenv.flags & 4) penv->dwFlags |= ENV_VOLSUSTAIN; - if (pis->volenv.flags & 8) penv->dwFlags |= ENV_VOLCARRY; - penv->nVolEnv = pis->volenv.num; - if (penv->nVolEnv > 25) penv->nVolEnv = 25; - - penv->nVolLoopStart = pis->volenv.lpb; - penv->nVolLoopEnd = pis->volenv.lpe; - penv->nVolSustainBegin = pis->volenv.slb; - penv->nVolSustainEnd = pis->volenv.sle; - // Panning Envelope - if (pis->panenv.flags & 1) penv->dwFlags |= ENV_PANNING; - if (pis->panenv.flags & 2) penv->dwFlags |= ENV_PANLOOP; - if (pis->panenv.flags & 4) penv->dwFlags |= ENV_PANSUSTAIN; - if (pis->panenv.flags & 8) penv->dwFlags |= ENV_PANCARRY; - penv->nPanEnv = pis->panenv.num; - if (penv->nPanEnv > 25) penv->nPanEnv = 25; - penv->nPanLoopStart = pis->panenv.lpb; - penv->nPanLoopEnd = pis->panenv.lpe; - penv->nPanSustainBegin = pis->panenv.slb; - penv->nPanSustainEnd = pis->panenv.sle; - // Pitch Envelope - if (pis->pitchenv.flags & 1) penv->dwFlags |= ENV_PITCH; - if (pis->pitchenv.flags & 2) penv->dwFlags |= ENV_PITCHLOOP; - if (pis->pitchenv.flags & 4) penv->dwFlags |= ENV_PITCHSUSTAIN; - if (pis->pitchenv.flags & 8) penv->dwFlags |= ENV_PITCHCARRY; - if (pis->pitchenv.flags & 0x80) penv->dwFlags |= ENV_FILTER; - penv->nPitchEnv = pis->pitchenv.num; - if (penv->nPitchEnv > 25) penv->nPitchEnv = 25; - penv->nPitchLoopStart = pis->pitchenv.lpb; - penv->nPitchLoopEnd = pis->pitchenv.lpe; - penv->nPitchSustainBegin = pis->pitchenv.slb; - penv->nPitchSustainEnd = pis->pitchenv.sle; - // Envelopes Data - for (UINT ev=0; ev<25; ev++) - { - penv->VolEnv[ev] = pis->volenv.data[ev*3]; - penv->VolPoints[ev] = (pis->volenv.data[ev*3+2] << 8) | (pis->volenv.data[ev*3+1]); - penv->PanEnv[ev] = pis->panenv.data[ev*3] + 32; - penv->PanPoints[ev] = (pis->panenv.data[ev*3+2] << 8) | (pis->panenv.data[ev*3+1]); - penv->PitchEnv[ev] = pis->pitchenv.data[ev*3] + 32; - penv->PitchPoints[ev] = (pis->pitchenv.data[ev*3+2] << 8) | (pis->pitchenv.data[ev*3+1]); - } - penv->nNNA = pis->nna; - penv->nDCT = pis->dct; - penv->nDNA = pis->dca; - penv->nPPS = pis->pps; - penv->nPPC = pis->ppc; - penv->nIFC = pis->ifc; - penv->nIFR = pis->ifr; - penv->nVolSwing = pis->rv; - penv->nPanSwing = pis->rp; - penv->nPan = (pis->dfp & 0x7F) << 2; - if (penv->nPan > 256) penv->nPan = 128; - if (pis->dfp < 0x80) penv->dwFlags |= ENV_SETPANNING; - } - if ((penv->nVolLoopStart >= 25) || (penv->nVolLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP; - if ((penv->nVolSustainBegin >= 25) || (penv->nVolSustainEnd >= 25)) penv->dwFlags &= ~ENV_VOLSUSTAIN; - return TRUE; -} - - -BOOL CSoundFile::ReadIT(const BYTE *lpStream, DWORD dwMemLength) -//-------------------------------------------------------------- -{ - DWORD dwMemPos = sizeof(ITFILEHEADER); - DWORD inspos[MAX_INSTRUMENTS]; - DWORD smppos[MAX_SAMPLES]; - DWORD patpos[MAX_PATTERNS]; - BYTE chnmask[64], channels_used[64]; - MODCOMMAND lastvalue[64]; - - if ((!lpStream) || (dwMemLength < sizeof(ITFILEHEADER))) return FALSE; - ITFILEHEADER pifh = *(ITFILEHEADER *)lpStream; - - pifh.id = bswapLE32(pifh.id); - pifh.reserved1 = bswapLE16(pifh.reserved1); - pifh.ordnum = bswapLE16(pifh.ordnum); - pifh.insnum = bswapLE16(pifh.insnum); - pifh.smpnum = bswapLE16(pifh.smpnum); - pifh.patnum = bswapLE16(pifh.patnum); - pifh.cwtv = bswapLE16(pifh.cwtv); - pifh.cmwt = bswapLE16(pifh.cmwt); - pifh.flags = bswapLE16(pifh.flags); - pifh.special = bswapLE16(pifh.special); - pifh.msglength = bswapLE16(pifh.msglength); - pifh.msgoffset = bswapLE32(pifh.msgoffset); - pifh.reserved2 = bswapLE32(pifh.reserved2); - - if ((pifh.id != 0x4D504D49) || (pifh.insnum >= MAX_INSTRUMENTS) - || (!pifh.smpnum) || (pifh.smpnum >= MAX_INSTRUMENTS) || (!pifh.ordnum)) return FALSE; - if (dwMemPos + pifh.ordnum + pifh.insnum*4 - + pifh.smpnum*4 + pifh.patnum*4 > dwMemLength) return FALSE; - m_nType = MOD_TYPE_IT; - if (pifh.flags & 0x08) m_dwSongFlags |= SONG_LINEARSLIDES; - if (pifh.flags & 0x10) m_dwSongFlags |= SONG_ITOLDEFFECTS; - if (pifh.flags & 0x20) m_dwSongFlags |= SONG_ITCOMPATMODE; - if (pifh.flags & 0x80) m_dwSongFlags |= SONG_EMBEDMIDICFG; - if (pifh.flags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE; - memcpy(m_szNames[0], pifh.songname, 26); - m_szNames[0][26] = 0; - // Global Volume - if (pifh.globalvol) - { - m_nDefaultGlobalVolume = pifh.globalvol << 1; - if (!m_nDefaultGlobalVolume) m_nDefaultGlobalVolume = 256; - if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256; - } - if (pifh.speed) m_nDefaultSpeed = pifh.speed; - if (pifh.tempo) m_nDefaultTempo = pifh.tempo; - m_nSongPreAmp = pifh.mv & 0x7F; - // Reading Channels Pan Positions - for (int ipan=0; ipan<64; ipan++) if (pifh.chnpan[ipan] != 0xFF) - { - ChnSettings[ipan].nVolume = pifh.chnvol[ipan]; - ChnSettings[ipan].nPan = 128; - if (pifh.chnpan[ipan] & 0x80) ChnSettings[ipan].dwFlags |= CHN_MUTE; - UINT n = pifh.chnpan[ipan] & 0x7F; - if (n <= 64) ChnSettings[ipan].nPan = n << 2; - if (n == 100) ChnSettings[ipan].dwFlags |= CHN_SURROUND; - } - if (m_nChannels < 4) m_nChannels = 4; - // Reading Song Message - if ((pifh.special & 0x01) && (pifh.msglength) && (pifh.msglength <= dwMemLength) && (pifh.msgoffset < dwMemLength - pifh.msglength)) - { - m_lpszSongComments = new char[pifh.msglength+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+pifh.msgoffset, pifh.msglength); - m_lpszSongComments[pifh.msglength] = 0; - } - } - // Reading orders - UINT nordsize = pifh.ordnum; - if (nordsize > MAX_ORDERS) nordsize = MAX_ORDERS; - memcpy(Order, lpStream+dwMemPos, nordsize); - dwMemPos += pifh.ordnum; - // Reading Instrument Offsets - memset(inspos, 0, sizeof(inspos)); - UINT inspossize = pifh.insnum; - if (inspossize > MAX_INSTRUMENTS) inspossize = MAX_INSTRUMENTS; - inspossize <<= 2; - memcpy(inspos, lpStream+dwMemPos, inspossize); - for (UINT j=0; j < (inspossize>>2); j++) - { - inspos[j] = bswapLE32(inspos[j]); - } - dwMemPos += pifh.insnum * 4; - // Reading Samples Offsets - memset(smppos, 0, sizeof(smppos)); - UINT smppossize = pifh.smpnum; - if (smppossize > MAX_SAMPLES) smppossize = MAX_SAMPLES; - smppossize <<= 2; - memcpy(smppos, lpStream+dwMemPos, smppossize); - for (UINT j=0; j < (smppossize>>2); j++) - { - smppos[j] = bswapLE32(smppos[j]); - } - dwMemPos += pifh.smpnum * 4; - // Reading Patterns Offsets - memset(patpos, 0, sizeof(patpos)); - UINT patpossize = pifh.patnum; - if (patpossize > MAX_PATTERNS) patpossize = MAX_PATTERNS; - patpossize <<= 2; - memcpy(patpos, lpStream+dwMemPos, patpossize); - for (UINT j=0; j < (patpossize>>2); j++) - { - patpos[j] = bswapLE32(patpos[j]); - } - dwMemPos += pifh.patnum * 4; - // Reading IT Extra Info - if (dwMemPos + 2 < dwMemLength) - { - UINT nflt = bswapLE16(*((WORD *)(lpStream + dwMemPos))); - dwMemPos += 2; - if (dwMemPos + nflt * 8 < dwMemLength) dwMemPos += nflt * 8; - } - // Reading Midi Output & Macros - if (m_dwSongFlags & SONG_EMBEDMIDICFG) - { - if (dwMemPos + sizeof(MODMIDICFG) < dwMemLength) - { - memcpy(&m_MidiCfg, lpStream+dwMemPos, sizeof(MODMIDICFG)); - dwMemPos += sizeof(MODMIDICFG); - } - } - // Read pattern names: "PNAM" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50)) - { - UINT len = bswapLE32(*((DWORD *)(lpStream+dwMemPos+4))); - dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME)) - { - m_lpszPatternNames = new char[len]; - if (m_lpszPatternNames) - { - m_nPatternNames = len / MAX_PATTERNNAME; - memcpy(m_lpszPatternNames, lpStream+dwMemPos, len); - } - dwMemPos += len; - } - } - // 4-channels minimum - m_nChannels = 4; - // Read channel names: "CNAM" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43)) - { - UINT len = bswapLE32(*((DWORD *)(lpStream+dwMemPos+4))); - dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= 64*MAX_CHANNELNAME)) - { - UINT n = len / MAX_CHANNELNAME; - if (n > m_nChannels) m_nChannels = n; - for (UINT i=0; i MAX_PATTERNS) npatterns = MAX_PATTERNS; - for (UINT patchk=0; patchk= dwMemLength - 4)) continue; - UINT len = bswapLE16(*((WORD *)(lpStream+patpos[patchk]))); - UINT rows = bswapLE16(*((WORD *)(lpStream+patpos[patchk]+2))); - if ((rows < 4) || (rows > 256)) continue; - if (8+len > dwMemLength || patpos[patchk] > dwMemLength - (8+len)) continue; - UINT i = 0; - const BYTE *p = lpStream+patpos[patchk]+8; - UINT nrow = 0; - while (nrow= len) break; - BYTE b = p[i++]; - if (!b) - { - nrow++; - continue; - } - UINT ch = b & 0x7F; - if (ch) ch = (ch - 1) & 0x3F; - if (b & 0x80) - { - if (i >= len) break; - chnmask[ch] = p[i++]; - } - // Channel used - if (chnmask[ch] & 0x0F) - { - if ((ch >= m_nChannels) && (ch < 64)) m_nChannels = ch+1; - } - // Note - if (chnmask[ch] & 1) i++; - // Instrument - if (chnmask[ch] & 2) i++; - // Volume - if (chnmask[ch] & 4) i++; - // Effect - if (chnmask[ch] & 8) i += 2; - if (i >= len) break; - } - } - // Reading Instruments - m_nInstruments = 0; - if (pifh.flags & 0x04) m_nInstruments = pifh.insnum; - if (m_nInstruments >= MAX_INSTRUMENTS) m_nInstruments = MAX_INSTRUMENTS-1; - for (UINT nins=0; nins 0) && (inspos[nins] < dwMemLength - sizeof(ITOLDINSTRUMENT))) - { - INSTRUMENTHEADER *penv = new INSTRUMENTHEADER; - if (!penv) continue; - Headers[nins+1] = penv; - memset(penv, 0, sizeof(INSTRUMENTHEADER)); - ITInstrToMPT(lpStream + inspos[nins], penv, pifh.cmwt); - } - } - // Reading Samples - m_nSamples = pifh.smpnum; - if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; - for (UINT nsmp=0; nsmpname, pis.filename, 12); - pins->uFlags = 0; - pins->nLength = 0; - pins->nLoopStart = pis.loopbegin; - pins->nLoopEnd = pis.loopend; - pins->nSustainStart = pis.susloopbegin; - pins->nSustainEnd = pis.susloopend; - pins->nC4Speed = pis.C5Speed; - if (!pins->nC4Speed) pins->nC4Speed = 8363; - if (pis.C5Speed < 256) pins->nC4Speed = 256; - pins->nVolume = pis.vol << 2; - if (pins->nVolume > 256) pins->nVolume = 256; - pins->nGlobalVol = pis.gvl; - if (pins->nGlobalVol > 64) pins->nGlobalVol = 64; - if (pis.flags & 0x10) pins->uFlags |= CHN_LOOP; - if (pis.flags & 0x20) pins->uFlags |= CHN_SUSTAINLOOP; - if (pis.flags & 0x40) pins->uFlags |= CHN_PINGPONGLOOP; - if (pis.flags & 0x80) pins->uFlags |= CHN_PINGPONGSUSTAIN; - pins->nPan = (pis.dfp & 0x7F) << 2; - if (pins->nPan > 256) pins->nPan = 256; - if (pis.dfp & 0x80) pins->uFlags |= CHN_PANNING; - pins->nVibType = autovibit2xm[pis.vit & 7]; - pins->nVibRate = pis.vis; - pins->nVibDepth = pis.vid & 0x7F; - pins->nVibSweep = (pis.vir + 3) / 4; - if ((pis.samplepointer) && (pis.samplepointer < dwMemLength) && (pis.length)) - { - pins->nLength = pis.length; - if (pins->nLength > MAX_SAMPLE_LENGTH) pins->nLength = MAX_SAMPLE_LENGTH; - UINT flags = (pis.cvt & 1) ? RS_PCM8S : RS_PCM8U; - if (pis.flags & 2) - { - flags += 5; - if (pis.flags & 4) flags |= RSF_STEREO; - pins->uFlags |= CHN_16BIT; - // IT 2.14 16-bit packed sample ? - if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT21516 : RS_IT21416; - } else - { - if (pis.flags & 4) flags |= RSF_STEREO; - if (pis.cvt == 0xFF) flags = RS_ADPCM4; else - // IT 2.14 8-bit packed sample ? - if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT2158 : RS_IT2148; - } - ReadSample(&Ins[nsmp+1], flags, (LPSTR)(lpStream+pis.samplepointer), dwMemLength - pis.samplepointer); - } - } - memcpy(m_szNames[nsmp+1], pis.name, 26); - } - // Reading Patterns - for (UINT npat=0; npat= dwMemLength - 4)) - { - PatternSize[npat] = 64; - Patterns[npat] = AllocatePattern(64, m_nChannels); - continue; - } - - UINT len = bswapLE16(*((WORD *)(lpStream+patpos[npat]))); - UINT rows = bswapLE16(*((WORD *)(lpStream+patpos[npat]+2))); - if ((rows < 4) || (rows > 256)) continue; - if (8+len > dwMemLength || patpos[npat] > dwMemLength - (8+len)) continue; - PatternSize[npat] = rows; - if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) continue; - memset(lastvalue, 0, sizeof(lastvalue)); - memset(chnmask, 0, sizeof(chnmask)); - MODCOMMAND *m = Patterns[npat]; - UINT i = 0; - const BYTE *p = lpStream+patpos[npat]+8; - UINT nrow = 0; - while (nrow= len) break; - BYTE b = p[i++]; - if (!b) - { - nrow++; - m+=m_nChannels; - continue; - } - UINT ch = b & 0x7F; - if (ch) ch = (ch - 1) & 0x3F; - if (b & 0x80) - { - if (i >= len) break; - chnmask[ch] = p[i++]; - } - if ((chnmask[ch] & 0x10) && (ch < m_nChannels)) - { - m[ch].note = lastvalue[ch].note; - } - if ((chnmask[ch] & 0x20) && (ch < m_nChannels)) - { - m[ch].instr = lastvalue[ch].instr; - } - if ((chnmask[ch] & 0x40) && (ch < m_nChannels)) - { - m[ch].volcmd = lastvalue[ch].volcmd; - m[ch].vol = lastvalue[ch].vol; - } - if ((chnmask[ch] & 0x80) && (ch < m_nChannels)) - { - m[ch].command = lastvalue[ch].command; - m[ch].param = lastvalue[ch].param; - } - if (chnmask[ch] & 1) // Note - { - if (i >= len) break; - UINT note = p[i++]; - if (ch < m_nChannels) - { - if (note < 0x80) note++; - m[ch].note = note; - lastvalue[ch].note = note; - channels_used[ch] = TRUE; - } - } - if (chnmask[ch] & 2) - { - if (i >= len) break; - UINT instr = p[i++]; - if (ch < m_nChannels) - { - m[ch].instr = instr; - lastvalue[ch].instr = instr; - } - } - if (chnmask[ch] & 4) - { - if (i >= len) break; - UINT vol = p[i++]; - if (ch < m_nChannels) - { - // 0-64: Set Volume - if (vol <= 64) { m[ch].volcmd = VOLCMD_VOLUME; m[ch].vol = vol; } else - // 128-192: Set Panning - if ((vol >= 128) && (vol <= 192)) { m[ch].volcmd = VOLCMD_PANNING; m[ch].vol = vol - 128; } else - // 65-74: Fine Volume Up - if (vol < 75) { m[ch].volcmd = VOLCMD_FINEVOLUP; m[ch].vol = vol - 65; } else - // 75-84: Fine Volume Down - if (vol < 85) { m[ch].volcmd = VOLCMD_FINEVOLDOWN; m[ch].vol = vol - 75; } else - // 85-94: Volume Slide Up - if (vol < 95) { m[ch].volcmd = VOLCMD_VOLSLIDEUP; m[ch].vol = vol - 85; } else - // 95-104: Volume Slide Down - if (vol < 105) { m[ch].volcmd = VOLCMD_VOLSLIDEDOWN; m[ch].vol = vol - 95; } else - // 105-114: Pitch Slide Up - if (vol < 115) { m[ch].volcmd = VOLCMD_PORTADOWN; m[ch].vol = vol - 105; } else - // 115-124: Pitch Slide Down - if (vol < 125) { m[ch].volcmd = VOLCMD_PORTAUP; m[ch].vol = vol - 115; } else - // 193-202: Portamento To - if ((vol >= 193) && (vol <= 202)) { m[ch].volcmd = VOLCMD_TONEPORTAMENTO; m[ch].vol = vol - 193; } else - // 203-212: Vibrato - if ((vol >= 203) && (vol <= 212)) { m[ch].volcmd = VOLCMD_VIBRATOSPEED; m[ch].vol = vol - 203; } - lastvalue[ch].volcmd = m[ch].volcmd; - lastvalue[ch].vol = m[ch].vol; - } - } - // Reading command/param - if (chnmask[ch] & 8) - { - if (i > len - 2) break; - UINT cmd = p[i++]; - UINT param = p[i++]; - if (ch < m_nChannels) - { - if (cmd) - { - m[ch].command = cmd; - m[ch].param = param; - S3MConvert(&m[ch], TRUE); - lastvalue[ch].command = m[ch].command; - lastvalue[ch].param = m[ch].param; - } - } - } - } - } - for (UINT ncu=0; ncu=m_nChannels) - { - ChnSettings[ncu].nVolume = 64; - ChnSettings[ncu].dwFlags &= ~CHN_MUTE; - } - } - m_nMinPeriod = 8; - m_nMaxPeriod = 0xF000; - return TRUE; -} - - -#ifndef MODPLUG_NO_FILESAVE -//#define SAVEITTIMESTAMP -#ifdef _MSC_VER -#pragma warning(disable:4100) -#endif - -BOOL CSoundFile::SaveIT(LPCSTR lpszFileName, UINT nPacking) -//--------------------------------------------------------- -{ - DWORD dwPatNamLen, dwChnNamLen; - ITFILEHEADER header, writeheader; - ITINSTRUMENT iti, writeiti; - ITSAMPLESTRUCT itss; - BYTE smpcount[MAX_SAMPLES]; - DWORD inspos[MAX_INSTRUMENTS]; - DWORD patpos[MAX_PATTERNS]; - DWORD smppos[MAX_SAMPLES]; - DWORD dwPos = 0, dwHdrPos = 0, dwExtra = 2; - WORD patinfo[4]; - BYTE chnmask[64]; - BYTE buf[512]; - MODCOMMAND lastvalue[64]; - FILE *f; - - - if ((!lpszFileName) || ((f = fopen(lpszFileName, "wb")) == NULL)) return FALSE; - memset(inspos, 0, sizeof(inspos)); - memset(patpos, 0, sizeof(patpos)); - memset(smppos, 0, sizeof(smppos)); - // Writing Header - memset(&header, 0, sizeof(header)); - dwPatNamLen = 0; - dwChnNamLen = 0; - header.id = 0x4D504D49; // IMPM - lstrcpyn((char *)header.songname, m_szNames[0], 27); - header.reserved1 = 0x1004; - header.ordnum = 0; - while ((header.ordnum < MAX_ORDERS) && (Order[header.ordnum] < 0xFF)) header.ordnum++; - if (header.ordnum < MAX_ORDERS) Order[header.ordnum++] = 0xFF; - header.insnum = m_nInstruments; - header.smpnum = m_nSamples; - header.patnum = MAX_PATTERNS; - while ((header.patnum > 0) && (!Patterns[header.patnum-1])) header.patnum--; - header.cwtv = 0x217; - header.cmwt = 0x200; - header.flags = 0x0001; - header.special = 0x0006; - if (m_nInstruments) header.flags |= 0x04; - if (m_dwSongFlags & SONG_LINEARSLIDES) header.flags |= 0x08; - if (m_dwSongFlags & SONG_ITOLDEFFECTS) header.flags |= 0x10; - if (m_dwSongFlags & SONG_ITCOMPATMODE) header.flags |= 0x20; - if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000; - header.globalvol = m_nDefaultGlobalVolume >> 1; - header.mv = m_nSongPreAmp; - // clip song pre-amp values (between 0x20 and 0x7f) - if (header.mv < 0x20) header.mv = 0x20; - if (header.mv > 0x7F) header.mv = 0x7F; - header.speed = m_nDefaultSpeed; - header.tempo = m_nDefaultTempo; - header.sep = m_nStereoSeparation; - dwHdrPos = sizeof(header) + header.ordnum; - // Channel Pan and Volume - memset(header.chnpan, 0xFF, 64); - memset(header.chnvol, 64, 64); - for (UINT ich=0; ich> 2; - if (ChnSettings[ich].dwFlags & CHN_SURROUND) header.chnpan[ich] = 100; - header.chnvol[ich] = ChnSettings[ich].nVolume; - if (ChnSettings[ich].dwFlags & CHN_MUTE) header.chnpan[ich] |= 0x80; - if (ChnSettings[ich].szName[0]) - { - dwChnNamLen = (ich+1) * MAX_CHANNELNAME; - } - } - if (dwChnNamLen) dwExtra += dwChnNamLen + 8; -#ifdef SAVEITTIMESTAMP - dwExtra += 8; // Time Stamp -#endif - if (m_dwSongFlags & SONG_EMBEDMIDICFG) - { - header.flags |= 0x80; - header.special |= 0x08; - dwExtra += sizeof(MODMIDICFG); - } - // Pattern Names - if ((m_nPatternNames) && (m_lpszPatternNames)) - { - dwPatNamLen = m_nPatternNames * MAX_PATTERNNAME; - while ((dwPatNamLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwPatNamLen-MAX_PATTERNNAME])) dwPatNamLen -= MAX_PATTERNNAME; - if (dwPatNamLen < MAX_PATTERNNAME) dwPatNamLen = 0; - if (dwPatNamLen) dwExtra += dwPatNamLen + 8; - } - // Mix Plugins - dwExtra += SaveMixPlugins(NULL, TRUE); - // Comments - if (m_lpszSongComments) - { - header.special |= 1; - header.msglength = strlen(m_lpszSongComments)+1; - header.msgoffset = dwHdrPos + dwExtra + header.insnum*4 + header.patnum*4 + header.smpnum*4; - } - // Write file header - memcpy(&writeheader, &header, sizeof(header)); - - // Byteswap header information - writeheader.id = bswapLE32(writeheader.id); - writeheader.reserved1 = bswapLE16(writeheader.reserved1); - writeheader.ordnum = bswapLE16(writeheader.ordnum); - writeheader.insnum = bswapLE16(writeheader.insnum); - writeheader.smpnum = bswapLE16(writeheader.smpnum); - writeheader.patnum = bswapLE16(writeheader.patnum); - writeheader.cwtv = bswapLE16(writeheader.cwtv); - writeheader.cmwt = bswapLE16(writeheader.cmwt); - writeheader.flags = bswapLE16(writeheader.flags); - writeheader.special = bswapLE16(writeheader.special); - writeheader.msglength = bswapLE16(writeheader.msglength); - writeheader.msgoffset = bswapLE32(writeheader.msgoffset); - writeheader.reserved2 = bswapLE32(writeheader.reserved2); - - fwrite(&writeheader, 1, sizeof(writeheader), f); - - fwrite(Order, 1, header.ordnum, f); - if (header.insnum) fwrite(inspos, 4, header.insnum, f); - if (header.smpnum) fwrite(smppos, 4, header.smpnum, f); - if (header.patnum) fwrite(patpos, 4, header.patnum, f); - // Writing editor history information - { -#ifdef SAVEITTIMESTAMP - SYSTEMTIME systime; - FILETIME filetime; - WORD timestamp[4]; - WORD nInfoEx = 1; - memset(timestamp, 0, sizeof(timestamp)); - fwrite(&nInfoEx, 1, 2, f); - GetSystemTime(&systime); - SystemTimeToFileTime(&systime, &filetime); - FileTimeToDosDateTime(&filetime, ×tamp[0], ×tamp[1]); - fwrite(timestamp, 1, 8, f); -#else - WORD nInfoEx = 0; - fwrite(&nInfoEx, 1, 2, f); -#endif - } - // Writing midi cfg - if (header.flags & 0x80) - { - fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); - } - // Writing pattern names - if (dwPatNamLen) - { - DWORD d = bswapLE32(0x4d414e50); - UINT len= bswapLE32(dwPatNamLen); - fwrite(&d, 1, 4, f); - fwrite(&len, 1, 4, f); - fwrite(m_lpszPatternNames, 1, dwPatNamLen, f); - } - // Writing channel Names - if (dwChnNamLen) - { - DWORD d = bswapLE32(0x4d414e43); - UINT len= bswapLE32(dwChnNamLen); - fwrite(&d, 1, 4, f); - fwrite(&len, 1, 4, f); - UINT nChnNames = dwChnNamLen / MAX_CHANNELNAME; - for (UINT inam=0; inamfilename, 12); - memcpy(iti.name, penv->name, 26); - iti.mbank = penv->wMidiBank; - iti.mpr = penv->nMidiProgram; - iti.mch = penv->nMidiChannel; - iti.nna = penv->nNNA; - iti.dct = penv->nDCT; - iti.dca = penv->nDNA; - iti.fadeout = penv->nFadeOut >> 5; - iti.pps = penv->nPPS; - iti.ppc = penv->nPPC; - iti.gbv = (BYTE)(penv->nGlobalVol << 1); - iti.dfp = (BYTE)penv->nPan >> 2; - if (!(penv->dwFlags & ENV_SETPANNING)) iti.dfp |= 0x80; - iti.rv = penv->nVolSwing; - iti.rp = penv->nPanSwing; - iti.ifc = penv->nIFC; - iti.ifr = penv->nIFR; - iti.nos = 0; - for (UINT i=0; iKeyboard[i] < MAX_SAMPLES) - { - UINT smp = penv->Keyboard[i]; - if ((smp) && (!smpcount[smp])) - { - smpcount[smp] = 1; - iti.nos++; - } - iti.keyboard[i*2] = penv->NoteMap[i] - 1; - iti.keyboard[i*2+1] = smp; - } - // Writing Volume envelope - if (penv->dwFlags & ENV_VOLUME) iti.volenv.flags |= 0x01; - if (penv->dwFlags & ENV_VOLLOOP) iti.volenv.flags |= 0x02; - if (penv->dwFlags & ENV_VOLSUSTAIN) iti.volenv.flags |= 0x04; - if (penv->dwFlags & ENV_VOLCARRY) iti.volenv.flags |= 0x08; - iti.volenv.num = (BYTE)penv->nVolEnv; - iti.volenv.lpb = (BYTE)penv->nVolLoopStart; - iti.volenv.lpe = (BYTE)penv->nVolLoopEnd; - iti.volenv.slb = penv->nVolSustainBegin; - iti.volenv.sle = penv->nVolSustainEnd; - // Writing Panning envelope - if (penv->dwFlags & ENV_PANNING) iti.panenv.flags |= 0x01; - if (penv->dwFlags & ENV_PANLOOP) iti.panenv.flags |= 0x02; - if (penv->dwFlags & ENV_PANSUSTAIN) iti.panenv.flags |= 0x04; - if (penv->dwFlags & ENV_PANCARRY) iti.panenv.flags |= 0x08; - iti.panenv.num = (BYTE)penv->nPanEnv; - iti.panenv.lpb = (BYTE)penv->nPanLoopStart; - iti.panenv.lpe = (BYTE)penv->nPanLoopEnd; - iti.panenv.slb = penv->nPanSustainBegin; - iti.panenv.sle = penv->nPanSustainEnd; - // Writing Pitch Envelope - if (penv->dwFlags & ENV_PITCH) iti.pitchenv.flags |= 0x01; - if (penv->dwFlags & ENV_PITCHLOOP) iti.pitchenv.flags |= 0x02; - if (penv->dwFlags & ENV_PITCHSUSTAIN) iti.pitchenv.flags |= 0x04; - if (penv->dwFlags & ENV_PITCHCARRY) iti.pitchenv.flags |= 0x08; - if (penv->dwFlags & ENV_FILTER) iti.pitchenv.flags |= 0x80; - iti.pitchenv.num = (BYTE)penv->nPitchEnv; - iti.pitchenv.lpb = (BYTE)penv->nPitchLoopStart; - iti.pitchenv.lpe = (BYTE)penv->nPitchLoopEnd; - iti.pitchenv.slb = (BYTE)penv->nPitchSustainBegin; - iti.pitchenv.sle = (BYTE)penv->nPitchSustainEnd; - // Writing Envelopes data - for (UINT ev=0; ev<25; ev++) - { - iti.volenv.data[ev*3] = penv->VolEnv[ev]; - iti.volenv.data[ev*3+1] = penv->VolPoints[ev] & 0xFF; - iti.volenv.data[ev*3+2] = penv->VolPoints[ev] >> 8; - iti.panenv.data[ev*3] = penv->PanEnv[ev] - 32; - iti.panenv.data[ev*3+1] = penv->PanPoints[ev] & 0xFF; - iti.panenv.data[ev*3+2] = penv->PanPoints[ev] >> 8; - iti.pitchenv.data[ev*3] = penv->PitchEnv[ev] - 32; - iti.pitchenv.data[ev*3+1] = penv->PitchPoints[ev] & 0xFF; - iti.pitchenv.data[ev*3+2] = penv->PitchPoints[ev] >> 8; - } - } else - // Save Empty Instrument - { - for (UINT i=0; icommand; - UINT param = m->param; - UINT vol = 0xFF; - UINT note = m->note; - if (note) b |= 1; - if ((note) && (note < 0x80)) note--; // 0xfe->0x80 --Toad - if (m->instr) b |= 2; - if (m->volcmd) - { - UINT volcmd = m->volcmd; - switch(volcmd) - { - case VOLCMD_VOLUME: vol = m->vol; if (vol > 64) vol = 64; break; - case VOLCMD_PANNING: vol = m->vol + 128; if (vol > 192) vol = 192; break; - case VOLCMD_VOLSLIDEUP: vol = 85 + ConvertVolParam(m->vol); break; - case VOLCMD_VOLSLIDEDOWN: vol = 95 + ConvertVolParam(m->vol); break; - case VOLCMD_FINEVOLUP: vol = 65 + ConvertVolParam(m->vol); break; - case VOLCMD_FINEVOLDOWN: vol = 75 + ConvertVolParam(m->vol); break; - case VOLCMD_VIBRATOSPEED: vol = 203 + ConvertVolParam(m->vol); break; - case VOLCMD_VIBRATO: vol = 203; break; - case VOLCMD_TONEPORTAMENTO: vol = 193 + ConvertVolParam(m->vol); break; - case VOLCMD_PORTADOWN: vol = 105 + ConvertVolParam(m->vol); break; - case VOLCMD_PORTAUP: vol = 115 + ConvertVolParam(m->vol); break; - default: vol = 0xFF; - } - } - if (vol != 0xFF) b |= 4; - if (command) - { - S3MSaveConvert(&command, ¶m, TRUE); - if (command) b |= 8; - } - // Packing information - if (b) - { - // Same note ? - if (b & 1) - { - if ((note == lastvalue[ch].note) && (lastvalue[ch].volcmd & 1)) - { - b &= ~1; - b |= 0x10; - } else - { - lastvalue[ch].note = note; - lastvalue[ch].volcmd |= 1; - } - } - // Same instrument ? - if (b & 2) - { - if ((m->instr == lastvalue[ch].instr) && (lastvalue[ch].volcmd & 2)) - { - b &= ~2; - b |= 0x20; - } else - { - lastvalue[ch].instr = m->instr; - lastvalue[ch].volcmd |= 2; - } - } - // Same volume column byte ? - if (b & 4) - { - if ((vol == lastvalue[ch].vol) && (lastvalue[ch].volcmd & 4)) - { - b &= ~4; - b |= 0x40; - } else - { - lastvalue[ch].vol = vol; - lastvalue[ch].volcmd |= 4; - } - } - // Same command / param ? - if (b & 8) - { - if ((command == lastvalue[ch].command) && (param == lastvalue[ch].param) && (lastvalue[ch].volcmd & 8)) - { - b &= ~8; - b |= 0x80; - } else - { - lastvalue[ch].command = command; - lastvalue[ch].param = param; - lastvalue[ch].volcmd |= 8; - } - } - if (b != chnmask[ch]) - { - chnmask[ch] = b; - buf[len++] = (ch+1) | 0x80; - buf[len++] = b; - } else - { - buf[len++] = ch+1; - } - if (b & 1) buf[len++] = note; - if (b & 2) buf[len++] = m->instr; - if (b & 4) buf[len++] = vol; - if (b & 8) - { - buf[len++] = command; - buf[len++] = param; - } - } - } - buf[len++] = 0; - dwPos += len; - patinfo[0] += len; - fwrite(buf, 1, len, f); - } - fseek(f, dwPatPos, SEEK_SET); - patinfo[0] = bswapLE16(patinfo[0]); // byteswap -- Toad - fwrite(patinfo, 8, 1, f); - fseek(f, dwPos, SEEK_SET); - } - // Writing Sample Data - for (UINT nsmp=1; nsmp<=header.smpnum; nsmp++) - { - MODINSTRUMENT *psmp = &Ins[nsmp]; - memset(&itss, 0, sizeof(itss)); - memcpy(itss.filename, psmp->name, 12); - memcpy(itss.name, m_szNames[nsmp], 26); - itss.id = 0x53504D49; - itss.gvl = (BYTE)psmp->nGlobalVol; - if (m_nInstruments) - { - for (UINT iu=1; iu<=m_nInstruments; iu++) if (Headers[iu]) - { - INSTRUMENTHEADER *penv = Headers[iu]; - for (UINT ju=0; ju<128; ju++) if (penv->Keyboard[ju] == nsmp) - { - itss.flags = 0x01; - break; - } - } - } else - { - itss.flags = 0x01; - } - if (psmp->uFlags & CHN_LOOP) itss.flags |= 0x10; - if (psmp->uFlags & CHN_SUSTAINLOOP) itss.flags |= 0x20; - if (psmp->uFlags & CHN_PINGPONGLOOP) itss.flags |= 0x40; - if (psmp->uFlags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80; - itss.C5Speed = psmp->nC4Speed; - if (!itss.C5Speed) // if no C5Speed assume it is XM Sample - { - UINT period; - - /** - * C5 note => number 61, but in XM samples: - * RealNote = Note + RelativeTone - */ - period = GetPeriodFromNote(61+psmp->RelativeTone, psmp->nFineTune, 0); - - if (period) - itss.C5Speed = GetFreqFromPeriod(period, 0, 0); - /** - * If it didn`t work, it may not be a XM file; - * so put the default C5Speed, 8363Hz. - */ - if (!itss.C5Speed) itss.C5Speed = 8363; - } - - itss.length = psmp->nLength; - itss.loopbegin = psmp->nLoopStart; - itss.loopend = psmp->nLoopEnd; - itss.susloopbegin = psmp->nSustainStart; - itss.susloopend = psmp->nSustainEnd; - itss.vol = psmp->nVolume >> 2; - itss.dfp = psmp->nPan >> 2; - itss.vit = autovibxm2it[psmp->nVibType & 7]; - itss.vis = psmp->nVibRate; - itss.vid = psmp->nVibDepth; - itss.vir = (psmp->nVibSweep < 64) ? psmp->nVibSweep * 4 : 255; - if (psmp->uFlags & CHN_PANNING) itss.dfp |= 0x80; - if ((psmp->pSample) && (psmp->nLength)) itss.cvt = 0x01; - UINT flags = RS_PCM8S; -#ifndef NO_PACKING - if (nPacking) - { - if ((!(psmp->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample((char *)psmp->pSample, psmp->nLength, nPacking))) - { - flags = RS_ADPCM4; - itss.cvt = 0xFF; - } - } else -#endif // NO_PACKING - { - if (psmp->uFlags & CHN_STEREO) - { - flags = RS_STPCM8S; - itss.flags |= 0x04; - } - if (psmp->uFlags & CHN_16BIT) - { - itss.flags |= 0x02; - flags = (psmp->uFlags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S; - } - } - itss.samplepointer = dwPos; - fseek(f, smppos[nsmp-1], SEEK_SET); - - itss.id = bswapLE32(itss.id); - itss.length = bswapLE32(itss.length); - itss.loopbegin = bswapLE32(itss.loopbegin); - itss.loopend = bswapLE32(itss.loopend); - itss.C5Speed = bswapLE32(itss.C5Speed); - itss.susloopbegin = bswapLE32(itss.susloopbegin); - itss.susloopend = bswapLE32(itss.susloopend); - itss.samplepointer = bswapLE32(itss.samplepointer); - - fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f); - fseek(f, dwPos, SEEK_SET); - if ((psmp->pSample) && (psmp->nLength)) - { - dwPos += WriteSample(f, psmp, flags); - } - } - // Updating offsets - fseek(f, dwHdrPos, SEEK_SET); - - /* Now we can byteswap them ;-) */ - UINT WW; - UINT WX; - WX = (UINT)header.insnum; - WX <<= 2; - for (WW=0; WW < (WX>>2); WW++) - inspos[WW] = bswapLE32(inspos[WW]); - - WX = (UINT)header.smpnum; - WX <<= 2; - for (WW=0; WW < (WX>>2); WW++) - smppos[WW] = bswapLE32(smppos[WW]); - - WX=(UINT)header.patnum; - WX <<= 2; - for (WW=0; WW < (WX>>2); WW++) - patpos[WW] = bswapLE32(patpos[WW]); - - if (header.insnum) fwrite(inspos, 4, header.insnum, f); - if (header.smpnum) fwrite(smppos, 4, header.smpnum, f); - if (header.patnum) fwrite(patpos, 4, header.patnum, f); - fclose(f); - return TRUE; -} - -#ifdef _MSC_VER -//#pragma warning(default:4100) -#endif -#endif // MODPLUG_NO_FILESAVE - -////////////////////////////////////////////////////////////////////////////// -// IT 2.14 compression - -DWORD ITReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n) -//----------------------------------------------------------------- -{ - DWORD retval = 0; - UINT i = n; - - if (n > 0) - { - do - { - if (!bitnum) - { - bitbuf = *ibuf++; - bitnum = 8; - } - retval >>= 1; - retval |= bitbuf << 31; - bitbuf >>= 1; - bitnum--; - i--; - } while (i); - i = n; - } - return (retval >> (32-i)); -} - -#define IT215_SUPPORT -void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215) -//------------------------------------------------------------------------------------------- -{ - signed char *pDst = pSample; - LPBYTE pSrc = lpMemFile; - DWORD wHdr = 0; - DWORD wCount = 0; - DWORD bitbuf = 0; - UINT bitnum = 0; - BYTE bLeft = 0, bTemp = 0, bTemp2 = 0; - - while (dwLen) - { - if (!wCount) - { - wCount = 0x8000; - wHdr = bswapLE16(*((LPWORD)pSrc)); - pSrc += 2; - bLeft = 9; - bTemp = bTemp2 = 0; - bitbuf = bitnum = 0; - } - DWORD d = wCount; - if (d > dwLen) d = dwLen; - // Unpacking - DWORD dwPos = 0; - do - { - WORD wBits = (WORD)ITReadBits(bitbuf, bitnum, pSrc, bLeft); - if (bLeft < 7) - { - DWORD i = 1 << (bLeft-1); - DWORD j = wBits & 0xFFFF; - if (i != j) goto UnpackByte; - wBits = (WORD)(ITReadBits(bitbuf, bitnum, pSrc, 3) + 1) & 0xFF; - bLeft = ((BYTE)wBits < bLeft) ? (BYTE)wBits : (BYTE)((wBits+1) & 0xFF); - goto Next; - } - if (bLeft < 9) - { - WORD i = (0xFF >> (9 - bLeft)) + 4; - WORD j = i - 8; - if ((wBits <= j) || (wBits > i)) goto UnpackByte; - wBits -= j; - bLeft = ((BYTE)(wBits & 0xFF) < bLeft) ? (BYTE)(wBits & 0xFF) : (BYTE)((wBits+1) & 0xFF); - goto Next; - } - if (bLeft >= 10) goto SkipByte; - if (wBits >= 256) - { - bLeft = (BYTE)(wBits + 1) & 0xFF; - goto Next; - } - UnpackByte: - if (bLeft < 8) - { - BYTE shift = 8 - bLeft; - signed char c = (signed char)(wBits << shift); - c >>= shift; - wBits = (WORD)c; - } - wBits += bTemp; - bTemp = (BYTE)wBits; - bTemp2 += bTemp; -#ifdef IT215_SUPPORT - pDst[dwPos] = (b215) ? bTemp2 : bTemp; -#else - pDst[dwPos] = bTemp; -#endif - SkipByte: - dwPos++; - Next: - if (pSrc >= lpMemFile+dwMemLength+1) return; - } while (dwPos < d); - // Move On - wCount -= d; - dwLen -= d; - pDst += d; - } -} - - -void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215) -//-------------------------------------------------------------------------------------------- -{ - signed short *pDst = (signed short *)pSample; - LPBYTE pSrc = lpMemFile; - DWORD wHdr = 0; - DWORD wCount = 0; - DWORD bitbuf = 0; - UINT bitnum = 0; - BYTE bLeft = 0; - signed short wTemp = 0, wTemp2 = 0; - - while (dwLen) - { - if (!wCount) - { - wCount = 0x4000; - wHdr = bswapLE16(*((LPWORD)pSrc)); - pSrc += 2; - bLeft = 17; - wTemp = wTemp2 = 0; - bitbuf = bitnum = 0; - } - DWORD d = wCount; - if (d > dwLen) d = dwLen; - // Unpacking - DWORD dwPos = 0; - do - { - DWORD dwBits = ITReadBits(bitbuf, bitnum, pSrc, bLeft); - if (bLeft < 7) - { - DWORD i = 1 << (bLeft-1); - DWORD j = dwBits; - if (i != j) goto UnpackByte; - dwBits = ITReadBits(bitbuf, bitnum, pSrc, 4) + 1; - bLeft = ((BYTE)(dwBits & 0xFF) < bLeft) ? (BYTE)(dwBits & 0xFF) : (BYTE)((dwBits+1) & 0xFF); - goto Next; - } - if (bLeft < 17) - { - DWORD i = (0xFFFF >> (17 - bLeft)) + 8; - DWORD j = (i - 16) & 0xFFFF; - if ((dwBits <= j) || (dwBits > (i & 0xFFFF))) goto UnpackByte; - dwBits -= j; - bLeft = ((BYTE)(dwBits & 0xFF) < bLeft) ? (BYTE)(dwBits & 0xFF) : (BYTE)((dwBits+1) & 0xFF); - goto Next; - } - if (bLeft >= 18) goto SkipByte; - if (dwBits >= 0x10000) - { - bLeft = (BYTE)(dwBits + 1) & 0xFF; - goto Next; - } - UnpackByte: - if (bLeft < 16) - { - BYTE shift = 16 - bLeft; - signed short c = (signed short)(dwBits << shift); - c >>= shift; - dwBits = (DWORD)c; - } - dwBits += wTemp; - wTemp = (signed short)dwBits; - wTemp2 += wTemp; -#ifdef IT215_SUPPORT - pDst[dwPos] = (b215) ? wTemp2 : wTemp; -#else - pDst[dwPos] = wTemp; -#endif - SkipByte: - dwPos++; - Next: - if (pSrc >= lpMemFile+dwMemLength+1) return; - } while (dwPos < d); - // Move On - wCount -= d; - dwLen -= d; - pDst += d; - if (pSrc >= lpMemFile+dwMemLength) break; - } -} - - -UINT CSoundFile::SaveMixPlugins(FILE *f, BOOL bUpdate) -//---------------------------------------------------- -{ - DWORD chinfo[64]; - CHAR s[32]; - DWORD nPluginSize, writeSwapDWORD; - SNDMIXPLUGININFO writePluginInfo; - UINT nTotalSize = 0; - UINT nChInfo = 0; - - for (UINT i=0; iInfo.dwPluginId1) || (p->Info.dwPluginId2)) - { - nPluginSize = sizeof(SNDMIXPLUGININFO)+4; // plugininfo+4 (datalen) - if ((p->pMixPlugin) && (bUpdate)) - { - p->pMixPlugin->SaveAllParameters(); - } - if (p->pPluginData) - { - nPluginSize += p->nPluginDataSize; - } - if (f) - { - s[0] = 'F'; - s[1] = 'X'; - s[2] = '0' + (i/10); - s[3] = '0' + (i%10); - fwrite(s, 1, 4, f); - writeSwapDWORD = bswapLE32(nPluginSize); - fwrite(&writeSwapDWORD, 1, 4, f); - - // Copy Information To Be Written for ByteSwapping - memcpy(&writePluginInfo, &p->Info, sizeof(SNDMIXPLUGININFO)); - writePluginInfo.dwPluginId1 = bswapLE32(p->Info.dwPluginId1); - writePluginInfo.dwPluginId2 = bswapLE32(p->Info.dwPluginId2); - writePluginInfo.dwInputRouting = bswapLE32(p->Info.dwInputRouting); - writePluginInfo.dwOutputRouting = bswapLE32(p->Info.dwOutputRouting); - for (UINT j=0; j<4; j++) - { - writePluginInfo.dwReserved[j] = bswapLE32(p->Info.dwReserved[j]); - } - - fwrite(&writePluginInfo, 1, sizeof(SNDMIXPLUGININFO), f); - writeSwapDWORD = bswapLE32(m_MixPlugins[i].nPluginDataSize); - fwrite(&writeSwapDWORD, 1, 4, f); - if (m_MixPlugins[i].pPluginData) - { - fwrite(m_MixPlugins[i].pPluginData, 1, m_MixPlugins[i].nPluginDataSize, f); - } - } - nTotalSize += nPluginSize + 8; - } - } - for (UINT j=0; j nLen-nPos-8) break; - if ((bswapLE32(*(DWORD *)(p+nPos))) == 0x58464843) - { - for (UINT ch=0; ch<64; ch++) if (ch*4 < nPluginSize) - { - ChnSettings[ch].nMixPlugin = bswapLE32(*(DWORD *)(p+nPos+8+ch*4)); - } - } else - { - if ((p[nPos] != 'F') || (p[nPos+1] != 'X') - || (p[nPos+2] < '0') || (p[nPos+3] < '0')) - { - break; - } - nPlugin = (p[nPos+2]-'0')*10 + (p[nPos+3]-'0'); - if ((nPlugin < MAX_MIXPLUGINS) && (nPluginSize >= sizeof(SNDMIXPLUGININFO)+4)) - { - DWORD dwExtra = bswapLE32(*(DWORD *)(p+nPos+8+sizeof(SNDMIXPLUGININFO))); - m_MixPlugins[nPlugin].Info = *(const SNDMIXPLUGININFO *)(p+nPos+8); - m_MixPlugins[nPlugin].Info.dwPluginId1 = bswapLE32(m_MixPlugins[nPlugin].Info.dwPluginId1); - m_MixPlugins[nPlugin].Info.dwPluginId2 = bswapLE32(m_MixPlugins[nPlugin].Info.dwPluginId2); - m_MixPlugins[nPlugin].Info.dwInputRouting = bswapLE32(m_MixPlugins[nPlugin].Info.dwInputRouting); - m_MixPlugins[nPlugin].Info.dwOutputRouting = bswapLE32(m_MixPlugins[nPlugin].Info.dwOutputRouting); - for (UINT j=0; j<4; j++) - { - m_MixPlugins[nPlugin].Info.dwReserved[j] = bswapLE32(m_MixPlugins[nPlugin].Info.dwReserved[j]); - } - if ((dwExtra) && (dwExtra <= nPluginSize-sizeof(SNDMIXPLUGININFO)-4)) - { - m_MixPlugins[nPlugin].nPluginDataSize = 0; - m_MixPlugins[nPlugin].pPluginData = new signed char [dwExtra]; - if (m_MixPlugins[nPlugin].pPluginData) - { - m_MixPlugins[nPlugin].nPluginDataSize = dwExtra; - memcpy(m_MixPlugins[nPlugin].pPluginData, p+nPos+8+sizeof(SNDMIXPLUGININFO)+4, dwExtra); - } - } - } - } - nPos += nPluginSize + 8; - } - return nPos; -} - diff --git a/jni/load_j2b.cpp b/jni/load_j2b.cpp deleted file mode 100644 index 2d86ce8..0000000 --- a/jni/load_j2b.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - - -/////////////////////////////////////////////////// -// -// J2B module loader -// -/////////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - diff --git a/jni/load_mdl.cpp b/jni/load_mdl.cpp deleted file mode 100644 index 3f6d94a..0000000 --- a/jni/load_mdl.cpp +++ /dev/null @@ -1,503 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -////////////////////////////////////////////// -// DigiTracker (MDL) module loader // -////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -typedef struct MDLSONGHEADER -{ - DWORD id; // "DMDL" = 0x4C444D44 - BYTE version; -} MDLSONGHEADER; - - -typedef struct MDLINFOBLOCK -{ - CHAR songname[32]; - CHAR composer[20]; - WORD norders; - WORD repeatpos; - BYTE globalvol; - BYTE speed; - BYTE tempo; - BYTE channelinfo[32]; - BYTE seq[256]; -} MDLINFOBLOCK; - - -typedef struct MDLPATTERNDATA -{ - BYTE channels; - BYTE lastrow; // nrows = lastrow+1 - CHAR name[16]; - WORD data[1]; -} MDLPATTERNDATA; - - -void ConvertMDLCommand(MODCOMMAND *m, UINT eff, UINT data) -//-------------------------------------------------------- -{ - UINT command = 0, param = data; - switch(eff) - { - case 0x01: command = CMD_PORTAMENTOUP; break; - case 0x02: command = CMD_PORTAMENTODOWN; break; - case 0x03: command = CMD_TONEPORTAMENTO; break; - case 0x04: command = CMD_VIBRATO; break; - case 0x05: command = CMD_ARPEGGIO; break; - case 0x07: command = (param < 0x20) ? CMD_SPEED : CMD_TEMPO; break; - case 0x08: command = CMD_PANNING8; param <<= 1; break; - case 0x0B: command = CMD_POSITIONJUMP; break; - case 0x0C: command = CMD_GLOBALVOLUME; break; - case 0x0D: command = CMD_PATTERNBREAK; param = (data & 0x0F) + (data>>4)*10; break; - case 0x0E: - command = CMD_S3MCMDEX; - switch(data & 0xF0) - { - case 0x00: command = 0; break; // What is E0x in MDL (there is a bunch) ? - case 0x10: if (param & 0x0F) { param |= 0xF0; command = CMD_PANNINGSLIDE; } else command = 0; break; - case 0x20: if (param & 0x0F) { param = (param << 4) | 0x0F; command = CMD_PANNINGSLIDE; } else command = 0; break; - case 0x30: param = (data & 0x0F) | 0x10; break; // glissando - case 0x40: param = (data & 0x0F) | 0x30; break; // vibrato waveform - case 0x60: param = (data & 0x0F) | 0xB0; break; - case 0x70: param = (data & 0x0F) | 0x40; break; // tremolo waveform - case 0x90: command = CMD_RETRIG; param &= 0x0F; break; - case 0xA0: param = (data & 0x0F) << 4; command = CMD_GLOBALVOLSLIDE; break; - case 0xB0: param = data & 0x0F; command = CMD_GLOBALVOLSLIDE; break; - case 0xF0: param = ((data >> 8) & 0x0F) | 0xA0; break; - } - break; - case 0x0F: command = CMD_SPEED; break; - case 0x10: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) == 0xF0) param = ((param << 4) | 0x0F); else param >>= 2; } break; - case 0x20: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) != 0xF0) param >>= 2; } break; - case 0x30: command = CMD_RETRIG; break; - case 0x40: command = CMD_TREMOLO; break; - case 0x50: command = CMD_TREMOR; break; - case 0xEF: if (param > 0xFF) param = 0xFF; command = CMD_OFFSET; break; - } - if (command) - { - m->command = command; - m->param = param; - } -} - - -void UnpackMDLTrack(MODCOMMAND *pat, UINT nChannels, UINT nRows, UINT nTrack, const BYTE *lpTracks) -//------------------------------------------------------------------------------------------------- -{ - MODCOMMAND cmd, *m = pat; - UINT len = *((WORD *)lpTracks); - UINT pos = 0, row = 0, i; - lpTracks += 2; - for (UINT ntrk=1; ntrk> 2; - switch(b & 0x03) - { - case 0x01: - for (i=0; i<=xx; i++) - { - if (row) *m = *(m-nChannels); - m += nChannels; - row++; - if (row >= nRows) break; - } - break; - - case 0x02: - if (xx < row) *m = pat[nChannels*xx]; - m += nChannels; - row++; - break; - - case 0x03: - { - cmd.note = (xx & 0x01) ? lpTracks[pos++] : 0; - cmd.instr = (xx & 0x02) ? lpTracks[pos++] : 0; - cmd.volcmd = cmd.vol = 0; - cmd.command = cmd.param = 0; - if ((cmd.note < NOTE_MAX-12) && (cmd.note)) cmd.note += 12; - UINT volume = (xx & 0x04) ? lpTracks[pos++] : 0; - UINT commands = (xx & 0x08) ? lpTracks[pos++] : 0; - UINT command1 = commands & 0x0F; - UINT command2 = commands & 0xF0; - UINT param1 = (xx & 0x10) ? lpTracks[pos++] : 0; - UINT param2 = (xx & 0x20) ? lpTracks[pos++] : 0; - if ((command1 == 0x0E) && ((param1 & 0xF0) == 0xF0) && (!command2)) - { - param1 = ((param1 & 0x0F) << 8) | param2; - command1 = 0xEF; - command2 = param2 = 0; - } - if (volume) - { - cmd.volcmd = VOLCMD_VOLUME; - cmd.vol = (volume+1) >> 2; - } - ConvertMDLCommand(&cmd, command1, param1); - if ((cmd.command != CMD_SPEED) - && (cmd.command != CMD_TEMPO) - && (cmd.command != CMD_PATTERNBREAK)) - ConvertMDLCommand(&cmd, command2, param2); - *m = cmd; - m += nChannels; - row++; - } - break; - - // Empty Slots - default: - row += xx+1; - m += (xx+1)*nChannels; - if (row >= nRows) break; - } - } -} - - - -BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - DWORD dwMemPos, dwPos, blocklen, dwTrackPos; - const MDLSONGHEADER *pmsh = (const MDLSONGHEADER *)lpStream; - const MDLINFOBLOCK *pmib; - const MDLPATTERNDATA *pmpd; - UINT i,j, norders = 0, npatterns = 0, ntracks = 0; - UINT ninstruments = 0, nsamples = 0; - WORD block; - WORD patterntracks[MAX_PATTERNS*32]; - BYTE smpinfo[MAX_SAMPLES]; - BYTE insvolenv[MAX_INSTRUMENTS]; - BYTE inspanenv[MAX_INSTRUMENTS]; - LPCBYTE pvolenv, ppanenv, ppitchenv; - UINT nvolenv, npanenv, npitchenv; - - if ((!lpStream) || (dwMemLength < 1024)) return FALSE; - if ((pmsh->id != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE; - memset(patterntracks, 0, sizeof(patterntracks)); - memset(smpinfo, 0, sizeof(smpinfo)); - memset(insvolenv, 0, sizeof(insvolenv)); - memset(inspanenv, 0, sizeof(inspanenv)); - dwMemPos = 5; - dwTrackPos = 0; - pvolenv = ppanenv = ppitchenv = NULL; - nvolenv = npanenv = npitchenv = 0; - m_nSamples = m_nInstruments = 0; - while (dwMemPos+6 < dwMemLength) - { - block = *((WORD *)(lpStream+dwMemPos)); - blocklen = *((DWORD *)(lpStream+dwMemPos+2)); - dwMemPos += 6; - if (dwMemPos + blocklen > dwMemLength) - { - if (dwMemPos == 11) return FALSE; - break; - } - switch(block) - { - // IN: infoblock - case 0x4E49: - pmib = (MDLINFOBLOCK *)(lpStream+dwMemPos); - memcpy(m_szNames[0], pmib->songname, 32); - norders = pmib->norders; - if (norders > MAX_ORDERS) norders = MAX_ORDERS; - m_nRestartPos = pmib->repeatpos; - m_nDefaultGlobalVolume = pmib->globalvol; - m_nDefaultTempo = pmib->tempo; - m_nDefaultSpeed = pmib->speed; - m_nChannels = 4; - for (i=0; i<32; i++) - { - ChnSettings[i].nVolume = 64; - ChnSettings[i].nPan = (pmib->channelinfo[i] & 0x7F) << 1; - if (pmib->channelinfo[i] & 0x80) - ChnSettings[i].dwFlags |= CHN_MUTE; - else - m_nChannels = i+1; - } - for (j=0; jseq[j]; - break; - // ME: song message - case 0x454D: - if (blocklen) - { - if (m_lpszSongComments) delete [] m_lpszSongComments; - m_lpszSongComments = new char[blocklen]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, blocklen); - m_lpszSongComments[blocklen-1] = 0; - } - } - break; - // PA: Pattern Data - case 0x4150: - npatterns = lpStream[dwMemPos]; - if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS; - dwPos = dwMemPos + 1; - for (i=0; i= dwMemLength) break; - pmpd = (MDLPATTERNDATA *)(lpStream + dwPos); - if (pmpd->channels > 32) break; - PatternSize[i] = pmpd->lastrow+1; - if (m_nChannels < pmpd->channels) m_nChannels = pmpd->channels; - dwPos += 18 + 2*pmpd->channels; - for (j=0; jchannels; j++) - { - patterntracks[i*32+j] = pmpd->data[j]; - } - } - break; - // TR: Track Data - case 0x5254: - if (dwTrackPos) break; - ntracks = *((WORD *)(lpStream+dwMemPos)); - dwTrackPos = dwMemPos+2; - break; - // II: Instruments - case 0x4949: - ninstruments = lpStream[dwMemPos]; - dwPos = dwMemPos+1; - for (i=0; i= MAX_INSTRUMENTS) || (!nins)) break; - if (m_nInstruments < nins) m_nInstruments = nins; - if (!Headers[nins]) - { - UINT note = 12; - if ((Headers[nins] = new INSTRUMENTHEADER) == NULL) break; - INSTRUMENTHEADER *penv = Headers[nins]; - memset(penv, 0, sizeof(INSTRUMENTHEADER)); - memcpy(penv->name, lpStream+dwPos+2, 32); - penv->nGlobalVol = 64; - penv->nPPC = 5*12; - for (j=0; jNoteMap[note] = note+1; - if (ps[0] < MAX_SAMPLES) - { - int ismp = ps[0]; - penv->Keyboard[note] = ps[0]; - Ins[ismp].nVolume = ps[2]; - Ins[ismp].nPan = ps[4] << 1; - Ins[ismp].nVibType = ps[11]; - Ins[ismp].nVibSweep = ps[10]; - Ins[ismp].nVibDepth = ps[9]; - Ins[ismp].nVibRate = ps[8]; - } - penv->nFadeOut = (ps[7] << 8) | ps[6]; - if (penv->nFadeOut == 0xFFFF) penv->nFadeOut = 0; - note++; - } - // Use volume envelope ? - if (ps[3] & 0x80) - { - penv->dwFlags |= ENV_VOLUME; - insvolenv[nins] = (ps[3] & 0x3F) + 1; - } - // Use panning envelope ? - if (ps[5] & 0x80) - { - penv->dwFlags |= ENV_PANNING; - inspanenv[nins] = (ps[5] & 0x3F) + 1; - } - } - } - dwPos += 34 + 14*lpStream[dwPos+1]; - } - for (j=1; j<=m_nInstruments; j++) if (!Headers[j]) - { - Headers[j] = new INSTRUMENTHEADER; - if (Headers[j]) memset(Headers[j], 0, sizeof(INSTRUMENTHEADER)); - } - break; - // VE: Volume Envelope - case 0x4556: - if ((nvolenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + nvolenv*32 + 1 <= dwMemLength) pvolenv = lpStream + dwMemPos + 1; - break; - // PE: Panning Envelope - case 0x4550: - if ((npanenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + npanenv*32 + 1 <= dwMemLength) ppanenv = lpStream + dwMemPos + 1; - break; - // FE: Pitch Envelope - case 0x4546: - if ((npitchenv = lpStream[dwMemPos]) == 0) break; - if (dwMemPos + npitchenv*32 + 1 <= dwMemLength) ppitchenv = lpStream + dwMemPos + 1; - break; - // IS: Sample Infoblock - case 0x5349: - nsamples = lpStream[dwMemPos]; - dwPos = dwMemPos+1; - for (i=0; i= MAX_SAMPLES) || (!nins)) continue; - if (m_nSamples < nins) m_nSamples = nins; - MODINSTRUMENT *pins = &Ins[nins]; - memcpy(m_szNames[nins], lpStream+dwPos+1, 32); - memcpy(pins->name, lpStream+dwPos+33, 8); - pins->nC4Speed = *((DWORD *)(lpStream+dwPos+41)); - pins->nLength = *((DWORD *)(lpStream+dwPos+45)); - pins->nLoopStart = *((DWORD *)(lpStream+dwPos+49)); - pins->nLoopEnd = pins->nLoopStart + *((DWORD *)(lpStream+dwPos+53)); - if (pins->nLoopEnd > pins->nLoopStart) pins->uFlags |= CHN_LOOP; - pins->nGlobalVol = 64; - if (lpStream[dwPos+58] & 0x01) - { - pins->uFlags |= CHN_16BIT; - pins->nLength >>= 1; - pins->nLoopStart >>= 1; - pins->nLoopEnd >>= 1; - } - if (lpStream[dwPos+58] & 0x02) pins->uFlags |= CHN_PINGPONGLOOP; - smpinfo[nins] = (lpStream[dwPos+58] >> 2) & 3; - } - break; - // SA: Sample Data - case 0x4153: - dwPos = dwMemPos; - for (i=1; i<=m_nSamples; i++) if ((Ins[i].nLength) && (!Ins[i].pSample) && (smpinfo[i] != 3) && (dwPos < dwMemLength)) - { - MODINSTRUMENT *pins = &Ins[i]; - UINT flags = (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; - if (!smpinfo[i]) - { - dwPos += ReadSample(pins, flags, (LPSTR)(lpStream+dwPos), dwMemLength - dwPos); - } else - { - DWORD dwLen = *((DWORD *)(lpStream+dwPos)); - dwPos += 4; - if ((dwLen < dwMemLength) && (dwLen <= dwMemLength - dwPos) && (dwLen > 4)) - { - flags = (pins->uFlags & CHN_16BIT) ? RS_MDL16 : RS_MDL8; - ReadSample(pins, flags, (LPSTR)(lpStream+dwPos), dwLen); - } - dwPos += dwLen; - } - } - break; - } - dwMemPos += blocklen; - } - // Unpack Patterns - if ((dwTrackPos) && (npatterns) && (m_nChannels) && (ntracks)) - { - for (UINT ipat=0; ipatnVolEnv = 15; - for (UINT iv=0; iv<15; iv++) - { - if (iv) vtick += pve[iv*2+1]; - penv->VolPoints[iv] = vtick; - penv->VolEnv[iv] = pve[iv*2+2]; - if (!pve[iv*2+1]) - { - penv->nVolEnv = iv+1; - break; - } - } - penv->nVolSustainBegin = penv->nVolSustainEnd = pve[31] & 0x0F; - if (pve[31] & 0x10) penv->dwFlags |= ENV_VOLSUSTAIN; - if (pve[31] & 0x20) penv->dwFlags |= ENV_VOLLOOP; - penv->nVolLoopStart = pve[32] & 0x0F; - penv->nVolLoopEnd = pve[32] >> 4; - } - } - // Setup panning envelope - if ((npanenv) && (ppanenv) && (inspanenv[iIns])) - { - LPCBYTE ppe = ppanenv; - for (UINT npe=0; npenPanEnv = 15; - for (UINT iv=0; iv<15; iv++) - { - if (iv) vtick += ppe[iv*2+1]; - penv->PanPoints[iv] = vtick; - penv->PanEnv[iv] = ppe[iv*2+2]; - if (!ppe[iv*2+1]) - { - penv->nPanEnv = iv+1; - break; - } - } - if (ppe[31] & 0x10) penv->dwFlags |= ENV_PANSUSTAIN; - if (ppe[31] & 0x20) penv->dwFlags |= ENV_PANLOOP; - penv->nPanLoopStart = ppe[32] & 0x0F; - penv->nPanLoopEnd = ppe[32] >> 4; - } - } - } - m_dwSongFlags |= SONG_LINEARSLIDES; - m_nType = MOD_TYPE_MDL; - return TRUE; -} - - -///////////////////////////////////////////////////////////////////////// -// MDL Sample Unpacking - -// MDL Huffman ReadBits compression -WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n) -//----------------------------------------------------------------- -{ - WORD v = (WORD)(bitbuf & ((1 << n) - 1) ); - bitbuf >>= n; - bitnum -= n; - if (bitnum <= 24) - { - bitbuf |= (((DWORD)(*ibuf++)) << bitnum); - bitnum += 8; - } - return v; -} - - diff --git a/jni/load_med.cpp b/jni/load_med.cpp deleted file mode 100644 index 4d3b2a2..0000000 --- a/jni/load_med.cpp +++ /dev/null @@ -1,931 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque , - * Adam Goode (endian and char fixes for PPC) -*/ - -#include "stdafx.h" -#include "sndfile.h" - -//#define MED_LOG - -#ifdef MED_LOG -extern void Log(LPCSTR s, ...); -#endif - -////////////////////////////////////////////////////////// -// OctaMed MED file support (import only) -// -// Lookup table for bpm values. -static const BYTE bpmvals[10] = { 179,164,152,141,131,123,116,110,104,99 }; - - -// flags -#define MMD_FLAG_FILTERON 0x1 -#define MMD_FLAG_JUMPINGON 0x2 -#define MMD_FLAG_JUMP8TH 0x4 -#define MMD_FLAG_INSTRSATT 0x8 // instruments are attached (this is a module) -#define MMD_FLAG_VOLHEX 0x10 -#define MMD_FLAG_STSLIDE 0x20 // SoundTracker mode for slides -#define MMD_FLAG_8CHANNEL 0x40 // OctaMED 8 channel song -#define MMD_FLAG_SLOWHQ 0x80 // HQ slows playing speed (V2-V4 compatibility) -// flags2 -#define MMD_FLAG2_BMASK 0x1F -#define MMD_FLAG2_BPM 0x20 -#define MMD_FLAG2_MIX 0x80 // uses Mixing (V7+) -// flags3: -#define MMD_FLAG3_STEREO 0x1 // mixing in Stereo mode -#define MMD_FLAG3_FREEPAN 0x2 // free panning -#define MMD_FLAG3_GM 0x4 // module designed for GM/XG compatibility - - -// generic MMD tags -#define MMDTAG_END 0 -#define MMDTAG_PTR 0x80000000 // data needs relocation -#define MMDTAG_MUSTKNOW 0x40000000 // loader must fail if this isn't recognized -#define MMDTAG_MUSTWARN 0x20000000 // loader must warn if this isn't recognized - -// ExpData tags -// # of effect groups, including the global group (will -// override settings in MMDSong struct), default = 1 -#define MMDTAG_EXP_NUMFXGROUPS 1 -#define MMDTAG_TRK_NAME (MMDTAG_PTR|1) // trackinfo tags -#define MMDTAG_TRK_NAMELEN 2 // namelen includes zero term. -#define MMDTAG_TRK_FXGROUP 3 -// effectinfo tags -#define MMDTAG_FX_ECHOTYPE 1 -#define MMDTAG_FX_ECHOLEN 2 -#define MMDTAG_FX_ECHODEPTH 3 -#define MMDTAG_FX_STEREOSEP 4 -#define MMDTAG_FX_GROUPNAME (MMDTAG_PTR|5) // the Global Effects group shouldn't have name saved! -#define MMDTAG_FX_GRPNAMELEN 6 // namelen includes zero term. - -#pragma pack(1) - -typedef struct tagMEDMODULEHEADER -{ - DWORD id; // MMD1-MMD3 - DWORD modlen; // Size of file - DWORD song; // Position in file for this song - WORD psecnum; - WORD pseq; - DWORD blockarr; // Position in file for blocks - DWORD mmdflags; - DWORD smplarr; // Position in file for samples - DWORD reserved; - DWORD expdata; // Absolute offset in file for ExpData (0 if not present) - DWORD reserved2; - WORD pstate; - WORD pblock; - WORD pline; - WORD pseqnum; - WORD actplayline; - BYTE counter; - BYTE extra_songs; // # of songs - 1 -} MEDMODULEHEADER; - - -typedef struct tagMMD0SAMPLE -{ - WORD rep, replen; - BYTE midich; - BYTE midipreset; - BYTE svol; - signed char strans; -} MMD0SAMPLE; - - -// Sample header is immediately followed by sample data... -typedef struct tagMMDSAMPLEHEADER -{ - DWORD length; // length of *one* *unpacked* channel in *bytes* - WORD type; - // if non-negative - // bits 0-3 reserved for multi-octave instruments, not supported on the PC - // 0x10: 16 bit (otherwise 8 bit) - // 0x20: Stereo (otherwise mono) - // 0x40: Uses DeltaCode - // 0x80: Packed data - // -1: Synth - // -2: Hybrid - // if type indicates packed data, these fields follow, otherwise we go right to the data - WORD packtype; // Only 1 = ADPCM is supported - WORD subtype; // Packing subtype - // ADPCM subtype - // 1: g723_40 - // 2: g721 - // 3: g723_24 - BYTE commonflags; // flags common to all packtypes (none defined so far) - BYTE packerflags; // flags for the specific packtype - ULONG leftchlen; // packed length of left channel in bytes - ULONG rightchlen; // packed length of right channel in bytes (ONLY PRESENT IN STEREO SAMPLES) - BYTE SampleData[1]; // Sample Data -} MMDSAMPLEHEADER; - - -// MMD0/MMD1 song header -typedef struct tagMMD0SONGHEADER -{ - MMD0SAMPLE sample[63]; - WORD numblocks; // # of blocks - WORD songlen; // # of entries used in playseq - BYTE playseq[256]; // Play sequence - WORD deftempo; // BPM tempo - signed char playtransp; // Play transpose - BYTE flags; // 0x10: Hex Volumes | 0x20: ST/NT/PT Slides | 0x40: 8 Channels song - BYTE flags2; // [b4-b0]+1: Tempo LPB, 0x20: tempo mode, 0x80: mix_conv=on - BYTE tempo2; // tempo TPL - BYTE trkvol[16]; // track volumes - BYTE mastervol; // master volume - BYTE numsamples; // # of samples (max=63) -} MMD0SONGHEADER; - - -// MMD2/MMD3 song header -typedef struct tagMMD2SONGHEADER -{ - MMD0SAMPLE sample[63]; - WORD numblocks; // # of blocks - WORD numsections; // # of sections - DWORD playseqtable; // filepos of play sequence - DWORD sectiontable; // filepos of sections table (WORD array) - DWORD trackvols; // filepos of tracks volume (BYTE array) - WORD numtracks; // # of tracks (max 64) - WORD numpseqs; // # of play sequences - DWORD trackpans; // filepos of tracks pan values (BYTE array) - LONG flags3; // 0x1:stereo_mix, 0x2:free_panning, 0x4:GM/XG compatibility - WORD voladj; // vol_adjust (set to 100 if 0) - WORD channels; // # of channels (4 if =0) - BYTE mix_echotype; // 1:normal,2:xecho - BYTE mix_echodepth; // 1..6 - WORD mix_echolen; // > 0 - signed char mix_stereosep; // -4..4 - BYTE pad0[223]; - WORD deftempo; // BPM tempo - signed char playtransp; // play transpose - BYTE flags; // 0x1:filteron, 0x2:jumpingon, 0x4:jump8th, 0x8:instr_attached, 0x10:hex_vol, 0x20:PT_slides, 0x40:8ch_conv,0x80:hq slows playing speed - BYTE flags2; // 0x80:mix_conv=on, [b4-b0]+1:tempo LPB, 0x20:tempo_mode - BYTE tempo2; // tempo TPL - BYTE pad1[16]; - BYTE mastervol; // master volume - BYTE numsamples; // # of samples (max 63) -} MMD2SONGHEADER; - -// For MMD0 the note information is held in 3 bytes, byte0, byte1, byte2. For reference we -// number the bits in each byte 0..7, where 0 is the low bit. -// The note is held as bits 5..0 of byte0 -// The instrument is encoded in 6 bits, bits 7 and 6 of byte0 and bits 7,6,5,4 of byte1 -// The command number is bits 3,2,1,0 of byte1, command data is in byte2: -// For command 0, byte2 represents the second data byte, otherwise byte2 -// represents the first data byte. -typedef struct tagMMD0BLOCK -{ - BYTE numtracks; - BYTE lines; // File value is 1 less than actual, so 0 -> 1 line -} MMD0BLOCK; // BYTE data[lines+1][tracks][3]; - - -// For MMD1,MMD2,MMD3 the note information is carried in 4 bytes, byte0, byte1, -// byte2 and byte3 -// The note is held as byte0 (values above 0x84 are ignored) -// The instrument is held as byte1 -// The command number is held as byte2, command data is in byte3 -// For commands 0 and 0x19 byte3 represents the second data byte, -// otherwise byte2 represents the first data byte. -typedef struct tagMMD1BLOCK -{ - WORD numtracks; // Number of tracks, may be > 64, but then that data is skipped. - WORD lines; // Stored value is 1 less than actual, so 0 -> 1 line - DWORD info; // Offset of BlockInfo (if 0, no block_info is present) -} MMD1BLOCK; - - -typedef struct tagMMD1BLOCKINFO -{ - DWORD hlmask; // Unimplemented - ignore - DWORD blockname; // file offset of block name - DWORD blocknamelen; // length of block name (including term. 0) - DWORD pagetable; // file offset of command page table - DWORD cmdexttable; // file offset of command extension table - DWORD reserved[4]; // future expansion -} MMD1BLOCKINFO; - - -// A set of play sequences is stored as an array of ULONG files offsets -// Each offset points to the play sequence itself. -typedef struct tagMMD2PLAYSEQ -{ - CHAR name[32]; - DWORD command_offs; // filepos of command table - DWORD reserved; - WORD length; - WORD seq[512]; // skip if > 0x8000 -} MMD2PLAYSEQ; - - -// A command table contains commands that effect a particular play sequence -// entry. The only commands read in are STOP or POSJUMP, all others are ignored -// POSJUMP is presumed to have extra bytes containing a WORD for the position -typedef struct tagMMDCOMMAND -{ - WORD offset; // Offset within current sequence entry - BYTE cmdnumber; // STOP (537) or POSJUMP (538) (others skipped) - BYTE extra_count; - BYTE extra_bytes[4];// [extra_count]; -} MMDCOMMAND; // Last entry has offset == 0xFFFF, cmd_number == 0 and 0 extrabytes - - -typedef struct tagMMD0EXP -{ - DWORD nextmod; // File offset of next Hdr - DWORD exp_smp; // Pointer to extra instrument data - WORD s_ext_entries; // Number of extra instrument entries - WORD s_ext_entrsz; // Size of extra instrument data - DWORD annotxt; - DWORD annolen; - DWORD iinfo; // Instrument names - WORD i_ext_entries; - WORD i_ext_entrsz; - DWORD jumpmask; - DWORD rgbtable; - BYTE channelsplit[4]; // Only used if 8ch_conv (extra channel for every nonzero entry) - DWORD n_info; - DWORD songname; // Song name - DWORD songnamelen; - DWORD dumps; - DWORD mmdinfo; - DWORD mmdrexx; - DWORD mmdcmd3x; - DWORD trackinfo_ofs; // ptr to song->numtracks ptrs to tag lists - DWORD effectinfo_ofs; // ptr to group ptrs - DWORD tag_end; -} MMD0EXP; - -#pragma pack() - - - -static void MedConvert(MODCOMMAND *p, const MMD0SONGHEADER *pmsh) -//--------------------------------------------------------------- -{ - UINT command = p->command; - UINT param = p->param; - switch(command) - { - case 0x00: if (param) command = CMD_ARPEGGIO; else command = 0; break; - case 0x01: command = CMD_PORTAMENTOUP; break; - case 0x02: command = CMD_PORTAMENTODOWN; break; - case 0x03: command = CMD_TONEPORTAMENTO; break; - case 0x04: command = CMD_VIBRATO; break; - case 0x05: command = CMD_TONEPORTAVOL; break; - case 0x06: command = CMD_VIBRATOVOL; break; - case 0x07: command = CMD_TREMOLO; break; - case 0x0A: if (param & 0xF0) param &= 0xF0; command = CMD_VOLUMESLIDE; if (!param) command = 0; break; - case 0x0B: command = CMD_POSITIONJUMP; break; - case 0x0C: command = CMD_VOLUME; - if (pmsh->flags & MMD_FLAG_VOLHEX) - { - if (param < 0x80) - { - param = (param+1) / 2; - } else command = 0; - } else - { - if (param <= 0x99) - { - param = (param >> 4)*10+((param & 0x0F) % 10); - if (param > 64) param = 64; - } else command = 0; - } - break; - case 0x09: command = (param < 0x20) ? CMD_SPEED : CMD_TEMPO; break; - case 0x0D: if (param & 0xF0) param &= 0xF0; command = CMD_VOLUMESLIDE; if (!param) command = 0; break; - case 0x0F: // Set Tempo / Special - // F.00 = Pattern Break - if (!param) command = CMD_PATTERNBREAK; else - // F.01 - F.F0: Set tempo/speed - if (param <= 0xF0) - { - if (pmsh->flags & MMD_FLAG_8CHANNEL) - { - param = (param > 10) ? 99 : bpmvals[param-1]; - } else - // F.01 - F.0A: Set Speed - if (param <= 0x0A) - { - command = CMD_SPEED; - } else - // Old tempo - if (!(pmsh->flags2 & MMD_FLAG2_BPM)) - { - param = _muldiv(param, 5*715909, 2*474326); - } - // F.0B - F.F0: Set Tempo (assumes LPB=4) - if (param > 0x0A) - { - command = CMD_TEMPO; - if (param < 0x21) param = 0x21; - if (param > 240) param = 240; - } - } else - switch(param) - { - // F.F1: Retrig 2x - case 0xF1: - command = CMD_MODCMDEX; - param = 0x93; - break; - // F.F2: Note Delay 2x - case 0xF2: - command = CMD_MODCMDEX; - param = 0xD3; - break; - // F.F3: Retrig 3x - case 0xF3: - command = CMD_MODCMDEX; - param = 0x92; - break; - // F.F4: Note Delay 1/3 - case 0xF4: - command = CMD_MODCMDEX; - param = 0xD2; - break; - // F.F5: Note Delay 2/3 - case 0xF5: - command = CMD_MODCMDEX; - param = 0xD4; - break; - // F.F8: Filter Off - case 0xF8: - command = CMD_MODCMDEX; - param = 0x00; - break; - // F.F9: Filter On - case 0xF9: - command = CMD_MODCMDEX; - param = 0x01; - break; - // F.FD: Very fast tone-portamento - case 0xFD: - command = CMD_TONEPORTAMENTO; - param = 0xFF; - break; - // F.FE: End Song - case 0xFE: - command = CMD_SPEED; - param = 0; - break; - // F.FF: Note Cut - case 0xFF: - command = CMD_MODCMDEX; - param = 0xC0; - break; - default: -#ifdef MED_LOG - Log("Unknown Fxx command: cmd=0x%02X param=0x%02X\n", command, param); -#endif - param = command = 0; - } - break; - // 11.0x: Fine Slide Up - case 0x11: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0x10; - break; - // 12.0x: Fine Slide Down - case 0x12: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0x20; - break; - // 14.xx: Vibrato - case 0x14: - command = CMD_VIBRATO; - break; - // 15.xx: FineTune - case 0x15: - command = CMD_MODCMDEX; - param &= 0x0F; - param |= 0x50; - break; - // 16.xx: Pattern Loop - case 0x16: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0x60; - break; - // 18.xx: Note Cut - case 0x18: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0xC0; - break; - // 19.xx: Sample Offset - case 0x19: - command = CMD_OFFSET; - break; - // 1A.0x: Fine Volume Up - case 0x1A: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0xA0; - break; - // 1B.0x: Fine Volume Down - case 0x1B: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0xB0; - break; - // 1D.xx: Pattern Break - case 0x1D: - command = CMD_PATTERNBREAK; - break; - // 1E.0x: Pattern Delay - case 0x1E: - command = CMD_MODCMDEX; - if (param > 0x0F) param = 0x0F; - param |= 0xE0; - break; - // 1F.xy: Retrig - case 0x1F: - command = CMD_RETRIG; - param &= 0x0F; - break; - // 2E.xx: set panning - case 0x2E: - command = CMD_MODCMDEX; - param = ((param + 0x10) & 0xFF) >> 1; - if (param > 0x0F) param = 0x0F; - param |= 0x80; - break; - default: -#ifdef MED_LOG - // 0x2E ? - Log("Unknown command: cmd=0x%02X param=0x%02X\n", command, param); -#endif - command = param = 0; - } - p->command = command; - p->param = param; -} - - -BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - const MEDMODULEHEADER *pmmh; - const MMD0SONGHEADER *pmsh; - const MMD2SONGHEADER *pmsh2; - const MMD0EXP *pmex; - DWORD dwBlockArr, dwSmplArr, dwExpData, wNumBlocks; - LPDWORD pdwTable; - CHAR version; - UINT deftempo; - int playtransp = 0; - - if ((!lpStream) || (dwMemLength < 0x200)) return FALSE; - pmmh = (MEDMODULEHEADER *)lpStream; - if (((pmmh->id & 0x00FFFFFF) != 0x444D4D) || (!pmmh->song)) return FALSE; - // Check for 'MMDx' - DWORD dwSong = bswapBE32(pmmh->song); - if ((dwSong >= dwMemLength) || (dwSong + sizeof(MMD0SONGHEADER) >= dwMemLength)) return FALSE; - version = (signed char)((pmmh->id >> 24) & 0xFF); - if ((version < '0') || (version > '3')) return FALSE; -#ifdef MED_LOG - Log("\nLoading MMD%c module (flags=0x%02X)...\n", version, bswapBE32(pmmh->mmdflags)); - Log(" modlen = %d\n", bswapBE32(pmmh->modlen)); - Log(" song = 0x%08X\n", bswapBE32(pmmh->song)); - Log(" psecnum = %d\n", bswapBE16(pmmh->psecnum)); - Log(" pseq = %d\n", bswapBE16(pmmh->pseq)); - Log(" blockarr = 0x%08X\n", bswapBE32(pmmh->blockarr)); - Log(" mmdflags = 0x%08X\n", bswapBE32(pmmh->mmdflags)); - Log(" smplarr = 0x%08X\n", bswapBE32(pmmh->smplarr)); - Log(" reserved = 0x%08X\n", bswapBE32(pmmh->reserved)); - Log(" expdata = 0x%08X\n", bswapBE32(pmmh->expdata)); - Log(" reserved2= 0x%08X\n", bswapBE32(pmmh->reserved2)); - Log(" pstate = %d\n", bswapBE16(pmmh->pstate)); - Log(" pblock = %d\n", bswapBE16(pmmh->pblock)); - Log(" pline = %d\n", bswapBE16(pmmh->pline)); - Log(" pseqnum = %d\n", bswapBE16(pmmh->pseqnum)); - Log(" actplayline=%d\n", bswapBE16(pmmh->actplayline)); - Log(" counter = %d\n", pmmh->counter); - Log(" extra_songs = %d\n", pmmh->extra_songs); - Log("\n"); -#endif - m_nType = MOD_TYPE_MED; - m_nSongPreAmp = 0x20; - dwBlockArr = bswapBE32(pmmh->blockarr); - dwSmplArr = bswapBE32(pmmh->smplarr); - dwExpData = bswapBE32(pmmh->expdata); - if ((dwExpData) && (dwExpData < dwMemLength - sizeof(MMD0EXP))) - pmex = (MMD0EXP *)(lpStream+dwExpData); - else - pmex = NULL; - pmsh = (MMD0SONGHEADER *)(lpStream + dwSong); - pmsh2 = (MMD2SONGHEADER *)pmsh; -#ifdef MED_LOG - if (version < '2') - { - Log("MMD0 Header:\n"); - Log(" numblocks = %d\n", bswapBE16(pmsh->numblocks)); - Log(" songlen = %d\n", bswapBE16(pmsh->songlen)); - Log(" playseq = "); - for (UINT idbg1=0; idbg1<16; idbg1++) Log("%2d, ", pmsh->playseq[idbg1]); - Log("...\n"); - Log(" deftempo = 0x%04X\n", bswapBE16(pmsh->deftempo)); - Log(" playtransp = %d\n", (signed char)pmsh->playtransp); - Log(" flags(1,2) = 0x%02X, 0x%02X\n", pmsh->flags, pmsh->flags2); - Log(" tempo2 = %d\n", pmsh->tempo2); - Log(" trkvol = "); - for (UINT idbg2=0; idbg2<16; idbg2++) Log("0x%02X, ", pmsh->trkvol[idbg2]); - Log("...\n"); - Log(" mastervol = 0x%02X\n", pmsh->mastervol); - Log(" numsamples = %d\n", pmsh->numsamples); - } else - { - Log("MMD2 Header:\n"); - Log(" numblocks = %d\n", bswapBE16(pmsh2->numblocks)); - Log(" numsections= %d\n", bswapBE16(pmsh2->numsections)); - Log(" playseqptr = 0x%04X\n", bswapBE32(pmsh2->playseqtable)); - Log(" sectionptr = 0x%04X\n", bswapBE32(pmsh2->sectiontable)); - Log(" trackvols = 0x%04X\n", bswapBE32(pmsh2->trackvols)); - Log(" numtracks = %d\n", bswapBE16(pmsh2->numtracks)); - Log(" numpseqs = %d\n", bswapBE16(pmsh2->numpseqs)); - Log(" trackpans = 0x%04X\n", bswapBE32(pmsh2->trackpans)); - Log(" flags3 = 0x%08X\n", bswapBE32(pmsh2->flags3)); - Log(" voladj = %d\n", bswapBE16(pmsh2->voladj)); - Log(" channels = %d\n", bswapBE16(pmsh2->channels)); - Log(" echotype = %d\n", pmsh2->mix_echotype); - Log(" echodepth = %d\n", pmsh2->mix_echodepth); - Log(" echolen = %d\n", bswapBE16(pmsh2->mix_echolen)); - Log(" stereosep = %d\n", (signed char)pmsh2->mix_stereosep); - Log(" deftempo = 0x%04X\n", bswapBE16(pmsh2->deftempo)); - Log(" playtransp = %d\n", (signed char)pmsh2->playtransp); - Log(" flags(1,2) = 0x%02X, 0x%02X\n", pmsh2->flags, pmsh2->flags2); - Log(" tempo2 = %d\n", pmsh2->tempo2); - Log(" mastervol = 0x%02X\n", pmsh2->mastervol); - Log(" numsamples = %d\n", pmsh->numsamples); - } - Log("\n"); -#endif - wNumBlocks = bswapBE16(pmsh->numblocks); - m_nChannels = 4; - m_nSamples = pmsh->numsamples; - if (m_nSamples > 63) m_nSamples = 63; - // Tempo - m_nDefaultTempo = 125; - deftempo = bswapBE16(pmsh->deftempo); - if (!deftempo) deftempo = 125; - if (pmsh->flags2 & MMD_FLAG2_BPM) - { - UINT tempo_tpl = (pmsh->flags2 & MMD_FLAG2_BMASK) + 1; - if (!tempo_tpl) tempo_tpl = 4; - deftempo *= tempo_tpl; - deftempo /= 4; - #ifdef MED_LOG - Log("newtempo: %3d bpm (bpm=%3d lpb=%2d)\n", deftempo, bswapBE16(pmsh->deftempo), (pmsh->flags2 & MMD_FLAG2_BMASK)+1); - #endif - } else - { - if (pmsh->flags & MMD_FLAG_8CHANNEL && deftempo > 0 && deftempo <= 10) - { - deftempo = bpmvals[deftempo-1]; - } else { - deftempo = _muldiv(deftempo, 5*715909, 2*474326); - } - #ifdef MED_LOG - Log("oldtempo: %3d bpm (bpm=%3d)\n", deftempo, bswapBE16(pmsh->deftempo)); - #endif - } - // Speed - m_nDefaultSpeed = pmsh->tempo2; - if (!m_nDefaultSpeed) m_nDefaultSpeed = 6; - if (deftempo < 0x21) deftempo = 0x21; - if (deftempo > 255) - { - while ((m_nDefaultSpeed > 3) && (deftempo > 260)) - { - deftempo = (deftempo * (m_nDefaultSpeed - 1)) / m_nDefaultSpeed; - m_nDefaultSpeed--; - } - if (deftempo > 255) deftempo = 255; - } - m_nDefaultTempo = deftempo; - // Reading Samples - for (UINT iSHdr=0; iSHdrnLoopStart = bswapBE16(pmsh->sample[iSHdr].rep) << 1; - pins->nLoopEnd = pins->nLoopStart + (bswapBE16(pmsh->sample[iSHdr].replen) << 1); - pins->nVolume = (pmsh->sample[iSHdr].svol << 2); - pins->nGlobalVol = 64; - if (pins->nVolume > 256) pins->nVolume = 256; - pins->RelativeTone = -12 * pmsh->sample[iSHdr].strans; - pins->nPan = 128; - if (pins->nLoopEnd) pins->uFlags |= CHN_LOOP; - } - // Common Flags - if (!(pmsh->flags & 0x20)) m_dwSongFlags |= SONG_FASTVOLSLIDES; - // Reading play sequence - if (version < '2') - { - UINT nbo = pmsh->songlen >> 8; - if (nbo >= MAX_ORDERS) nbo = MAX_ORDERS-1; - if (!nbo) nbo = 1; - memcpy(Order, pmsh->playseq, nbo); - playtransp = pmsh->playtransp; - } else - { - UINT nOrders, nSections; - UINT nTrks = bswapBE16(pmsh2->numtracks); - if ((nTrks >= 4) && (nTrks <= 32)) m_nChannels = nTrks; - DWORD playseqtable = bswapBE32(pmsh2->playseqtable); - UINT numplayseqs = bswapBE16(pmsh2->numpseqs); - if (!numplayseqs) numplayseqs = 1; - nOrders = 0; - nSections = bswapBE16(pmsh2->numsections); - DWORD sectiontable = bswapBE32(pmsh2->sectiontable); - if ((!nSections) || (!sectiontable) || (sectiontable >= dwMemLength-2)) nSections = 1; - nOrders = 0; - for (UINT iSection=0; iSectionname, 31); - UINT n = bswapBE16(pmps->length); - if (n < (dwMemLength - (pseq + sizeof(*pmps)) + sizeof(pmps->seq)) / sizeof(pmps->seq[0])) - { - for (UINT i=0; iseq[i] >> 8; - if ((seqval < wNumBlocks) && (nOrders < MAX_ORDERS-1)) - { - Order[nOrders++] = seqval; - } - } - } - } - } - playtransp = pmsh2->playtransp; - while (nOrders < MAX_ORDERS) Order[nOrders++] = 0xFF; - } - // Reading Expansion structure - if (pmex) - { - // Channel Split - if ((m_nChannels == 4) && (pmsh->flags & MMD_FLAG_8CHANNEL)) - { - for (UINT i8ch=0; i8ch<4; i8ch++) - { - if (pmex->channelsplit[i8ch]) --m_nChannels; - } - } - // Song Comments - uint32_t annotxt = bswapBE32(pmex->annotxt); - uint32_t annolen = bswapBE32(pmex->annolen); - if ((annotxt) && (annolen) && (annotxt + annolen > annotxt) // overflow checks. - && (annotxt+annolen <= dwMemLength)) - { - m_lpszSongComments = new char[annolen+1]; - memcpy(m_lpszSongComments, lpStream+annotxt, annolen); - m_lpszSongComments[annolen] = 0; - } - // Song Name - uint32_t songname = bswapBE32(pmex->songname); - uint32_t songnamelen = bswapBE32(pmex->songnamelen); - if ((songname) && (songnamelen) && (songname+songnamelen > songname) - && (songname+songnamelen <= dwMemLength)) - { - if (songnamelen > 31) songnamelen = 31; - memcpy(m_szNames[0], lpStream+songname, songnamelen); - m_szNames[0][31] = '\0'; - } - // Sample Names - DWORD smpinfoex = bswapBE32(pmex->iinfo); - if (smpinfoex) - { - DWORD iinfoptr = bswapBE32(pmex->iinfo); - UINT ientries = bswapBE16(pmex->i_ext_entries); - UINT ientrysz = bswapBE16(pmex->i_ext_entrsz); - - if ((iinfoptr) && (ientrysz < 256) && - (ientries*ientrysz < dwMemLength) && - (iinfoptr < dwMemLength - (ientries*ientrysz))) - { - LPCSTR psznames = (LPCSTR)(lpStream + iinfoptr); - UINT maxnamelen = ientrysz; - // copy a max of 32 bytes. - if (maxnamelen > 32) maxnamelen = 32; - for (UINT i=0; itrackinfo_ofs); - if ((trackinfo_ofs) && (trackinfo_ofs < dwMemLength) && (m_nChannels * 4 < dwMemLength - trackinfo_ofs)) - { - DWORD *ptrktags = (DWORD *)(lpStream + trackinfo_ofs); - for (UINT i=0; i MAX_CHANNELNAME) trknamelen = MAX_CHANNELNAME; - if ((trknameofs) && (trknamelen < dwMemLength) && (trknameofs < dwMemLength - trknamelen)) - { - lstrcpyn(ChnSettings[i].szName, (LPCSTR)(lpStream+trknameofs), MAX_CHANNELNAME); - ChnSettings[i].szName[MAX_CHANNELNAME-1] = '\0'; - } - } - } - } - } - // Reading samples - if (dwSmplArr > dwMemLength - 4*m_nSamples) return TRUE; - pdwTable = (LPDWORD)(lpStream + dwSmplArr); - for (UINT iSmp=0; iSmp= dwMemLength) || (dwPos + sizeof(MMDSAMPLEHEADER) >= dwMemLength)) continue; - MMDSAMPLEHEADER *psdh = (MMDSAMPLEHEADER *)(lpStream + dwPos); - UINT len = bswapBE32(psdh->length); - #ifdef MED_LOG - Log("SampleData %d: stype=0x%02X len=%d\n", iSmp, bswapBE16(psdh->type), len); - #endif - if ((len > MAX_SAMPLE_LENGTH) || (dwPos + len + 6 > dwMemLength)) len = 0; - UINT flags = RS_PCM8S, stype = bswapBE16(psdh->type); - LPSTR psdata = (LPSTR)(lpStream + dwPos + 6); - if (stype & 0x80) - { - psdata += (stype & 0x20) ? 14 : 6; - } else - { - if (stype & 0x10) - { - Ins[iSmp+1].uFlags |= CHN_16BIT; - len /= 2; - flags = (stype & 0x20) ? RS_STPCM16M : RS_PCM16M; - } else - { - flags = (stype & 0x20) ? RS_STPCM8S : RS_PCM8S; - } - if (stype & 0x20) len /= 2; - } - Ins[iSmp+1].nLength = len; - ReadSample(&Ins[iSmp+1], flags, psdata, dwMemLength - dwPos - 6); - } - // Reading patterns (blocks) - if (wNumBlocks > MAX_PATTERNS) wNumBlocks = MAX_PATTERNS; - if ((!dwBlockArr) || (dwBlockArr > dwMemLength - 4*wNumBlocks)) return TRUE; - pdwTable = (LPDWORD)(lpStream + dwBlockArr); - playtransp += (version == '3') ? 24 : 48; - for (UINT iBlk=0; iBlk= dwMemLength) || (dwPos >= dwMemLength - 8)) continue; - UINT lines = 64, tracks = 4; - if (version == '0') - { - const MMD0BLOCK *pmb = (const MMD0BLOCK *)(lpStream + dwPos); - lines = pmb->lines + 1; - tracks = pmb->numtracks; - if (!tracks) tracks = m_nChannels; - if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue; - PatternSize[iBlk] = lines; - MODCOMMAND *p = Patterns[iBlk]; - LPBYTE s = (LPBYTE)(lpStream + dwPos + 2); - UINT maxlen = tracks*lines*3; - if (maxlen + dwPos > dwMemLength - 2) break; - for (UINT y=0; y> 4; - if (s[0] & 0x80) instr |= 0x10; - if (s[0] & 0x40) instr |= 0x20; - if ((note) && (note <= 132)) p->note = note + playtransp; - p->instr = instr; - p->command = s[1] & 0x0F; - p->param = s[2]; - // if (!iBlk) Log("%02X.%02X.%02X | ", s[0], s[1], s[2]); - MedConvert(p, pmsh); - p++; - } - //if (!iBlk) Log("\n"); - } - } else - { - const MMD1BLOCK *pmb = (MMD1BLOCK *)(lpStream + dwPos); - #ifdef MED_LOG - Log("MMD1BLOCK: lines=%2d, tracks=%2d, offset=0x%04X\n", - bswapBE16(pmb->lines), bswapBE16(pmb->numtracks), bswapBE32(pmb->info)); - #endif - const MMD1BLOCKINFO *pbi = NULL; - BYTE *pcmdext = NULL; - lines = (pmb->lines >> 8) + 1; - tracks = pmb->numtracks >> 8; - if (!tracks) tracks = m_nChannels; - if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue; - PatternSize[iBlk] = (WORD)lines; - DWORD dwBlockInfo = bswapBE32(pmb->info); - if ((dwBlockInfo) && (dwBlockInfo < dwMemLength - sizeof(MMD1BLOCKINFO))) - { - pbi = (MMD1BLOCKINFO *)(lpStream + dwBlockInfo); - #ifdef MED_LOG - Log(" BLOCKINFO: blockname=0x%04X namelen=%d pagetable=0x%04X &cmdexttable=0x%04X\n", - bswapBE32(pbi->blockname), bswapBE32(pbi->blocknamelen), bswapBE32(pbi->pagetable), bswapBE32(pbi->cmdexttable)); - #endif - if ((pbi->blockname) && (pbi->blocknamelen)) - { - DWORD nameofs = bswapBE32(pbi->blockname); - UINT namelen = bswapBE32(pbi->blocknamelen); - if ((nameofs < dwMemLength) && (namelen < dwMemLength + nameofs)) - { - SetPatternName(iBlk, (LPCSTR)(lpStream+nameofs)); - } - } - if (pbi->cmdexttable) - { - DWORD cmdexttable = bswapBE32(pbi->cmdexttable); - if (cmdexttable < dwMemLength - 4) - { - cmdexttable = bswapBE32(*(DWORD *)(lpStream + cmdexttable)); - if ((cmdexttable) && (cmdexttable <= dwMemLength - lines*tracks)) - { - pcmdext = (BYTE *)(lpStream + cmdexttable); - } - } - } - } - MODCOMMAND *p = Patterns[iBlk]; - LPBYTE s = (LPBYTE)(lpStream + dwPos + 8); - UINT maxlen = tracks*lines*4; - if (maxlen + dwPos > dwMemLength - 8) break; - for (UINT y=0; y NOTE_MAX) rnote = NOTE_MAX; - p->note = (BYTE)rnote; - } - p->instr = s[1]; - p->command = s[2]; - p->param = s[3]; - if (pcmdext) p->vol = pcmdext[x]; - MedConvert(p, pmsh); - p++; - } - if (pcmdext) pcmdext += tracks; - } - } - } - // Setup channel pan positions - for (UINT iCh=0; iCh - - Portability: - All systems - all compilers (hopefully) -*/ - -#include -#include -#include -#include -#include -#ifndef _WIN32 -#include // for sleep -#endif - -#ifdef NEWMIKMOD -#include "mikmod.h" -#include "uniform.h" -#include "itshare.h" // for STMEM_PITCHSLIDE -typedef UBYTE BYTE; -typedef UWORD WORD; -#define MAX_POLYPHONY 12 // max notes in one midi channel -#define MAX_TRACKS 63 // max mod tracks -#define WHEELSHIFT 11 // how many bits the 13bit midi wheel value must shift right -#else -#include "stdafx.h" -#include "sndfile.h" -#define PAN_LEFT 0x30 -#define PAN_RIGHT 0xD0 -#define MAX_POLYPHONY 16 // max notes in one midi channel -#define MAX_TRACKS (MAX_BASECHANNELS-6) // max mod tracks -#define WHEELSHIFT 10 // how many bits the 13bit midi wheel value must shift right -#endif - -#include "load_pat.h" - -#define ROWSPERNOTE 16 -#define ENV_MMMID_SPEED "MMMID_SPEED" -#define ENV_MMMID_DEBUG "MMMID_DEBUG" -#define ENV_MMMID_VERBOSE "MMMID_VERBOSE" - -/************************************************************************** -**************************************************************************/ -#ifdef NEWMIKMOD -static char MID_Version[] = "Musical Instrument Digital Interface"; -#endif - -typedef enum { - none, - wheeldown, - wheelup, - fxbrk, - tmpo, - fxsync, - modwheel, - mainvol, - prog -} MIDEVENT_X_EFFECT; - -typedef struct _MIDEVENT -{ - struct _MIDEVENT *next; - ULONG tracktick; - BYTE flg; // 1 = note present - BYTE note; - BYTE volume; - BYTE smpno; - BYTE fx; - BYTE fxparam; -} MIDEVENT; - -typedef struct _MIDTRACK -{ - struct _MIDTRACK *next; - MIDEVENT *head; - MIDEVENT *tail; - MIDEVENT *workevent; // keeps track of events in track - int balance; // last balance on this track - ULONG vtracktick; // tracktick of last note event (on or off) - BYTE chan; - BYTE vpos; // 0xff is track is free for use, otherwise it's the note playing on this track - BYTE volume; // last note volume on this track - BYTE instr; // current instrument for this track -} MIDTRACK; - -#ifdef NEWMIKMOD - -#define MMFILE MMSTREAM -#define mmfseek(f,p,w) _mm_fseek(f,p,w) -#define mmftell(x) _mm_ftell(x) -#define mmreadUBYTE(f) _mm_read_UBYTE(f) -#define mmreadSBYTES(buf,sz,f) _mm_read_SBYTES(buf,sz,f) -#define mmreadUBYTES(buf,sz,f) _mm_read_UBYTES(buf,sz,f) - -#else - -#if defined(WIN32) && defined(_mm_free) -#undef _mm_free -#endif - -#define MMSTREAM FILE -#define _mm_fseek(f,pos,whence) fseek(f,pos,whence) -#define _mm_read_UBYTES(buf,sz,f) fread(buf,sz,1,f) -#define _mm_read_SBYTES(buf,sz,f) fread(buf,sz,1,f) -#define DupStr(h,buf,sz) strdup(buf) -#define _mm_calloc(h,n,sz) calloc(n,sz) -#define _mm_recalloc(h,buf,sz,elsz) realloc(buf,sz) -#define _mm_free(h,p) free(p) - -typedef struct { - char *mm; - int sz; - int pos; -} MMFILE; - -static void mmfseek(MMFILE *mmfile, long p, int whence) -{ - switch(whence) { - case SEEK_SET: - mmfile->pos = p; - break; - case SEEK_CUR: - mmfile->pos += p; - break; - case SEEK_END: - mmfile->pos = mmfile->sz + p; - break; - } -} - -static long mmftell(MMFILE *mmfile) -{ - return mmfile->pos; -} - -static BYTE mmreadUBYTE(MMFILE *mmfile) -{ - BYTE b; - b = (BYTE)mmfile->mm[mmfile->pos]; - mmfile->pos++; - return b; -} - -static void mmreadUBYTES(BYTE *buf, long sz, MMFILE *mmfile) -{ - memcpy(buf, &mmfile->mm[mmfile->pos], sz); - mmfile->pos += sz; -} - -static void mmreadSBYTES(char *buf, long sz, MMFILE *mmfile) -{ - memcpy(buf, &mmfile->mm[mmfile->pos], sz); - mmfile->pos += sz; -} - -#endif - -/************************************************************************** -**************************************************************************/ - -typedef struct _MIDHANDLE -{ -#ifdef NEWMIKMOD - MM_ALLOC *allochandle; - MM_ALLOC *trackhandle; -#endif - MMFILE *mmf; - MIDTRACK *track; - MIDTRACK *tp; - ULONG tracktime; - const char *debug; - const char *verbose; - int speed; - int midispeed; - int midiformat; - int resolution; - int miditracks; - int divider; - int tempo; - int percussion; - long deltatime; -} MIDHANDLE; - -static void mid_dump_tracks(MIDHANDLE *h) -{ - MIDTRACK *tr; - MIDEVENT *e; - int t; - printf("tracktime = %ld\n", (long)(h->tracktime)); - printf("speed = %d\n", h->speed); - printf("midispeed = %d\n", h->midispeed); - printf("midiformat = %d\n", h->midiformat); - printf("resolution = %d\n", h->resolution); - printf("miditracks = %d\n", h->miditracks); - printf("divider = %d\n", h->divider); - printf("tempo = %d\n", h->tempo); - printf("percussion = %d\n", h->percussion); - printf("deltatime = %ld\n", h->deltatime); - t = 0; - for( tr=h->track; tr; tr = tr->next ) { - t++; - printf("TRACK %2d chan=%d note=0x%02x vol=%d pan=0x%02x instr=%d\n", t, tr->chan + 1, tr->vpos, tr->balance, tr->volume, tr->instr); - for( e=tr->head; e; e=e->next ) { - printf("%2d %6ld %s %3d %3d %3d ", - t, (long)(e->tracktick), - e->flg? "NOTE": "CTRL", e->note, e->volume, e->smpno); - switch( e->fx ) { - case fxbrk: printf("fxbrk\n");break; - case fxsync: printf("fxsync\n");break; - case prog: printf("prog %d\n", e->fxparam);break; - case mainvol: printf("mainvol %d\n", e->fxparam);break; - case modwheel: printf("modwheel %d\n", e->fxparam);break; - case wheeldown: printf("wheeldown %d\n", e->fxparam);break; - case wheelup: printf("wheelup %d\n", e->fxparam);break; - case tmpo: printf("tmpo %d\n", e->fxparam);break; - default: printf("\n");break; - } - } - } -} - -static void mid_message(const char *s1, const char *s2) -{ - char txt[256]; - if( strlen(s1) + strlen(s2) > 255 ) return; - sprintf(txt, s1, s2); -#ifdef NEWMIKMOD - _mmlog(txt); -#else - fprintf(stderr, "load_mid > %s\n", txt); -#endif -} - -static ULONG miditicks(MIDHANDLE *h, ULONG modtick) -{ - return modtick * h->divider / ROWSPERNOTE / h->speed; -} - -static ULONG modticks(MIDHANDLE *h, ULONG miditick) -{ - return miditick * ROWSPERNOTE * h->speed / h->divider; -} - -static void mid_adjust_for_optimal_tempo(MIDHANDLE *h, int maxtempo) -{ - // the tempo is adjusted so that the maximum tempo is 255 - // this way we have the biggest change that very short notes get played - // and we make sure the tempo doesn't become too large or too small - // if the piece in hand isn't so weird it changes tempo from 20 to 255, that is. - // tempo is only registered in first track (h->track) because it is a global event - MIDEVENT *e; - int d, t; - if( maxtempo < 1 ) return; - d = h->divider; - t = maxtempo; - h->divider = (t * d) / 255; - while( (h->midispeed = miditicks(h, h->speed)) < h->speed ) { - ++t; - h->divider = (t * d) / 255; - } - if( h->verbose && t > maxtempo ) - printf("Adjusted maximum tempo from %d to %d to get %d miditicks per patternrow\n", - maxtempo, 2 * maxtempo - t, h->midispeed); - if( h->track ) { - for( e=h->track->head; e; e=e->next ) { - if( e->fx == tmpo ) - e->fxparam = (255 * e->fxparam ) / t; - } - } -} - -// ===================================================================================== -static MIDEVENT *mid_new_event(MIDHANDLE *h) -// ===================================================================================== -{ - MIDEVENT *retval; - - retval = (MIDEVENT *)_mm_calloc(h->trackhandle, 1,sizeof(MIDEVENT)); - retval->next = NULL; - retval->tracktick = h->tracktime; - retval->flg = 0; - retval->note = 0; - retval->volume = 0; - retval->smpno = 0; - retval->fx = none; - retval->fxparam = 0; - return retval; -} - -// ===================================================================================== -static MIDTRACK *mid_new_track(MIDHANDLE *h, int mch, int pos) -// ===================================================================================== -{ - MIDTRACK *retval; - retval = (MIDTRACK *)_mm_calloc(h->trackhandle, 1,sizeof(MIDTRACK)); - retval->next = NULL; - retval->vpos = pos; - retval->instr = 1; - retval->chan = mch; - retval->head = NULL; - retval->tail = NULL; - retval->workevent = NULL; - retval->vtracktick = 0; - retval->volume = h->track? h->track->volume: 120; - retval->balance = 64; - return retval; -} - -static int mid_numtracks(MIDHANDLE *h) -{ - int n; - MIDTRACK *t; - n=0; - for( t = h->track; t; t=t->next ) - n++; - return n; -} - -// find out how many midichannel we have -static int mid_numchans(MIDHANDLE *h) -{ - int i,c,n; - MIDTRACK *t; - c = 0; - for( t = h->track; t; t=t->next ) - c |= (1<chan); - n = 0; - for( i=0; i<16; i++ ) - if( c & (1<track; t; t=t->next ) - c |= (1<chan); - n = 0; - for( i=0; itracktime = 0; - for( tr = h->track; tr; tr = tr->next ) { - tr->vpos = 0xff; - tr->workevent = tr->head; - tr->vtracktick = 0; - } -} - -static void mid_update_track(MIDTRACK *tr) -{ - MIDEVENT *e; - e = tr->workevent; - if( e->flg ) { - if( e->volume ) tr->vpos = e->note; - else tr->vpos = 0xff; - tr->volume = e->volume; - tr->vtracktick = e->tracktick; - } - if( e->fx == prog ) tr->instr = e->fxparam; -} - -static void mid_sync_track(MIDTRACK *tr, ULONG tracktime) -{ - MIDEVENT *e; - e = tr->workevent; - if( e && e->tracktick > tracktime ) e = tr->head; // start again.... - for( ; e && e->tracktick <= tracktime; e=e->next ) { - tr->workevent = e; - mid_update_track(tr); - } -} - -// ===================================================================================== -static MIDTRACK *mid_find_track(MIDHANDLE *h, int mch, int pos) -// ===================================================================================== -{ - MIDTRACK *tr; - for( tr=h->track; tr; tr=tr->next ) { - mid_sync_track(tr, h->tracktime); - if( tr->chan == mch && tr->vpos == pos ) - return tr; - } - return NULL; -} - -// ===================================================================================== -static MIDTRACK *mid_locate_track(MIDHANDLE *h, int mch, int pos) -// ===================================================================================== -{ - MIDTRACK *tr, *prev, *trunused; - MIDEVENT *e; - int instrno = 1; - int polyphony; - int vol = 0, bal = 0; - int numtracks; - ULONG tmin; - prev = NULL; - trunused = NULL; - polyphony = 0; - numtracks = 0; - tmin = h->midispeed; // minimal distance between note events in track - // look up track with desired channel and pos (note) - for( tr=h->track; tr; tr=tr->next ) { - mid_sync_track(tr, h->tracktime); - if( tr->chan == mch ) { - if( tr->vpos == pos ) - return tr; - if( tr->vpos == 0xff ) { - // check if track with silence is quiet long enough - if( h->tracktime > tr->vtracktick + tmin ) trunused = tr; - } - else vol = tr->volume; - instrno = tr->instr; - bal = tr->balance; - polyphony++; - } - numtracks++; - prev = tr; - } - if( trunused ) { - trunused->vpos = pos; - return trunused; - } - if( polyphony > MAX_POLYPHONY || (polyphony > 0 && numtracks > MAX_TRACKS) ) { // do not use up too much channels - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - e = tr->workevent; - if( h->tracktime > e->tracktick + tmin ) { - tmin = h->tracktime - e->tracktick; - trunused = tr; - } - } - } - if( trunused ) { - trunused->vpos = pos; - return trunused; - } - } - if( numtracks > MAX_TRACKS ) { // we can not allocate new tracks - tmin = 0; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - e = tr->workevent; - if( h->tracktime >= e->tracktick + tmin ) { - tmin = h->tracktime - e->tracktick; - trunused = tr; - } - } - } - if( trunused ) { - trunused->vpos = pos; - return trunused; - } - tmin = 0; - for( tr=h->track; tr; tr=tr->next ) { - e = tr->workevent; - if( h->tracktime >= e->tracktick + tmin ) { - tmin = h->tracktime - e->tracktick; - trunused = tr; - } - } - if( trunused ) { - trunused->vpos = pos; - trunused->chan = mch; - return trunused; - } - } - tr = mid_new_track(h, mch, pos); - tr->instr = instrno; - tr->volume = vol; - tr->balance = bal; - if( prev ) prev->next = tr; - else h->track = tr; - return tr; -} - -static void mid_add_event(MIDHANDLE *h, MIDTRACK *tp, MIDEVENT *e) -{ - MIDEVENT *ew, *ep; - ep = NULL; - ew = tp->workevent; - if( ew && ew->tracktick > e->tracktick ) ew = tp->head; // start again from the beginning... - for( ; ew && ew->tracktick <= e->tracktick; ew = ew->next ) { - ep = ew; - tp->workevent = ew; - mid_update_track(tp); - } - if( ep ) { - ep->next = e; - e->next = ew; - } - else { - e->next = tp->head; - tp->head = e; - } - if( !e->next ) - tp->tail = e; - tp->workevent = e; - mid_update_track(tp); -} - -static void mid_add_tempo_event(MIDHANDLE *h, int tempo) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 0; - e->fx = tmpo; - e->fxparam = tempo; - mid_add_event(h, h->track, e); -} - -static void mid_add_partbreak(MIDHANDLE *h) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 0; - e->fx = fxbrk; - mid_add_event(h, h->track, e); -} - -static void mid_add_noteoff(MIDHANDLE *h, MIDTRACK *tp) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 1; - e->note = tp->vpos; - e->smpno = tp->instr; - mid_add_event(h, tp, e); -} - -static void mid_add_noteon(MIDHANDLE *h, MIDTRACK *tp, int n, int vol) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 1; - e->note = n; - e->smpno = tp->instr; - e->volume = vol; - mid_add_event(h, tp, e); -} - -static BYTE modtremolo(int midimod) -{ - int m; - if( midimod == 0 ) return 0; - if( midimod > 63 ) { - m = (128 - midimod) / 4; - if( m==0 ) m = 1; - return m|0xf0; // find slide down - } - m = midimod / 4; - if( m==0 ) m = 1; - return (m<<4)|0x0f; // find slide up -} - -// ===================================================================================== -static void mid_mod_wheel(MIDHANDLE *h, int mch, int mod) -// ===================================================================================== -{ - MIDTRACK *tr; - MIDEVENT *e; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - mid_sync_track(tr, h->tracktime); - if( tr->vpos != 0xff ) { // only on tracks with notes on... - e = mid_new_event(h); - e->flg = 0; - e->fx = modwheel; - e->fxparam = modtremolo(mod); - mid_add_event(h, tr, e); - } - } - } -} - -// ===================================================================================== -static void mid_main_volume(MIDHANDLE *h, int mch, int vol) -// ===================================================================================== -{ - MIDTRACK *tr; - MIDEVENT *e; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - e = mid_new_event(h); - e->flg = 0; - e->fx = mainvol; - e->fxparam = vol; - mid_add_event(h, tr, e); - } - } -} - -// transform 0..63..127 to left..center..right in 2n+1 areas -static int modpan(int midipan, int n) -{ - int npan, area, x; - x = 2 * n + 1; - area = (midipan * x * (PAN_RIGHT - PAN_LEFT))>>7; - npan = (PAN_LEFT * x + area) / x; - return npan; -} - -// ===================================================================================== -static void mid_pan(MIDHANDLE *h, int mch, int pan) -// ===================================================================================== -{ - MIDTRACK *tr; - int hits; - hits = 0; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - hits++; - tr->balance = pan; - } - } - if( !hits ) { - tr = mid_locate_track(h, mch, 0xff); - tr->balance = pan; - } -} - -// ===================================================================================== -static void mid_add_program(MIDHANDLE *h, int mch, int pr) -// ===================================================================================== -{ - MIDTRACK *tr; - MIDEVENT *e; - int hits; - hits = 0; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - hits++; - e = mid_new_event(h); - e->flg = 0; - e->fx = prog; - e->fxparam = pat_gmtosmp(pr + 1); - mid_add_event(h, tr, e); - } - } - if( !hits ) { - tr = mid_locate_track(h, mch, 0xff); - e = mid_new_event(h); - e->flg = 0; - e->fx = prog; - e->fxparam = pat_gmtosmp(pr + 1); - mid_add_event(h, tr, e); - } -} - -// ===================================================================================== -static void mid_all_notes_off(MIDHANDLE *h, int mch) -// ===================================================================================== -{ - MIDTRACK *tr; - if( h->debug ) printf("%ld %d all notes off\n",(long)(h->tracktime), mch+1); - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch || mch == -1 ) { - mid_sync_track(tr, h->tracktime); - if( tr->vpos != 0xff ) - mid_add_noteoff(h, tr); - } - } -} - -#ifndef NEWMIKMOD -static void mid_add_sync(MIDHANDLE *h, MIDTRACK *tp) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 0; - e->fx = fxsync; - mid_add_event(h, tp, e); -} -#endif - -static BYTE mid_to_mod_wheel(unsigned int midwheel) -{ - unsigned int i; - if( midwheel == 0 ) return 0; - i = midwheel >> WHEELSHIFT; - return i+1; -} - -static void mid_add_wheel(MIDHANDLE *h, MIDTRACK *tp, int wheel) -{ - MIDEVENT *e; - e = mid_new_event(h); - e->flg = 0; - if( wheel < 0 ) { - e->fx = wheeldown; - e->fxparam = mid_to_mod_wheel(-wheel); - } - else { - e->fx = wheelup; - e->fxparam = mid_to_mod_wheel(wheel); - } - mid_add_event(h, tp, e); -} - -static void mid_add_pitchwheel(MIDHANDLE *h, int mch, int wheel) -{ - MIDTRACK *tr; - int hits; - hits = 0; - for( tr=h->track; tr; tr=tr->next ) { - if( tr->chan == mch ) { - hits++; - mid_sync_track(tr, h->tracktime); - if( tr->vpos != 0xff ) // only on tracks with notes on... - mid_add_wheel(h, tr, wheel); - } - } - if( !hits ) { // special case in midiformat 1 events in first track... - tr = mid_locate_track(h, mch, 0xff); - mid_add_wheel(h, tr, wheel); - } -} - -static long int mid_read_long(MIDHANDLE *h) -{ - BYTE buf[4]; - mmreadUBYTES(buf, 4, h->mmf); - return (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3]; -} - -static short int mid_read_short(MIDHANDLE *h) -{ - BYTE buf[2]; - mmreadUBYTES(buf, 2, h->mmf); - return (buf[0]<<8)|buf[1]; -} - -static BYTE mid_read_byte(MIDHANDLE *h) -{ - return mmreadUBYTE(h->mmf); -} - -static int mid_read_delta(MIDHANDLE *h) -{ - BYTE bits; - int i, d; - d = 0; - for( i=0; i<4; ) { - bits = mid_read_byte(h); - i++; - d = (d<<7)|(bits&0x7f); - if( !(bits & 0x80) ) - break; - } - h->deltatime = d; - return i; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -BOOL MID_Test(MMSTREAM *mmfile) -#else -BOOL CSoundFile::TestMID(const BYTE *lpStream, DWORD dwMemLength) -#endif -// ===================================================================================== -{ - char id[5]; - MIDHANDLE h; -#ifdef NEWMIKMOD - h.mmf = mmfile; -#else - MMFILE mm; - mm.mm = (char *)lpStream; - mm.sz = dwMemLength; - h.mmf = &mm; -#endif - mmfseek(h.mmf,0,SEEK_SET); - mmreadSBYTES(id, 4, h.mmf); - id[4] = '\0'; - return !strcmp(id,"MThd") && mid_read_long(&h) == 6; -} - -// ===================================================================================== -static MIDHANDLE *MID_Init(void) -{ - MIDHANDLE *retval; -#ifdef NEWMIKMOD - MM_ALLOC *allochandle; - - allochandle = _mmalloc_create("Load_MID", NULL); - retval = (MIDHANDLE *)_mm_calloc(allochandle, 1,sizeof(MIDHANDLE)); - if( !retval ) return NULL; - retval->allochandle = allochandle; - allochandle = _mmalloc_create("Load_ABC_tracks", NULL); - retval->trackhandle = allochandle; -#else - retval = (MIDHANDLE *)calloc(1,sizeof(MIDHANDLE)); - if( !retval ) return NULL; -#endif - retval->track = NULL; - retval->percussion = 0; - retval->debug = NULL; - return retval; -} - -#ifndef NEWMIKMOD -static void MID_CleanupTrack(MIDTRACK *tp) -{ - MIDEVENT *ep, *en; - if( tp ) { - for( ep=tp->head; ep; ep = en ) { - en=ep->next; - free(ep); - } - tp->head = NULL; - } -} -#endif - -// ===================================================================================== -static void MID_CleanupTracks(MIDHANDLE *handle) -// ===================================================================================== -{ -#ifdef NEWMIKMOD - if(handle && handle->trackhandle) { - _mmalloc_close(handle->trackhandle); - handle->trackhandle = 0; - } -#else - MIDTRACK *tp, *tn; - if(handle) { - for( tp=handle->track; tp; tp = tn ) { - tn=tp->next; - MID_CleanupTrack(tp); - } - handle->track = NULL; - } -#endif -} - -// ===================================================================================== -static void MID_Cleanup(MIDHANDLE *handle) -// ===================================================================================== -{ -#ifdef NEWMIKMOD - if(handle && handle->allochandle) { - MID_CleanupTracks(handle); - _mmalloc_close(handle->allochandle); - handle->allochandle = 0; - } -#else - if(handle) { - MID_CleanupTracks(handle); - free(handle); - handle = 0; - } -#endif -} - -static int mid_is_global_event(MIDEVENT *e) -{ - return (e->fx == tmpo || e->fx == fxbrk); -} - -static MIDEVENT *mid_next_global(MIDEVENT *e) -{ - for( ; e && !mid_is_global_event(e); e=e->next ) ; - return e; -} - -static MIDEVENT *mid_next_fx(MIDEVENT *e) -{ - for( ; e && e->fx == none; e=e->next ) ; - return e; -} - -static int mid_is_note_event(MIDEVENT *e) -{ -#ifdef LOOPED_NOTES_OFF - return (e->flg == 0); -#else - if( e->flg == 0 ) return 0; - if( e->volume ) return 1; - return pat_smplooped(e->smpno); // let non looping samples die out... -#endif -} - -static MIDEVENT *mid_next_note(MIDEVENT *e) -{ - for( ; e && !mid_is_note_event(e); e=e->next ) ; - return e; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -static void MID_ReadPatterns(UNIMOD *of, MIDHANDLE *h, int numpat) -// ===================================================================================== -{ - int pat,row,i,ch,trkset; - BYTE n,ins,vol; - MIDTRACK *t; - MIDEVENT *e, *en, *ef, *el; - ULONG tt1, tt2; - UNITRK_EFFECT eff; - - // initialize start points of event list in tracks - for( t = h->track; t; t = t->next ) t->workevent = t->head; - for( pat = 0; pat < numpat; pat++ ) { - utrk_reset(of->ut); - for( row = 0; row < 64; row++ ) { - tt1 = miditicks(h, (pat * 64 + row ) * h->speed); - tt2 = tt1 + h->midispeed; - for( e=mid_next_global(h->track->workevent); e && e->tracktick < tt2; e=mid_next_global(e->next) ) { - if( e && e->tracktick >= tt1 ) { // we have a controller event in this row - switch( e->fx ) { - case tmpo: - eff.effect = UNI_GLOB_TEMPO; - eff.param.u = e->fxparam; - eff.framedly = UFD_RUNONCE; - utrk_write_global(of->ut, &eff, PTMEM_TEMPO); - break; - case fxbrk: - eff.effect = UNI_GLOB_PATBREAK; - eff.param.u = 0; - eff.framedly = UFD_RUNONCE; - utrk_write_global(of->ut, &eff, UNIMEM_NONE); - break; - } - } - } - ch = 0; - for( t = h->track; t; t = t->next ) { - trkset = 0; - e = NULL; - for( el=mid_next_fx(t->workevent); el && el->tracktick < tt2; el=mid_next_fx(el->next) ) { - if( el && el->tracktick >= tt1 ) { - switch( el->fx ) { - case modwheel: - case wheelup: - case wheeldown: - e = el; - default: - break; - } - } - } - if( e ) { // we have a controller event in this row - switch( e->fx ) { - case modwheel: - if( !trkset ) { - utrk_settrack(of->ut, ch); - trkset = 1; - } - eff.effect = UNI_VOLSLIDE; - eff.framedly = UFD_RUNONCE; - if( (e->fxparam & 0x0f) == 0x0f ) - eff.param.s = (e->fxparam >> 3)&0x1f; - else - eff.param.s = -((e->fxparam & 0x0f)*2); - utrk_write_local(of->ut, &eff, STMEM_VOLSLIDE); - break; - case wheelup: - if( !trkset ) { - utrk_settrack(of->ut, ch); - trkset = 1; - } - eff.effect = UNI_PITCHSLIDE; - eff.framedly = UFD_RUNONCE; - eff.param.s = e->fxparam; - utrk_write_local(of->ut, &eff, STMEM_PITCHSLIDE); - break; - case wheeldown: - if( !trkset ) { - utrk_settrack(of->ut, ch); - trkset = 1; - } - eff.effect = UNI_PITCHSLIDE; - eff.framedly = UFD_RUNONCE; - eff.param.s = -(int)(e->fxparam); - utrk_write_local(of->ut, &eff, STMEM_PITCHSLIDE); - break; - } - } - for( e=mid_next_note(t->workevent); e && e->tracktick < tt1; e=mid_next_note(e->next) ) - t->workevent = e; - i = 0; - ef = NULL; - en = e; - el = e; - for( ; e && e->tracktick < tt2; e=mid_next_note(e->next) ) { // we have a note event in this row - t->workevent = e; - i++; - if( e->volume ) { - if( !ef ) ef = e; - el = e; - } - } - if( i ) { - if( !trkset ) { - utrk_settrack(of->ut, ch); - trkset = 1; - } - if( i == 1 || ef == el || !ef ) { // only one event in this row - if( ef ) e = ef; - else e = en; - el = t->workevent; - n = pat_modnote(e->note); - ins = e->smpno; - eff.framedly = modticks(h, e->tracktick - tt1); - eff.param.u = 0; - eff.param.byte_a = n; - eff.param.byte_b = ins; - vol = e->volume; - if( vol == 0 ) { - eff.effect = UNI_NOTEKILL; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - else { - if( el->volume == 0 ) { - eff.framedly = modticks(h, el->tracktick - tt1); - eff.effect = UNI_NOTEKILL; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - else { - if( eff.framedly ) { - eff.effect = UNI_NOTEDELAY; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - } - } - utrk_write_inst(of->ut, ins); - utrk_write_note(of->ut, n); // <- normal note - pt_write_effect(of->ut, 0xc, vol); - } - else { - // two notes in one row, use FINEPITCHSLIDE runonce effect - // start first note on first tick and framedly runonce on seconds note tick - // use volume and instrument of last note - n = pat_modnote(ef->note); - i = pat_modnote(el->note); - ins = el->smpno; - vol = el->volume; - eff.effect = UNI_PITCHSLIDE; - eff.framedly = modticks(h, el->tracktick - tt1)|UFD_RUNONCE; - eff.param.s = ((i > n)?i-n:n-i); - utrk_write_inst(of->ut, ins); - utrk_write_note(of->ut, n); // <- normal note - pt_write_effect(of->ut, 0xc, vol); - utrk_write_local(of->ut, &eff, (i > n)? PTMEM_PITCHSLIDEUP: PTMEM_PITCHSLIDEDN); - } - } - ch++; - } - utrk_newline(of->ut); - } - if(!utrk_dup_pattern(of->ut,of)) return; - } -} - -#else - -static int MID_ReadPatterns(MODCOMMAND *pattern[], WORD psize[], MIDHANDLE *h, int numpat, int channels) -// ===================================================================================== -{ - int pat,row,i,ch; - BYTE n,ins,vol; - MIDTRACK *t; - MIDEVENT *e, *en, *ef, *el; - ULONG tt1, tt2; - MODCOMMAND *m; - int patbrk, tempo; - if( numpat > MAX_PATTERNS ) numpat = MAX_PATTERNS; - - // initialize start points of event list in tracks - for( t = h->track; t; t = t->next ) t->workevent = t->head; - for( pat = 0; pat < numpat; pat++ ) { - pattern[pat] = CSoundFile::AllocatePattern(64, channels); - if( !pattern[pat] ) return 0; - psize[pat] = 64; - for( row = 0; row < 64; row++ ) { - tt1 = miditicks(h, (pat * 64 + row ) * h->speed); - tt2 = tt1 + h->midispeed; - ch = 0; - tempo = 0; - patbrk = 0; - for( e=mid_next_global(h->track->workevent); e && e->tracktick < tt2; e=mid_next_global(e->next) ) { - if( e && e->tracktick >= tt1 ) { // we have a controller event in this row - switch( e->fx ) { - case tmpo: - tempo = e->fxparam; - break; - case fxbrk: - patbrk = 1; - break; - } - } - } - for( t = h->track; t; t = t->next ) { - m = &pattern[pat][row * channels + ch]; - m->param = 0; - m->command = CMD_NONE; - for( e=mid_next_fx(t->workevent); e && e->tracktick < tt2; e=mid_next_fx(e->next) ) { - if( e && e->tracktick >= tt1 ) { // we have a controller event in this row - switch( e->fx ) { - case modwheel: - m->param = e->fxparam; - m->command = CMD_VOLUMESLIDE; - break; - case wheelup: - m->param = e->fxparam|0x10; - m->command = CMD_XFINEPORTAUPDOWN; - break; - case wheeldown: - m->param = e->fxparam|0x20; - m->command = CMD_XFINEPORTAUPDOWN; - break; - } - } - } - for( e=mid_next_note(t->workevent); e && e->tracktick < tt1; e=mid_next_note(e->next) ) - t->workevent = e; - i = 0; - ef = NULL; - en = e; - el = e; - for( ; e && e->tracktick < tt2; e=mid_next_note(e->next) ) { // we have a note event in this row - t->workevent = e; - i++; - if( e->volume ) { - if( !ef ) ef = e; - el = e; - } - } - if( i ) { - if( i == 1 || ef == el || !ef ) { // only one event in this row or a note on with some note off - if( ef ) e = ef; - else e = en; - el = t->workevent; - n = pat_modnote(e->note); - ins = e->smpno; - if( e->volume == 0 ) { - m->param = (BYTE)modticks(h, e->tracktick - tt1); - if( m->param ) { // note cut - m->command = CMD_S3MCMDEX; - m->param |= 0xC0; - } - else { - m->param = 0; - m->command = CMD_KEYOFF; - } - vol = 0; - } - else { - vol = e->volume/2; - if( el->volume == 0 ) { - m->param = (BYTE)modticks(h, el->tracktick - tt1); - if( m->param ) { // note cut - m->command = CMD_S3MCMDEX; - m->param |= 0xC0; - } - } - else { - m->param = (BYTE)modticks(h, e->tracktick - tt1); - if( m->param ) { // note delay - m->command = CMD_S3MCMDEX; - m->param |= 0xD0; - } - } - } - m->instr = ins; - m->note = n; // <- normal note - m->volcmd = VOLCMD_VOLUME; - m->vol = vol; - } - else { - // two notes in one row, use FINEPITCHSLIDE runonce effect - // start first note on first tick and framedly runonce on seconds note tick - // use volume and instrument of last note - n = pat_modnote(ef->note); - i = pat_modnote(el->note); - ins = el->smpno; - vol = el->volume/2; - if( vol > 64 ) vol = 64; - m->instr = ins; - m->note = n; // <- normal note - m->volcmd = VOLCMD_VOLUME; - m->vol = vol; - m->param = ((i > n)?i-n:n-i); - if( m->param < 16 ) { - if( m->param ) { - m->command = CMD_XFINEPORTAUPDOWN; - m->param |= (i > n)? 0x10: 0x20; - } - else { // retrigger same note... - m->command = CMD_RETRIG; - m->param = (BYTE)modticks(h, el->tracktick - tt1); - } - } - else - m->command = (i > n)? CMD_PORTAMENTOUP: CMD_PORTAMENTODOWN; - } - } - if( m->param == 0 && m->command == CMD_NONE ) { - if( tempo ) { - m->command = CMD_TEMPO; - m->param = tempo; - tempo = 0; - } - else { - if( patbrk ) { - m->command = CMD_PATTERNBREAK; - patbrk = 0; - } - } - } - ch++; - } - if( tempo || patbrk ) return 1; - } - } - return 0; -} - -#endif - -static ULONG mid_next_tracktick(MIDEVENT *e) -{ - MIDEVENT *en; - en = e->next; - if( en ) return en->tracktick; - return 0x7fffffff; // practically indefinite -} - -// cut off alle events that follow the given event -static void mid_stripoff(MIDTRACK *tp, MIDEVENT *e) -{ -#ifndef NEWMIKMOD - MIDEVENT *ep, *en; - for( ep=e->next; ep; ep = en ) { - en=ep->next; - free(ep); - } -#endif - e->next = NULL; - tp->tail = e; - tp->workevent = tp->head; - mid_sync_track(tp, e->tracktick); -} - -static void mid_notes_to_percussion(MIDTRACK *tp, ULONG adjust, ULONG tmin) -{ - MIDEVENT *e, *lno = 0; - int n = 0,v; - ULONG ton, toff = 0, tnext; - v = 0x7f; // as loud as it gets - ton = 0; - for( e=tp->head; e; e=e->next ) { - if( e->tracktick < adjust ) e->tracktick = 0; - else e->tracktick -= adjust; - if( e->flg == 1 ) { - if( e->volume > 0 ) { - n = e->note; - e->smpno = pat_gmtosmp(pat_gm_drumnr(n)); - e->note = pat_gm_drumnote(n); - e->volume = (v * e->volume) / 128; - if( v && !e->volume ) e->volume = 1; - ton = e->tracktick; - } - else { - toff = ton + tmin; - if( toff > e->tracktick ) { - tnext = mid_next_tracktick(e); - if( toff + tmin < tnext ) e->tracktick = toff; - else { - if( toff < tnext ) e->tracktick = toff - 1; - else e->tracktick = tnext - 1; - } - } - toff = e->tracktick; - lno = e; - } - } - else { - if( e->fx == mainvol ) { - v = e->fxparam; - if( !v && ton > toff ) { - e->flg = 1; - e->volume = 0; - e->note = pat_gm_drumnote(n); - toff = e->tracktick; - lno = e; - } - } - } - } - if( ton > toff ) { - char info[32]; - sprintf(info,"%ld > %ld note %d", (long)ton, (long)toff, n); - mid_message("drum track ends with note on (%s)", info); - } - if( lno && lno->next ) mid_stripoff(tp, lno); -} - -static void mid_prog_to_notes(MIDTRACK *tp, ULONG adjust, ULONG tmin) -{ - MIDEVENT *e, *lno = 0; - int i = 0, n = 0, v = 0x7f; - ULONG ton, toff = 0, tnext; - ton = 0; - for( e=tp->head; e; e=e->next ) { - if( e->tracktick < adjust ) e->tracktick = 0; - else e->tracktick -= adjust; - if( e->flg == 1 ) { - if( !i ) i = pat_gmtosmp(1); // happens in eternal2.mid - e->smpno = i; - n = e->note; - if( e->volume > 0 ) { - e->volume = (v * e->volume) / 128; - if( v && !e->volume ) e->volume = 1; - ton = e->tracktick; - } - else { - toff = ton + tmin; - if( toff > e->tracktick ) { - tnext = mid_next_tracktick(e); - if( toff + tmin < tnext ) e->tracktick = toff; - else { - if( toff < tnext ) e->tracktick = toff - 1; - else e->tracktick = tnext - 1; - } - } - toff = e->tracktick; - lno = e; - } - } - else { - if( e->fx == prog ) i = e->fxparam; - if( e->fx == mainvol ) { - v = e->fxparam; - if( !v && ton > toff ) { - e->flg = 1; - e->volume = 0; - e->note = n; - toff = e->tracktick; - lno = e; - } - } - } - } - if( ton > toff ) { - char info[40]; - sprintf(info,"channel %d, %ld > %ld note %d", tp->chan + 1, (long)ton, (long)toff, n); - mid_message("melody track ends with note on (%s)", info); - } - if( lno && lno->next ) mid_stripoff(tp, lno); -} - -static int midiword(BYTE *b) -{ - int i; - i = (b[0]&0x7f)|((b[1]&0x7f)<<7); - return i; -} - -static int midishort(BYTE *b) -{ - return midiword(b) - 0x2000; -} - -ULONG mid_first_noteonevent_tick(MIDEVENT *e) -{ - while( e && (e->flg == 0 || e->volume == 0) ) e=e->next; - if( !e ) return 0x7fffffff; - return e->tracktick; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -BOOL MID_Load(MIDHANDLE *h, UNIMOD *of, MMSTREAM *mmfile) -#else -BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) -#endif -{ - static int avoid_reentry = 0; -#ifdef NEWMIKMOD -#define m_nDefaultTempo of->inittempo -#else - MIDHANDLE *h; - MMFILE mm; -#endif - int ch, dmulti, maxtempo, panlow, panhigh, numchans, numtracks; - MIDTRACK *ttp; - uint32_t t, numpats; - char buf[256]; - long miditracklen; - BYTE runningstatus; - BYTE cmd; - BYTE midibyte[2]; - long metalen, delta; - BYTE *p; - while( avoid_reentry ) sleep(1); - avoid_reentry = 1; -#ifdef NEWMIKMOD - h->mmf = mmfile; -#else - if( !TestMID(lpStream, dwMemLength) ) { - avoid_reentry = 0; - return FALSE; - } - h = MID_Init(); - if( !h ) { - avoid_reentry = 0; - return FALSE; - } - h->mmf = &mm; - mm.mm = (char *)lpStream; - mm.sz = dwMemLength; - mm.pos = 0; -#endif - h->debug = getenv(ENV_MMMID_DEBUG); - h->verbose = getenv(ENV_MMMID_VERBOSE); - pat_resetsmp(); - pat_init_patnames(); - mmfseek(h->mmf,8,SEEK_SET); - h->midiformat = mid_read_short(h); - h->miditracks = mid_read_short(h); - h->resolution = mid_read_short(h); - // at this point the h->mmf is positioned at first miditrack - if( h->midiformat == 0 ) h->miditracks = 1; - if( h->resolution & 0x8000 ) - h->divider = ((h->resolution & 0x7f00)>>8)*(h->resolution & 0xff); - else - h->divider = h->resolution; - h->divider <<= 2; // ticks per quartnote ==> ticks per note - h->tempo = 122; - m_nDefaultTempo = 0; - h->tracktime = 0; - h->speed = 6; - p = (BYTE *)getenv(ENV_MMMID_SPEED); - if( p && isdigit(*p) && p[0] != '0' && p[1] == '\0' ) { - // transform speed - t = *p - '0'; - h->speed *= t; - h->divider *= t; - h->speed /= 6; - h->divider /= 6; - } - // calculate optimal delta multiplier dmulti keeping tempo adjustments - // from 10 to 255 in mind (hoping there will be no midi's with tempo's - // lower than 10, that is sooo sick...) - // this is necessary for the tracks to patterns routine - dmulti = 1; - maxtempo = h->divider; - while( (h->midispeed = miditicks(h, h->speed)) * 10 < 255 * h->speed ) { - ++dmulti; - h->divider = maxtempo * dmulti; - } - h->tp = NULL; - memset(buf,0,sizeof(buf)); -#ifdef NEWMIKMOD - of->songname = NULL; -#else - strcpy(m_szNames[0], ""); -#endif - maxtempo = 0; - panlow = 64; - panhigh = 64; - if( h->verbose ) { - printf("Scanning MIDI with format: %d resolution: %d tracks: %d\n", - h->midiformat, - h->resolution, - h->miditracks); - } - if( h->verbose && dmulti > 1 ) { - printf("Multiplying resolution and deltatimes by %d to get %d miditicks per patternrow\n", - dmulti, h->midispeed); - } - for( t=0; t<(uint32_t)h->miditracks; t++ ) { - if( h->verbose ) printf("Parsing track %d\n", t+1); - mmreadSBYTES(buf,4,h->mmf); - buf[4] = '\0'; - if( strcmp(buf,"MTrk") ) { - mid_message("invalid track-chunk '%s' is not 'MTrk'",buf); - avoid_reentry = 0; - return FALSE; - } - miditracklen = mid_read_long(h); - runningstatus = 0; - if( t && h->midiformat == 1 ) mid_rewind_tracks(h); // tracks sound simultaneously - while( miditracklen > 0 ) { - miditracklen -= mid_read_delta(h); - midibyte[0] = mid_read_byte(h); - miditracklen--; - if( midibyte[0] & 0x80 ) { - runningstatus = midibyte[0]; - switch( runningstatus ) { - case 0xf1: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - case 0xf8: - case 0xf9: - case 0xfa: - case 0xfb: - case 0xfc: - case 0xfd: - case 0xfe: - break; - default: - midibyte[0] = mid_read_byte(h); - miditracklen--; - break; - } - } - h->tracktime += dmulti * h->deltatime; - ch = runningstatus & 0x0f; - cmd = runningstatus & 0xf0; - switch( cmd ) { - case 0x80: // note off - midibyte[1] = mid_read_byte(h); - miditracklen--; - ttp = mid_find_track(h, ch, midibyte[0]); - if( ttp ) mid_add_noteoff(h, ttp); - if( h->debug ) - printf("%2d %08ld Note off: ch %d 0x%02x 0x%02x\n", - t, (long)(h->tracktime), - ch + 1, midibyte[0], midibyte[1]); - break; - case 0x90: // note on - midibyte[1] = mid_read_byte(h); - miditracklen--; - if( midibyte[1] ) { - ttp = mid_locate_track(h, ch, midibyte[0]); - mid_add_noteon(h, ttp, midibyte[0], midibyte[1]); - if( h->debug ) - printf("%2d %08ld Note on: ch %d 0x%02x 0x%02x\n", - t, (long)(h->tracktime), - ch + 1, midibyte[0], midibyte[1]); - } - else { - ttp = mid_find_track(h, ch, midibyte[0]); - if( ttp ) mid_add_noteoff(h, ttp); - if( h->debug ) - printf("%2d %08ld note off: ch %d 0x%02x\n", - t, (long)(h->tracktime), - ch + 1, midibyte[0]); - } - break; - case 0xa0: // polyphonic key pressure - midibyte[1] = mid_read_byte(h); - miditracklen--; - if( h->debug ) - printf("%2d %08ld polyphonic key pressure: ch %d 0x%02x 0x%02x\n", t, (long)(h->tracktime), ch + 1, midibyte[0], midibyte[1]); - break; - case 0xb0: // control change - midibyte[1] = mid_read_byte(h); - miditracklen--; - switch(midibyte[0]) { - case 0x01: // mod wheel - mid_mod_wheel(h, ch, midibyte[1]); - break; - case 0x07: // main volume - mid_main_volume(h, ch, midibyte[1]); - break; - case 0x0a: // pan - if( midibyte[1] < panlow ) panlow = midibyte[1]; - if( midibyte[1] > panhigh ) panhigh = midibyte[1]; - mid_pan(h, ch, midibyte[1]); - break; - case 0x0b: // expression - break; - case 0x7b: - if( midibyte[1] == 0x00 ) // all notes off - mid_all_notes_off(h, ch); - break; - default: - break; - } - if( h->debug ) - printf("%2d %08ld control change: ch %d 0x%02x 0x%02x\n", - t, (long)(h->tracktime), ch + 1, midibyte[0], midibyte[1]); - break; - case 0xc0: // program change - mid_add_program(h, ch, midibyte[0]); - if( h->debug ) - printf("%2d %08ld program change: ch %d %d\n", - t, (long)(h->tracktime), ch + 1, midibyte[0]); - break; - case 0xd0: // channel pressure - if( h->debug ) - printf("%2d %08ld channel pressure: ch %d 0x%02x\n", t, (long)(h->tracktime), ch + 1, midibyte[0]); - break; - case 0xe0: // pitch wheel change - midibyte[1] = mid_read_byte(h); - miditracklen--; - if( h->debug ) - printf("%2d %08ld pitch wheel change: ch %d %d\n", - t, (long)(h->tracktime), ch + 1, midishort(midibyte)); - mid_add_pitchwheel(h, ch, midishort(midibyte)); - break; - case 0xf0: // system & realtime - switch( runningstatus ) { - case 0xf0: // sysex - if( h->debug ) printf("%2d %08ld sysex: 0x%02x", - t, (long)(h->tracktime), midibyte[0]); - while( midibyte[0] != 0xf7 ) { - midibyte[0] = mid_read_byte(h); - miditracklen--; - if( h->debug ) printf(" %02X", midibyte[0]); - } - if( h->debug ) printf("\n"); - break; - case 0xf2: // song position pointer - midibyte[1] = mid_read_byte(h); - miditracklen--; - if( h->debug ) - printf("%2d %08ld song position pointer: %d", - t, (long)(h->tracktime), midishort(midibyte)); - break; - case 0xf7: - delta = h->deltatime; - miditracklen -= mid_read_delta(h); - metalen = h->deltatime; - if( h->debug ) - printf("%2d %08ld sysex continued: %ld", - t, (long)(h->tracktime), metalen); - while( metalen > 0 ) { - midibyte[1] = mid_read_byte(h); - metalen--; - miditracklen--; - if( h->debug ) printf(" %02X", midibyte[1]); - } - h->deltatime = delta; - break; - case 0xff: // meta event - delta = h->deltatime; - miditracklen -= mid_read_delta(h); - metalen = h->deltatime; - if( metalen > 31 ) metalen = 31; - if( metalen ) { - mmreadSBYTES(buf, metalen, h->mmf); - miditracklen -= metalen; - } - buf[metalen] = '\0'; - metalen = h->deltatime - metalen; - while( metalen > 0 ) { - midibyte[1] = mid_read_byte(h); - metalen--; - miditracklen--; - } - h->deltatime = delta; - switch( midibyte[0] ) { - case 0x03: // type: track name - if( h->debug ) - printf("%2d %08ld META trackname:%s\n", t, (long)(h->tracktime), buf); -#ifdef NEWMIKMOD - if( !of->songname ) - of->songname = DupStr(of->allochandle, buf, strlen(buf)); -#else - if( m_szNames[0][0] == '\0' ) - strcpy(m_szNames[0], buf); -#endif - break; - case 0x51: // type: tempo - p=(BYTE *)buf; - delta = (p[0]<<16)|(p[1]<<8)|p[2]; - if( delta ) - h->tempo = 60000000 / delta; - if( h->debug ) printf("%2d %08ld META tempo:%d\n", t, (long)(h->tracktime), h->tempo); - if( m_nDefaultTempo == 0 ) m_nDefaultTempo = h->tempo; - else { - ttp = h->track; - if( !ttp ) ttp = mid_locate_track(h, 0, 0xff); - mid_add_tempo_event(h,h->tempo); - } - if( h->tempo > maxtempo ) maxtempo = h->tempo; - break; - case 0x2f: // type: end of track - if( h->debug ) printf("%2d %08ld META end of track\n", t, (long)(h->tracktime)); - if( miditracklen > 0 ) { - sprintf(buf, "%ld", miditracklen); - mid_message("Meta event not at end of track, %s bytes left in track", buf); - miditracklen = 0; - } - break; - default: - if( h->debug ) printf("%2d %08ld META type 0x%02x\n", t, (long)(h->tracktime), midibyte[0]); - break; - } - break; - default: - if( h->debug ) printf("%2d %08ld System type 0x%02x\n", t, (long)(h->tracktime), midibyte[0]); - break; - } - break; - default: // no running status, just skip it... - if( h->debug ) printf("%2d %08ld unknown runningstatus: 0x%02x skipped:0x%02x\n", t, (long)(h->tracktime), runningstatus, midibyte[0]); - break; - } - if( miditracklen < 1 && (runningstatus != 0xff || midibyte[0] != 0x2f) ) { - delta = mmftell(h->mmf); - mmreadSBYTES(buf,4,h->mmf); - buf[4] = '\0'; - if( strcmp(buf,"MTrk") ) { - miditracklen = 0x7fffffff; - mid_message("Meta event not at end of track, %s bytes left in track", "superfluous"); - } - else - mid_message("Meta event not at end of track, %s bytes left in track", "no"); - mmfseek(h->mmf,delta,SEEK_SET); - } - } - } - if( h->verbose ) printf("Determining percussion channel\n"); - // get the lowest event time and the used channels - delta = 0x7fffffff; - metalen = 0; // use as bit bucket for used channels - for( ttp=h->track; ttp; ttp=ttp->next ) { - metalen |= (1<chan); - if( ttp->head ) { - ULONG tt; - tt = mid_first_noteonevent_tick(ttp->head); - if( tt < (ULONG)delta ) - delta = tt; - } - } - if( metalen & 0x03ff ) { - if( (metalen & 0x0f00) == 0x0400 ) - h->percussion = 10; // buggy sng2mid uses channel 10 - else - h->percussion = 9; - } - else h->percussion = 15; - if( h->verbose ) - printf("Percussion channel is %d\nStripping off silences and other optimalisations\n", h->percussion + 1); - // last but not least shut off all pending events, transform drumnotes when appropriate - // strip off silences at begin and end and get the greatest tracktime - h->tracktime = 0; - metalen = h->midispeed; - for( ttp=h->track; ttp; ttp=ttp->next ) { - if( ttp->chan == h->percussion ) - mid_notes_to_percussion(ttp, delta, metalen); - else - mid_prog_to_notes(ttp, delta, metalen); - if( ttp->tail && ttp->tail->tracktick > h->tracktime ) - h->tracktime = ttp->tail->tracktick; - } - h->tracktime += h->divider >> 2; // add one quartnote to the song for silence - mid_add_partbreak(h); - if( h->debug ) - mid_dump_tracks(h); - numchans = mid_numchans(h); - if( panlow > 48 || panhigh < 80 ) { - for( ttp=h->track; ttp; ttp=ttp->next ) { - ttp->balance = ((0x40*numchans+0x80*mid_ordchan(h, ttp->chan))/numchans)&0x7f; - } - } - // set module variables - numtracks = mid_numtracks(h); - if( m_nDefaultTempo == 0 ) m_nDefaultTempo = h->tempo; - if( maxtempo == 0 ) maxtempo = h->tempo; - if( maxtempo != 255 ) { - if( h->verbose ) printf("Adjusting tempo %d to 255\n", maxtempo); - mid_adjust_for_optimal_tempo(h, maxtempo); - } - if( maxtempo > 0 ) m_nDefaultTempo = (255 * m_nDefaultTempo) / maxtempo; - numpats = 1 + (modticks(h, h->tracktime) / h->speed / 64 ); - if( h->verbose ) printf("Generating %d patterns with speed %d\n", numpats, h->speed); -#ifdef NEWMIKMOD - if( !of->songname ) of->songname = DupStr(of->allochandle, "Untitled", 8); - of->memsize = STMEM_LAST; // Number of memory slots to reserve! - of->modtype = _mm_strdup(of->allochandle, MID_Version); - of->numpat = numpats; - of->numpos = of->numpat; - of->reppos = 0; - of->initspeed = h->speed; - of->numchn = numtracks; - of->numtrk = of->numpat * of->numchn; - of->initvolume = 64; - of->pansep = 128; - // orderlist - if(!AllocPositions(of, of->numpos)) { - avoid_reentry = 0; - return FALSE; - } - for(t=0; tnumpos; t++) - of->positions[t] = t; - if( !PAT_Load_Instruments(of) ) { - avoid_reentry = 0; - return FALSE; - } - // ============================== - // Load the pattern info now! - if(!AllocTracks(of)) { - avoid_reentry = 0; - return FALSE; - } - if(!AllocPatterns(of)) { - avoid_reentry = 0; - return FALSE; - } - of->ut = utrk_init(of->numchn, h->allochandle); - utrk_memory_reset(of->ut); - utrk_local_memflag(of->ut, PTMEM_PORTAMENTO, TRUE, FALSE); - MID_ReadPatterns(of, h, numpats); - // ============================================================ - // set panning positions - t = 0; - for( ttp=h->track; ttp; ttp=ttp->next ) { - of->panning[t] = modpan(ttp->balance, numchans / 2); - t++; - } -#else - m_nType = MOD_TYPE_MID; - m_nDefaultSpeed = h->speed; - m_nChannels = numtracks; - m_dwSongFlags = SONG_LINEARSLIDES; - m_nMinPeriod = 28 << 2; - m_nMaxPeriod = 1712 << 3; - // orderlist - for(t=0; t < numpats; t++) - Order[t] = t; - if( !PAT_Load_Instruments(this) ) { - avoid_reentry = 0; - return FALSE; - } - // ============================== - // Load the pattern info now! - if( MID_ReadPatterns(Patterns, PatternSize, h, numpats, m_nChannels) ) { - // :^( need one more channel to handle the global events ;^b - m_nChannels++; - h->tp = mid_new_track(h, h->track->chan, 0xff); - for( ttp=h->track; ttp->next; ttp=ttp->next ) ; - ttp->next = h->tp; - mid_add_sync(h, h->tp); - for( t=0; ttrack; ttp; ttp=ttp->next ) { - ChnSettings[t].nPan = modpan(ttp->balance, numchans / 2); - ChnSettings[t].nVolume = 64; - t++; - } - MID_Cleanup(h); // we dont need it anymore -#endif - if( h->verbose ) printf("Done\n"); - avoid_reentry = 0; // it is safe now, I'm finished - return TRUE; -} - -#ifdef NEWMIKMOD -// ===================================================================================== -CHAR *MID_LoadTitle(MMSTREAM *mmfile) -// ===================================================================================== -{ - int t; - char buf[24]; - long miditracklen; - BYTE runningstatus; - BYTE cmd; - BYTE midibyte[2]; - long metalen; - MIDHANDLE hh, *h; - h = &hh; - h->mmf = mmfile; - mmfseek(h->mmf,8,SEEK_SET); - h->midiformat = mid_read_short(h); - h->miditracks = mid_read_short(h); - h->resolution = mid_read_short(h); - // at this point the h->mmf is positioned at first miditrack - if( h->midiformat == 0 ) h->miditracks = 1; - h->tracktime = 0; - for( t=0; tmiditracks; t++ ) { - mmreadSBYTES(buf,4,h->mmf); - miditracklen = mid_read_long(h); - runningstatus = 0; - while( miditracklen > 0 ) { - miditracklen -= mid_read_delta(h); - midibyte[0] = mid_read_byte(h); - miditracklen--; - if( midibyte[0] & 0x80 ) { - runningstatus = midibyte[0]; - switch( runningstatus ) { - case 0xf1: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - case 0xf8: - case 0xf9: - case 0xfa: - case 0xfb: - case 0xfc: - case 0xfd: - case 0xfe: - break; - default: - midibyte[0] = mid_read_byte(h); - miditracklen--; - break; - } - } - cmd = runningstatus & 0xf0; - switch( cmd ) { - case 0x80: // note off - case 0x90: // note on - case 0xa0: // polyphonic key pressure - case 0xb0: // control change - case 0xe0: // pitch wheel change - midibyte[1] = mid_read_byte(h); - miditracklen--; - case 0xc0: // program change - case 0xd0: // channel pressure - break; - case 0xf0: // system & realtime - switch( runningstatus ) { - case 0xf0: // sysex - while( midibyte[0] != 0xf7 ) { - midibyte[0] = mid_read_byte(h); - miditracklen--; - } - break; - case 0xf2: // song position pointer - midibyte[1] = mid_read_byte(h); - miditracklen--; - break; - case 0xf7: - miditracklen -= mid_read_delta(h); - metalen = h->deltatime; - while( metalen > 0 ) { - midibyte[1] = mid_read_byte(h); - metalen--; - miditracklen--; - } - break; - case 0xff: // meta event - miditracklen -= mid_read_delta(h); - metalen = h->deltatime; - if( metalen > 21 ) metalen = 21; - if( metalen ) { - mmreadSBYTES(buf, metalen, h->mmf); - miditracklen -= metalen; - } - buf[metalen] = '\0'; - metalen = h->deltatime - metalen; - while( metalen > 0 ) { - midibyte[1] = mid_read_byte(h); - metalen--; - miditracklen--; - } - switch( midibyte[0] ) { - case 0x03: // type: track name - return DupStr(NULL, buf, strlen(buf)); - break; - case 0x2f: // type: end of track - miditracklen = 0; - break; - default: - break; - } - break; - default: - break; - } - break; - default: // no running status, just skip it... - break; - } - if( miditracklen < 1 && (runningstatus != 0xff || midibyte[0] != 0x2f) ) { - metalen = mmftell(h->mmf); - mmreadSBYTES(buf,4,h->mmf); - buf[4] = '\0'; - if( strcmp(buf,"MTrk") ) miditracklen = 0x7fffffff; - mmfseek(h->mmf,metalen,SEEK_SET); - } - } - } - return DupStr(NULL, "Untitled" ,8); -} - -MLOADER load_mid = -{ - "MID", - "Musical Instrument Digital Interface", - 0x30, - NULL, - MID_Test, - (void *(*)(void))MID_Init, - (void (*)(ML_HANDLE *))MID_Cleanup, - /* Every single loader seems to need one of these! */ - (BOOL (*)(ML_HANDLE *, UNIMOD *, MMSTREAM *))MID_Load, - MID_LoadTitle -}; -#endif diff --git a/jni/load_mod.cpp b/jni/load_mod.cpp deleted file mode 100644 index 57304ac..0000000 --- a/jni/load_mod.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque , - * Adam Goode (endian and char fixes for PPC) -*/ - -#include "stdafx.h" -#include "sndfile.h" -#include "tables.h" - -#ifdef _MSC_VER -//#pragma warning(disable:4244) -#endif - -////////////////////////////////////////////////////////// -// ProTracker / NoiseTracker MOD/NST file support - -void CSoundFile::ConvertModCommand(MODCOMMAND *m) const -//----------------------------------------------------- -{ - UINT command = m->command, param = m->param; - - switch(command) - { - case 0x00: if (param) command = CMD_ARPEGGIO; break; - case 0x01: command = CMD_PORTAMENTOUP; break; - case 0x02: command = CMD_PORTAMENTODOWN; break; - case 0x03: command = CMD_TONEPORTAMENTO; break; - case 0x04: command = CMD_VIBRATO; break; - case 0x05: command = CMD_TONEPORTAVOL; if (param & 0xF0) param &= 0xF0; break; - case 0x06: command = CMD_VIBRATOVOL; if (param & 0xF0) param &= 0xF0; break; - case 0x07: command = CMD_TREMOLO; break; - case 0x08: command = CMD_PANNING8; break; - case 0x09: command = CMD_OFFSET; break; - case 0x0A: command = CMD_VOLUMESLIDE; if (param & 0xF0) param &= 0xF0; break; - case 0x0B: command = CMD_POSITIONJUMP; break; - case 0x0C: command = CMD_VOLUME; break; - case 0x0D: command = CMD_PATTERNBREAK; param = ((param >> 4) * 10) + (param & 0x0F); break; - case 0x0E: command = CMD_MODCMDEX; break; - case 0x0F: command = (param <= (UINT)((m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? 0x1F : 0x20)) ? CMD_SPEED : CMD_TEMPO; - if ((param == 0xFF) && (m_nSamples == 15)) command = 0; break; - // Extension for XM extended effects - case 'G' - 55: command = CMD_GLOBALVOLUME; break; - case 'H' - 55: command = CMD_GLOBALVOLSLIDE; if (param & 0xF0) param &= 0xF0; break; - case 'K' - 55: command = CMD_KEYOFF; break; - case 'L' - 55: command = CMD_SETENVPOSITION; break; - case 'M' - 55: command = CMD_CHANNELVOLUME; break; - case 'N' - 55: command = CMD_CHANNELVOLSLIDE; break; - case 'P' - 55: command = CMD_PANNINGSLIDE; if (param & 0xF0) param &= 0xF0; break; - case 'R' - 55: command = CMD_RETRIG; break; - case 'T' - 55: command = CMD_TREMOR; break; - case 'X' - 55: command = CMD_XFINEPORTAUPDOWN; break; - case 'Y' - 55: command = CMD_PANBRELLO; break; - case 'Z' - 55: command = CMD_MIDI; break; - default: command = 0; - } - m->command = command; - m->param = param; -} - - -WORD CSoundFile::ModSaveCommand(const MODCOMMAND *m, BOOL bXM) const -//------------------------------------------------------------------ -{ - UINT command = m->command & 0x3F, param = m->param; - - switch(command) - { - case 0: command = param = 0; break; - case CMD_ARPEGGIO: command = 0; break; - case CMD_PORTAMENTOUP: - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) - { - if ((param & 0xF0) == 0xE0) { command=0x0E; param=((param & 0x0F) >> 2)|0x10; break; } - else if ((param & 0xF0) == 0xF0) { command=0x0E; param &= 0x0F; param|=0x10; break; } - } - command = 0x01; - break; - case CMD_PORTAMENTODOWN: - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) - { - if ((param & 0xF0) == 0xE0) { command=0x0E; param=((param & 0x0F) >> 2)|0x20; break; } - else if ((param & 0xF0) == 0xF0) { command=0x0E; param &= 0x0F; param|=0x20; break; } - } - command = 0x02; - break; - case CMD_TONEPORTAMENTO: command = 0x03; break; - case CMD_VIBRATO: command = 0x04; break; - case CMD_TONEPORTAVOL: command = 0x05; break; - case CMD_VIBRATOVOL: command = 0x06; break; - case CMD_TREMOLO: command = 0x07; break; - case CMD_PANNING8: - command = 0x08; - if (bXM) - { - if ((m_nType != MOD_TYPE_IT) && (m_nType != MOD_TYPE_XM) && (param <= 0x80)) - { - param <<= 1; - if (param > 255) param = 255; - } - } else - { - if ((m_nType == MOD_TYPE_IT) || (m_nType == MOD_TYPE_XM)) param >>= 1; - } - break; - case CMD_OFFSET: command = 0x09; break; - case CMD_VOLUMESLIDE: command = 0x0A; break; - case CMD_POSITIONJUMP: command = 0x0B; break; - case CMD_VOLUME: command = 0x0C; break; - case CMD_PATTERNBREAK: command = 0x0D; param = ((param / 10) << 4) | (param % 10); break; - case CMD_MODCMDEX: command = 0x0E; break; - case CMD_SPEED: command = 0x0F; if (param > 0x20) param = 0x20; break; - case CMD_TEMPO: if (param > 0x20) { command = 0x0F; break; } - case CMD_GLOBALVOLUME: command = 'G' - 55; break; - case CMD_GLOBALVOLSLIDE: command = 'H' - 55; break; - case CMD_KEYOFF: command = 'K' - 55; break; - case CMD_SETENVPOSITION: command = 'L' - 55; break; - case CMD_CHANNELVOLUME: command = 'M' - 55; break; - case CMD_CHANNELVOLSLIDE: command = 'N' - 55; break; - case CMD_PANNINGSLIDE: command = 'P' - 55; break; - case CMD_RETRIG: command = 'R' - 55; break; - case CMD_TREMOR: command = 'T' - 55; break; - case CMD_XFINEPORTAUPDOWN: command = 'X' - 55; break; - case CMD_PANBRELLO: command = 'Y' - 55; break; - case CMD_MIDI: command = 'Z' - 55; break; - case CMD_S3MCMDEX: - switch(param & 0xF0) - { - case 0x10: command = 0x0E; param = (param & 0x0F) | 0x30; break; - case 0x20: command = 0x0E; param = (param & 0x0F) | 0x50; break; - case 0x30: command = 0x0E; param = (param & 0x0F) | 0x40; break; - case 0x40: command = 0x0E; param = (param & 0x0F) | 0x70; break; - case 0x90: command = 'X' - 55; break; - case 0xB0: command = 0x0E; param = (param & 0x0F) | 0x60; break; - case 0xA0: - case 0x50: - case 0x70: - case 0x60: command = param = 0; break; - default: command = 0x0E; break; - } - break; - default: command = param = 0; - } - return (WORD)((command << 8) | (param)); -} - - -#pragma pack(1) - -typedef struct _MODSAMPLE -{ - CHAR name[22]; - WORD length; - BYTE finetune; - BYTE volume; - WORD loopstart; - WORD looplen; -} MODSAMPLE, *PMODSAMPLE; - -typedef struct _MODMAGIC -{ - BYTE nOrders; - BYTE nRestartPos; - BYTE Orders[128]; - char Magic[4]; // changed from CHAR -} MODMAGIC, *PMODMAGIC; - -#pragma pack() - -BOOL IsMagic(LPCSTR s1, LPCSTR s2) -{ - return ((*(DWORD *)s1) == (*(DWORD *)s2)) ? TRUE : FALSE; -} - - -BOOL CSoundFile::ReadMod(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - char s[1024]; // changed from CHAR - DWORD dwMemPos, dwTotalSampleLen; - PMODMAGIC pMagic; - UINT nErr; - - if ((!lpStream) || (dwMemLength < 0x600)) return FALSE; - dwMemPos = 20; - m_nSamples = 31; - m_nChannels = 4; - pMagic = (PMODMAGIC)(lpStream+dwMemPos+sizeof(MODSAMPLE)*31); - // Check Mod Magic - memcpy(s, pMagic->Magic, 4); - if ((IsMagic(s, "M.K.")) || (IsMagic(s, "M!K!")) - || (IsMagic(s, "M&K!")) || (IsMagic(s, "N.T."))) m_nChannels = 4; else - if ((IsMagic(s, "CD81")) || (IsMagic(s, "OKTA"))) m_nChannels = 8; else - if ((s[0]=='F') && (s[1]=='L') && (s[2]=='T') && (s[3]>='4') && (s[3]<='9')) m_nChannels = s[3] - '0'; else - if ((s[0]>='2') && (s[0]<='9') && (s[1]=='C') && (s[2]=='H') && (s[3]=='N')) m_nChannels = s[0] - '0'; else - if ((s[0]=='1') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 10; else - if ((s[0]=='2') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 20; else - if ((s[0]=='3') && (s[1]>='0') && (s[1]<='2') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 30; else - if ((s[0]=='T') && (s[1]=='D') && (s[2]=='Z') && (s[3]>='4') && (s[3]<='9')) m_nChannels = s[3] - '0'; else - if (IsMagic(s,"16CN")) m_nChannels = 16; else - if (IsMagic(s,"32CN")) m_nChannels = 32; else m_nSamples = 15; - // Load Samples - nErr = 0; - dwTotalSampleLen = 0; - for (UINT i=1; i<=m_nSamples; i++) - { - PMODSAMPLE pms = (PMODSAMPLE)(lpStream+dwMemPos); - MODINSTRUMENT *psmp = &Ins[i]; - UINT loopstart, looplen; - - memcpy(m_szNames[i], pms->name, 22); - m_szNames[i][22] = 0; - psmp->uFlags = 0; - psmp->nLength = bswapBE16(pms->length)*2; - dwTotalSampleLen += psmp->nLength; - psmp->nFineTune = MOD2XMFineTune(pms->finetune & 0x0F); - psmp->nVolume = 4*pms->volume; - if (psmp->nVolume > 256) { psmp->nVolume = 256; nErr++; } - psmp->nGlobalVol = 64; - psmp->nPan = 128; - loopstart = bswapBE16(pms->loopstart)*2; - looplen = bswapBE16(pms->looplen)*2; - // Fix loops - if ((looplen > 2) && (loopstart+looplen > psmp->nLength) - && (loopstart/2+looplen <= psmp->nLength)) - { - loopstart /= 2; - } - psmp->nLoopStart = loopstart; - psmp->nLoopEnd = loopstart + looplen; - if (psmp->nLength < 4) psmp->nLength = 0; - if (psmp->nLength) - { - UINT derr = 0; - if (psmp->nLoopStart >= psmp->nLength) { psmp->nLoopStart = psmp->nLength-1; derr|=1; } - if (psmp->nLoopEnd > psmp->nLength) { psmp->nLoopEnd = psmp->nLength; derr |= 1; } - if (psmp->nLoopStart > psmp->nLoopEnd) derr |= 1; - if ((psmp->nLoopStart > psmp->nLoopEnd) || (psmp->nLoopEnd <= 8) - || (psmp->nLoopEnd - psmp->nLoopStart <= 4)) - { - psmp->nLoopStart = 0; - psmp->nLoopEnd = 0; - } - if (psmp->nLoopEnd > psmp->nLoopStart) - { - psmp->uFlags |= CHN_LOOP; - } - } - dwMemPos += sizeof(MODSAMPLE); - } - if ((m_nSamples == 15) && (dwTotalSampleLen > dwMemLength * 4)) return FALSE; - pMagic = (PMODMAGIC)(lpStream+dwMemPos); - dwMemPos += sizeof(MODMAGIC); - if (m_nSamples == 15) dwMemPos -= 4; - memset(Order, 0,sizeof(Order)); - memcpy(Order, pMagic->Orders, 128); - - UINT nbp, nbpbuggy, nbpbuggy2, norders; - - norders = pMagic->nOrders; - if ((!norders) || (norders > 0x80)) - { - norders = 0x80; - while ((norders > 1) && (!Order[norders-1])) norders--; - } - nbpbuggy = 0; - nbpbuggy2 = 0; - nbp = 0; - for (UINT iord=0; iord<128; iord++) - { - UINT i = Order[iord]; - if ((i < 0x80) && (nbp <= i)) - { - nbp = i+1; - if (iord= nbpbuggy2) nbpbuggy2 = i+1; - } - for (UINT iend=norders; iendnRestartPos; - if (m_nRestartPos >= 0x78) m_nRestartPos = 0; - if (m_nRestartPos + 1 >= (UINT)norders) m_nRestartPos = 0; - if (!nbp) return FALSE; - DWORD dwWowTest = dwTotalSampleLen+dwMemPos; - if ((IsMagic(pMagic->Magic, "M.K.")) && (dwWowTest + nbp*8*256 == dwMemLength)) m_nChannels = 8; - if ((nbp != nbpbuggy) && (dwWowTest + nbp*m_nChannels*256 != dwMemLength)) - { - if (dwWowTest + nbpbuggy*m_nChannels*256 == dwMemLength) nbp = nbpbuggy; - else nErr += 8; - } else - if ((nbpbuggy2 > nbp) && (dwWowTest + nbpbuggy2*m_nChannels*256 == dwMemLength)) - { - nbp = nbpbuggy2; - } - if ((dwWowTest < 0x600) || (dwWowTest > dwMemLength)) nErr += 8; - if ((m_nSamples == 15) && (nErr >= 16)) return FALSE; - // Default settings - m_nType = MOD_TYPE_MOD; - m_nDefaultSpeed = 6; - m_nDefaultTempo = 125; - m_nMinPeriod = 14 << 2; - m_nMaxPeriod = 3424 << 2; - memcpy(m_szNames, lpStream, 20); - // Setting channels pan - for (UINT ich=0; ich= dwMemLength) break; - MODCOMMAND *m = Patterns[ipat]; - LPCBYTE p = lpStream + dwMemPos; - for (UINT j=m_nChannels*64; j; m++,p+=4,j--) - { - BYTE A0=p[0], A1=p[1], A2=p[2], A3=p[3]; - UINT n = ((((UINT)A0 & 0x0F) << 8) | (A1)); - if ((n) && (n != 0xFFF)) m->note = GetNoteFromPeriod(n << 2); - m->instr = ((UINT)A2 >> 4) | (A0 & 0x10); - m->command = A2 & 0x0F; - m->param = A3; - if ((m->command) || (m->param)) ConvertModCommand(m); - } - } - dwMemPos += m_nChannels*256; - } - // Reading instruments - DWORD dwErrCheck = 0; - for (UINT ismp=1; ismp<=m_nSamples; ismp++) if (Ins[ismp].nLength) - { - LPSTR p = (LPSTR)(lpStream+dwMemPos); - UINT flags = 0; - if (dwMemPos + 5 >= dwMemLength) break; - if (!strnicmp(p, "ADPCM", 5)) - { - flags = 3; - p += 5; - dwMemPos += 5; - } - DWORD dwSize = ReadSample(&Ins[ismp], flags, p, dwMemLength - dwMemPos); - if (dwSize) - { - dwMemPos += dwSize; - dwErrCheck++; - } - } -#ifdef MODPLUG_TRACKER - return TRUE; -#else - return (dwErrCheck) ? TRUE : FALSE; -#endif -} - - -#ifndef MODPLUG_NO_FILESAVE - -#ifdef _MSC_VER -#pragma warning(disable:4100) -#endif - -BOOL CSoundFile::SaveMod(LPCSTR lpszFileName, UINT nPacking) -//---------------------------------------------------------- -{ - BYTE insmap[32]; - UINT inslen[32]; - BYTE bTab[32]; - BYTE ord[128]; - FILE *f; - - if ((!m_nChannels) || (!lpszFileName)) return FALSE; - if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE; - memset(ord, 0, sizeof(ord)); - memset(inslen, 0, sizeof(inslen)); - if (m_nInstruments) - { - memset(insmap, 0, sizeof(insmap)); - for (UINT i=1; i<32; i++) if (Headers[i]) - { - for (UINT j=0; j<128; j++) if (Headers[i]->Keyboard[j]) - { - insmap[i] = Headers[i]->Keyboard[j]; - break; - } - } - } else - { - for (UINT i=0; i<32; i++) insmap[i] = (BYTE)i; - } - // Writing song name - fwrite(m_szNames, 20, 1, f); - // Writing instrument definition - for (UINT iins=1; iins<=31; iins++) - { - MODINSTRUMENT *pins = &Ins[insmap[iins]]; - memcpy(bTab, m_szNames[iins],22); - inslen[iins] = pins->nLength; - if (inslen[iins] > 0x1fff0) inslen[iins] = 0x1fff0; - bTab[22] = inslen[iins] >> 9; - bTab[23] = inslen[iins] >> 1; - if (pins->RelativeTone < 0) bTab[24] = 0x08; else - if (pins->RelativeTone > 0) bTab[24] = 0x07; else - bTab[24] = (BYTE)XM2MODFineTune(pins->nFineTune); - bTab[25] = pins->nVolume >> 2; - bTab[26] = pins->nLoopStart >> 9; - bTab[27] = pins->nLoopStart >> 1; - bTab[28] = (pins->nLoopEnd - pins->nLoopStart) >> 9; - bTab[29] = (pins->nLoopEnd - pins->nLoopStart) >> 1; - fwrite(bTab, 30, 1, f); - } - // Writing number of patterns - UINT nbp=0, norders=128; - for (UINT iord=0; iord<128; iord++) - { - if (Order[iord] == 0xFF) - { - norders = iord; - break; - } - if ((Order[iord] < 0x80) && (nbp<=Order[iord])) nbp = Order[iord]+1; - } - bTab[0] = norders; - bTab[1] = m_nRestartPos; - fwrite(bTab, 2, 1, f); - // Writing pattern list - if (norders) memcpy(ord, Order, norders); - fwrite(ord, 128, 1, f); - // Writing signature - if (m_nChannels == 4) - lstrcpy((LPSTR)&bTab, "M.K."); - else - wsprintf((LPSTR)&bTab, "%luCHN", m_nChannels); - fwrite(bTab, 4, 1, f); - // Writing patterns - for (UINT ipat=0; ipat> 8; - param &= 0xFF; - if (command > 0x0F) command = param = 0; - if ((m->vol >= 0x10) && (m->vol <= 0x50) && (!command) && (!param)) { command = 0x0C; param = m->vol - 0x10; } - UINT period = m->note; - if (period) - { - if (period < 37) period = 37; - period -= 37; - if (period >= 6*12) period = 6*12-1; - period = ProTrackerPeriodTable[period]; - } - UINT instr = (m->instr > 31) ? 0 : m->instr; - p[0] = ((period >> 8) & 0x0F) | (instr & 0x10); - p[1] = period & 0xFF; - p[2] = ((instr & 0x0F) << 4) | (command & 0x0F); - p[3] = param; - } - fwrite(s, m_nChannels, 4, f); - } else - { - memset(s, 0, m_nChannels*4); - fwrite(s, m_nChannels, 4, f); - } - } - // Writing instruments - for (UINT ismpd=1; ismpd<=31; ismpd++) if (inslen[ismpd]) - { - MODINSTRUMENT *pins = &Ins[insmap[ismpd]]; - UINT flags = RS_PCM8S; -#ifndef NO_PACKING - if (!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) - { - if ((nPacking) && (CanPackSample((char *)pins->pSample, inslen[ismpd], nPacking))) - { - fwrite("ADPCM", 1, 5, f); - flags = RS_ADPCM4; - } - } -#endif - WriteSample(f, pins, flags, inslen[ismpd]); - } - fclose(f); - return TRUE; -} - -#ifdef _MSC_VER -#pragma warning(default:4100) -#endif - -#endif // MODPLUG_NO_FILESAVE diff --git a/jni/load_mt2.cpp b/jni/load_mt2.cpp deleted file mode 100644 index bf8bb25..0000000 --- a/jni/load_mt2.cpp +++ /dev/null @@ -1,635 +0,0 @@ -#include "stdafx.h" -#include "sndfile.h" - -//#define MT2DEBUG - -#pragma pack(1) - -typedef struct _MT2FILEHEADER -{ - DWORD dwMT20; // 0x3032544D "MT20" - DWORD dwSpecial; - WORD wVersion; - CHAR szTrackerName[32]; // "MadTracker 2.0" - CHAR szSongName[64]; - WORD nOrders; - WORD wRestart; - WORD wPatterns; - WORD wChannels; - WORD wSamplesPerTick; - BYTE bTicksPerLine; - BYTE bLinesPerBeat; - DWORD fulFlags; // b0=packed patterns - WORD wInstruments; - WORD wSamples; - BYTE Orders[256]; -} MT2FILEHEADER; - -typedef struct _MT2PATTERN -{ - WORD wLines; - DWORD wDataLen; -} MT2PATTERN; - -typedef struct _MT2COMMAND -{ - BYTE note; // 0=nothing, 97=note off - BYTE instr; - BYTE vol; - BYTE pan; - BYTE fxcmd; - BYTE fxparam1; - BYTE fxparam2; -} MT2COMMAND; - -typedef struct _MT2DRUMSDATA -{ - WORD wDrumPatterns; - WORD wDrumSamples[8]; - BYTE DrumPatternOrder[256]; -} MT2DRUMSDATA; - -typedef struct _MT2AUTOMATION -{ - DWORD dwFlags; - DWORD dwEffectId; - DWORD nEnvPoints; -} MT2AUTOMATION; - -typedef struct _MT2INSTRUMENT -{ - CHAR szName[32]; - DWORD dwDataLen; - WORD wSamples; - BYTE GroupsMapping[96]; - BYTE bVibType; - BYTE bVibSweep; - BYTE bVibDepth; - BYTE bVibRate; - WORD wFadeOut; - WORD wNNA; - WORD wInstrFlags; - WORD wEnvFlags1; - WORD wEnvFlags2; -} MT2INSTRUMENT; - -typedef struct _MT2ENVELOPE -{ - BYTE nFlags; - BYTE nPoints; - BYTE nSustainPos; - BYTE nLoopStart; - BYTE nLoopEnd; - BYTE bReserved[3]; - BYTE EnvData[64]; -} MT2ENVELOPE; - -typedef struct _MT2SYNTH -{ - BYTE nSynthId; - BYTE nFxId; - WORD wCutOff; - BYTE nResonance; - BYTE nAttack; - BYTE nDecay; - BYTE bReserved[25]; -} MT2SYNTH; - -typedef struct _MT2SAMPLE -{ - CHAR szName[32]; - DWORD dwDataLen; - DWORD dwLength; - DWORD dwFrequency; - BYTE nQuality; - BYTE nChannels; - BYTE nFlags; - BYTE nLoop; - DWORD dwLoopStart; - DWORD dwLoopEnd; - WORD wVolume; - BYTE nPan; - BYTE nBaseNote; - WORD wSamplesPerBeat; -} MT2SAMPLE; - -typedef struct _MT2GROUP -{ - BYTE nSmpNo; - BYTE nVolume; // 0-128 - BYTE nFinePitch; - BYTE Reserved[5]; -} MT2GROUP; - -#pragma pack() - - -static VOID ConvertMT2Command(CSoundFile *that, MODCOMMAND *m, const MT2COMMAND *p) -//--------------------------------------------------------------------------- -{ - // Note - m->note = 0; - if (p->note) m->note = (p->note > 96) ? 0xFF : p->note+12; - // Instrument - m->instr = p->instr; - // Volume Column - if ((p->vol >= 0x10) && (p->vol <= 0x90)) - { - m->volcmd = VOLCMD_VOLUME; - m->vol = (p->vol - 0x10) >> 1; - } else - if ((p->vol >= 0xA0) && (p->vol <= 0xAF)) - { - m->volcmd = VOLCMD_VOLSLIDEDOWN; - m->vol = (p->vol & 0x0f); - } else - if ((p->vol >= 0xB0) && (p->vol <= 0xBF)) - { - m->volcmd = VOLCMD_VOLSLIDEUP; - m->vol = (p->vol & 0x0f); - } else - if ((p->vol >= 0xC0) && (p->vol <= 0xCF)) - { - m->volcmd = VOLCMD_FINEVOLDOWN; - m->vol = (p->vol & 0x0f); - } else - if ((p->vol >= 0xD0) && (p->vol <= 0xDF)) - { - m->volcmd = VOLCMD_FINEVOLUP; - m->vol = (p->vol & 0x0f); - } else - { - m->volcmd = 0; - m->vol = 0; - } - // Effects - m->command = 0; - m->param = 0; - if ((p->fxcmd) || (p->fxparam1) || (p->fxparam2)) - { - if (!p->fxcmd) - { - m->command = p->fxparam2; - m->param = p->fxparam1; - that->ConvertModCommand(m); - } else - { - // TODO: MT2 Effects - } - } -} - - -BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength) -//----------------------------------------------------------- -{ - const MT2FILEHEADER *pfh = (MT2FILEHEADER *)lpStream; - DWORD dwMemPos, dwDrumDataPos, dwExtraDataPos; - UINT nDrumDataLen, nExtraDataLen; - const MT2DRUMSDATA *pdd; - const MT2INSTRUMENT *InstrMap[255]; - const MT2SAMPLE *SampleMap[256]; - - if ((!lpStream) || (dwMemLength < sizeof(MT2FILEHEADER)) - || (pfh->dwMT20 != 0x3032544D) - || (pfh->wVersion < 0x0200) || (pfh->wVersion >= 0x0300) - || (pfh->wChannels < 4) || (pfh->wChannels > 64)) return FALSE; - pdd = NULL; - m_nType = MOD_TYPE_MT2; - m_nChannels = pfh->wChannels; - m_nRestartPos = pfh->wRestart; - m_nDefaultSpeed = pfh->bTicksPerLine; - m_nDefaultTempo = 125; - if ((pfh->wSamplesPerTick > 100) && (pfh->wSamplesPerTick < 5000)) - { - m_nDefaultTempo = 110250 / pfh->wSamplesPerTick; - } - for (UINT iOrd=0; iOrdnOrders) ? pfh->Orders[iOrd] : 0xFF); - } - memcpy(m_szNames[0], pfh->szSongName, 32); - m_szNames[0][31] = 0; - dwMemPos = sizeof(MT2FILEHEADER); - nDrumDataLen = *(WORD *)(lpStream + dwMemPos); - dwDrumDataPos = dwMemPos + 2; - if (nDrumDataLen >= 2) pdd = (MT2DRUMSDATA *)(lpStream+dwDrumDataPos); - dwMemPos += 2 + nDrumDataLen; -#ifdef MT2DEBUG - - Log("MT2 v%03X: \"%s\" (flags=%04X)\n", pfh->wVersion, m_szNames[0], pfh->fulFlags); - Log("%d Channels, %d Patterns, %d Instruments, %d Samples\n", pfh->wChannels, pfh->wPatterns, pfh->wInstruments, pfh->wSamples); - Log("Drum Data: %d bytes @%04X\n", nDrumDataLen, dwDrumDataPos); -#endif - if (dwMemPos >= dwMemLength-12) return TRUE; - if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4; - if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4; - nExtraDataLen = *(DWORD *)(lpStream+dwMemPos); - dwExtraDataPos = dwMemPos + 4; - dwMemPos += 4; -#ifdef MT2DEBUG - Log("Extra Data: %d bytes @%04X\n", nExtraDataLen, dwExtraDataPos); -#endif - if (dwMemPos + nExtraDataLen >= dwMemLength) return TRUE; - while (dwMemPos+8 < dwExtraDataPos + nExtraDataLen) - { - DWORD dwId = *(DWORD *)(lpStream+dwMemPos); - DWORD dwLen = *(DWORD *)(lpStream+dwMemPos+4); - dwMemPos += 8; - if (dwMemPos + dwLen > dwMemLength) return TRUE; -#ifdef MT2DEBUG - CHAR s[5]; - memcpy(s, &dwId, 4); - s[4] = 0; - Log("pos=0x%04X: %s: %d bytes\n", dwMemPos-8, s, dwLen); -#endif - switch(dwId) - { - // MSG - case 0x0047534D: - if ((dwLen > 3) && (!m_lpszSongComments)) - { - DWORD nTxtLen = dwLen; - if (nTxtLen > 32000) nTxtLen = 32000; - m_lpszSongComments = new char[nTxtLen]; // changed from CHAR - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos+1, nTxtLen-1); - m_lpszSongComments[nTxtLen-1] = 0; - } - } - break; - // SUM -> author name (or "Unregistered") - // TMAP - // TRKS - case 0x534b5254: - break; - } - dwMemPos += dwLen; - } - // Load Patterns - dwMemPos = dwExtraDataPos + nExtraDataLen; - for (UINT iPat=0; iPatwPatterns; iPat++) if (dwMemPos < dwMemLength-6) - { - const MT2PATTERN *pmp = (MT2PATTERN *)(lpStream+dwMemPos); - UINT wDataLen = (pmp->wDataLen + 1) & ~1; - dwMemPos += 6; - if (dwMemPos + wDataLen > dwMemLength) break; - UINT nLines = pmp->wLines; - if ((iPat < MAX_PATTERNS) && (nLines > 0) && (nLines <= 256)) - { - #ifdef MT2DEBUG - Log("Pattern #%d @%04X: %d lines, %d bytes\n", iPat, dwMemPos-6, nLines, pmp->wDataLen); - #endif - PatternSize[iPat] = nLines; - Patterns[iPat] = AllocatePattern(nLines, m_nChannels); - if (!Patterns[iPat]) return TRUE; - MODCOMMAND *m = Patterns[iPat]; - UINT len = wDataLen; - if (pfh->fulFlags & 1) // Packed Patterns - { - BYTE *p = (BYTE *)(lpStream+dwMemPos); - UINT pos = 0, row=0, ch=0; - while (pos < len) - { - MT2COMMAND cmd; - UINT infobyte = p[pos++]; - UINT rptcount = 0; - if (infobyte == 0xff) - { - rptcount = p[pos++]; - infobyte = p[pos++]; - #if 0 - Log("(%d.%d) FF(%02X).%02X\n", row, ch, rptcount, infobyte); - } else - { - Log("(%d.%d) %02X\n", row, ch, infobyte); - #endif - } - if (infobyte & 0x7f) - { - UINT patpos = row*m_nChannels+ch; - cmd.note = cmd.instr = cmd.vol = cmd.pan = cmd.fxcmd = cmd.fxparam1 = cmd.fxparam2 = 0; - if (infobyte & 1) cmd.note = p[pos++]; - if (infobyte & 2) cmd.instr = p[pos++]; - if (infobyte & 4) cmd.vol = p[pos++]; - if (infobyte & 8) cmd.pan = p[pos++]; - if (infobyte & 16) cmd.fxcmd = p[pos++]; - if (infobyte & 32) cmd.fxparam1 = p[pos++]; - if (infobyte & 64) cmd.fxparam2 = p[pos++]; - #ifdef MT2DEBUG - if (cmd.fxcmd) - { - Log("(%d.%d) MT2 FX=%02X.%02X.%02X\n", row, ch, cmd.fxcmd, cmd.fxparam1, cmd.fxparam2); - } - #endif - ConvertMT2Command(this, &m[patpos], &cmd); - } - row += rptcount+1; - while (row >= nLines) { row-=nLines; ch++; } - if (ch >= m_nChannels) break; - } - } else - { - const MT2COMMAND *p = (MT2COMMAND *)(lpStream+dwMemPos); - UINT n = 0; - while ((len > sizeof(MT2COMMAND)) && (n < m_nChannels*nLines)) - { - ConvertMT2Command(this, m, p); - len -= sizeof(MT2COMMAND); - n++; - p++; - m++; - } - } - } - dwMemPos += wDataLen; - } - // Skip Drum Patterns - if (pdd) - { - #ifdef MT2DEBUG - Log("%d Drum Patterns at offset 0x%08X\n", pdd->wDrumPatterns, dwMemPos); - #endif - for (UINT iDrm=0; iDrmwDrumPatterns; iDrm++) - { - if (dwMemPos > dwMemLength-2) return TRUE; - UINT nLines = *(WORD *)(lpStream+dwMemPos); - #ifdef MT2DEBUG - if (nLines != 64) Log("Drum Pattern %d: %d Lines @%04X\n", iDrm, nLines, dwMemPos); - #endif - dwMemPos += 2 + nLines * 32; - } - } - // Automation - if (pfh->fulFlags & 2) - { - #ifdef MT2DEBUG - Log("Automation at offset 0x%08X\n", dwMemPos); - #endif - UINT nAutoCount = m_nChannels; - if (pfh->fulFlags & 0x10) nAutoCount++; // Master Automation - if ((pfh->fulFlags & 0x08) && (pdd)) nAutoCount += 8; // Drums Automation - nAutoCount *= pfh->wPatterns; - for (UINT iAuto=0; iAuto= dwMemLength) return TRUE; - const MT2AUTOMATION *pma = (MT2AUTOMATION *)(lpStream+dwMemPos); - dwMemPos += (pfh->wVersion <= 0x201) ? 4 : 8; - for (UINT iEnv=0; iEnv<14; iEnv++) - { - if (pma->dwFlags & (1 << iEnv)) - { - #ifdef MT2DEBUG - UINT nPoints = *(DWORD *)(lpStream+dwMemPos); - Log(" Env[%d/%d] %04X @%04X: %d points\n", iAuto, nAutoCount, 1 << iEnv, dwMemPos-8, nPoints); - #endif - dwMemPos += 260; - } - } - } - } - // Load Instruments -#ifdef MT2DEBUG - Log("Loading instruments at offset 0x%08X\n", dwMemPos); -#endif - memset(InstrMap, 0, sizeof(InstrMap)); - m_nInstruments = (pfh->wInstruments < MAX_INSTRUMENTS) ? pfh->wInstruments : MAX_INSTRUMENTS-1; - for (UINT iIns=1; iIns<=255; iIns++) - { - if (dwMemPos+36 > dwMemLength) return TRUE; - const MT2INSTRUMENT *pmi = (MT2INSTRUMENT *)(lpStream+dwMemPos); - INSTRUMENTHEADER *penv = NULL; - if (iIns <= m_nInstruments) - { - penv = new INSTRUMENTHEADER; - Headers[iIns] = penv; - if (penv) - { - memset(penv, 0, sizeof(INSTRUMENTHEADER)); - memcpy(penv->name, pmi->szName, 32); - penv->nGlobalVol = 64; - penv->nPan = 128; - for (UINT i=0; iNoteMap[i] = i+1; - } - } - } - #ifdef MT2DEBUG - if (iIns <= pfh->wInstruments) Log(" Instrument #%d at offset %04X: %d bytes\n", iIns, dwMemPos, pmi->dwDataLen); - #endif - if (((LONG)pmi->dwDataLen > 0) && (dwMemPos <= dwMemLength - 40) && (pmi->dwDataLen <= dwMemLength - (dwMemPos + 40))) - { - InstrMap[iIns-1] = pmi; - if (penv) - { - penv->nFadeOut = pmi->wFadeOut; - penv->nNNA = pmi->wNNA & 3; - penv->nDCT = (pmi->wNNA>>8) & 3; - penv->nDNA = (pmi->wNNA>>12) & 3; - MT2ENVELOPE *pehdr[4]; - WORD *pedata[4]; - if (pfh->wVersion <= 0x201) - { - DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT) - 4; - pehdr[0] = (MT2ENVELOPE *)(lpStream+dwEnvPos); - pehdr[1] = (MT2ENVELOPE *)(lpStream+dwEnvPos+8); - pehdr[2] = pehdr[3] = NULL; - pedata[0] = (WORD *)(lpStream+dwEnvPos+16); - pedata[1] = (WORD *)(lpStream+dwEnvPos+16+64); - pedata[2] = pedata[3] = NULL; - } else - { - DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT); - for (UINT i=0; i<4; i++) - { - if (pmi->wEnvFlags1 & (1<EnvData; - dwEnvPos += sizeof(MT2ENVELOPE); - } else - { - pehdr[i] = NULL; - pedata[i] = NULL; - } - } - } - // Load envelopes - for (UINT iEnv=0; iEnv<4; iEnv++) if (pehdr[iEnv]) - { - const MT2ENVELOPE *pme = pehdr[iEnv]; - WORD *pEnvPoints = NULL; - BYTE *pEnvData = NULL; - #ifdef MT2DEBUG - Log(" Env %d.%d @%04X: %d points\n", iIns, iEnv, (UINT)(((BYTE *)pme)-lpStream), pme->nPoints); - #endif - switch(iEnv) - { - // Volume Envelope - case 0: - if (pme->nFlags & 1) penv->dwFlags |= ENV_VOLUME; - if (pme->nFlags & 2) penv->dwFlags |= ENV_VOLSUSTAIN; - if (pme->nFlags & 4) penv->dwFlags |= ENV_VOLLOOP; - penv->nVolEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; - penv->nVolSustainBegin = penv->nVolSustainEnd = pme->nSustainPos; - penv->nVolLoopStart = pme->nLoopStart; - penv->nVolLoopEnd = pme->nLoopEnd; - pEnvPoints = penv->VolPoints; - pEnvData = penv->VolEnv; - break; - - // Panning Envelope - case 1: - if (pme->nFlags & 1) penv->dwFlags |= ENV_PANNING; - if (pme->nFlags & 2) penv->dwFlags |= ENV_PANSUSTAIN; - if (pme->nFlags & 4) penv->dwFlags |= ENV_PANLOOP; - penv->nPanEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; - penv->nPanSustainBegin = penv->nPanSustainEnd = pme->nSustainPos; - penv->nPanLoopStart = pme->nLoopStart; - penv->nPanLoopEnd = pme->nLoopEnd; - pEnvPoints = penv->PanPoints; - pEnvData = penv->PanEnv; - break; - - // Pitch/Filter envelope - default: - if (pme->nFlags & 1) penv->dwFlags |= (iEnv==3) ? (ENV_PITCH|ENV_FILTER) : ENV_PITCH; - if (pme->nFlags & 2) penv->dwFlags |= ENV_PITCHSUSTAIN; - if (pme->nFlags & 4) penv->dwFlags |= ENV_PITCHLOOP; - penv->nPitchEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; - penv->nPitchSustainBegin = penv->nPitchSustainEnd = pme->nSustainPos; - penv->nPitchLoopStart = pme->nLoopStart; - penv->nPitchLoopEnd = pme->nLoopEnd; - pEnvPoints = penv->PitchPoints; - pEnvData = penv->PitchEnv; - } - // Envelope data - if ((pEnvPoints) && (pEnvData) && (pedata[iEnv])) - { - WORD *psrc = pedata[iEnv]; - for (UINT i=0; i<16; i++) - { - pEnvPoints[i] = psrc[i*2]; - pEnvData[i] = (BYTE)psrc[i*2+1]; - } - } - } - } - dwMemPos += pmi->dwDataLen + 36; - if (pfh->wVersion > 0x201) dwMemPos += 4; // ? - } else - { - dwMemPos += 36; - } - } -#ifdef MT2DEBUG - Log("Loading samples at offset 0x%08X\n", dwMemPos); -#endif - memset(SampleMap, 0, sizeof(SampleMap)); - m_nSamples = (pfh->wSamples < MAX_SAMPLES) ? pfh->wSamples : MAX_SAMPLES-1; - for (UINT iSmp=1; iSmp<=256; iSmp++) - { - if (dwMemPos+36 > dwMemLength) return TRUE; - const MT2SAMPLE *pms = (MT2SAMPLE *)(lpStream+dwMemPos); - #ifdef MT2DEBUG - if (iSmp <= m_nSamples) Log(" Sample #%d at offset %04X: %d bytes\n", iSmp, dwMemPos, pms->dwDataLen); - #endif - if (iSmp < MAX_SAMPLES) - { - memcpy(m_szNames[iSmp], pms->szName, 32); - } - if (pms->dwDataLen > 0) - { - SampleMap[iSmp-1] = pms; - if (iSmp < MAX_SAMPLES) - { - MODINSTRUMENT *psmp = &Ins[iSmp]; - psmp->nGlobalVol = 64; - psmp->nVolume = (pms->wVolume >> 7); - psmp->nPan = (pms->nPan == 0x80) ? 128 : (pms->nPan^0x80); - psmp->nLength = pms->dwLength; - psmp->nC4Speed = pms->dwFrequency; - psmp->nLoopStart = pms->dwLoopStart; - psmp->nLoopEnd = pms->dwLoopEnd; - FrequencyToTranspose(psmp); - psmp->RelativeTone -= pms->nBaseNote - 49; - psmp->nC4Speed = TransposeToFrequency(psmp->RelativeTone, psmp->nFineTune); - if (pms->nQuality == 2) { psmp->uFlags |= CHN_16BIT; psmp->nLength >>= 1; } - if (pms->nChannels == 2) { psmp->nLength >>= 1; } - if (pms->nLoop == 1) psmp->uFlags |= CHN_LOOP; - if (pms->nLoop == 2) psmp->uFlags |= CHN_LOOP|CHN_PINGPONGLOOP; - } - dwMemPos += pms->dwDataLen + 36; - } else - { - dwMemPos += 36; - } - } -#ifdef MT2DEBUG - Log("Loading groups at offset 0x%08X\n", dwMemPos); -#endif - for (UINT iMap=0; iMap<255; iMap++) if (InstrMap[iMap]) - { - if (dwMemPos+8 > dwMemLength) return TRUE; - const MT2INSTRUMENT *pmi = InstrMap[iMap]; - INSTRUMENTHEADER *penv = NULL; - if (iMapwSamples; iGrp++) - { - if (penv) - { - const MT2GROUP *pmg = (MT2GROUP *)(lpStream+dwMemPos); - for (UINT i=0; i<96; i++) - { - if (pmi->GroupsMapping[i] == iGrp) - { - UINT nSmp = pmg->nSmpNo+1; - penv->Keyboard[i+12] = (BYTE)nSmp; - if (nSmp <= m_nSamples) - { - Ins[nSmp].nVibType = pmi->bVibType; - Ins[nSmp].nVibSweep = pmi->bVibSweep; - Ins[nSmp].nVibDepth = pmi->bVibDepth; - Ins[nSmp].nVibRate = pmi->bVibRate; - } - } - } - } - dwMemPos += 8; - } - } -#ifdef MT2DEBUG - Log("Loading sample data at offset 0x%08X\n", dwMemPos); -#endif - for (UINT iData=0; iData<256; iData++) if ((iData < m_nSamples) && (SampleMap[iData])) - { - const MT2SAMPLE *pms = SampleMap[iData]; - MODINSTRUMENT *psmp = &Ins[iData+1]; - if (!(pms->nFlags & 5)) - { - if (psmp->nLength > 0) - { - #ifdef MT2DEBUG - Log(" Reading sample #%d at offset 0x%04X (len=%d)\n", iData+1, dwMemPos, psmp->nLength); - #endif - UINT rsflags; - - if (pms->nChannels == 2) - rsflags = (psmp->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D; - else - rsflags = (psmp->uFlags & CHN_16BIT) ? RS_PCM16D : RS_PCM8D; - - dwMemPos += ReadSample(psmp, rsflags, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos); - } - } else - if (dwMemPos+4 < dwMemLength) - { - UINT nNameLen = *(DWORD *)(lpStream+dwMemPos); - dwMemPos += nNameLen + 16; - } - if (dwMemPos+4 >= dwMemLength) break; - } - return TRUE; -} diff --git a/jni/load_mtm.cpp b/jni/load_mtm.cpp deleted file mode 100644 index f5f0299..0000000 --- a/jni/load_mtm.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -////////////////////////////////////////////////////////// -// MTM file support (import only) - -#pragma pack(1) - - -typedef struct tagMTMSAMPLE -{ - char samplename[22]; // changed from CHAR - DWORD length; - DWORD reppos; - DWORD repend; - CHAR finetune; - BYTE volume; - BYTE attribute; -} MTMSAMPLE; - - -typedef struct tagMTMHEADER -{ - char id[4]; // MTM file marker + version // changed from CHAR - char songname[20]; // ASCIIZ songname // changed from CHAR - WORD numtracks; // number of tracks saved - BYTE lastpattern; // last pattern number saved - BYTE lastorder; // last order number to play (songlength-1) - WORD commentsize; // length of comment field - BYTE numsamples; // number of samples saved - BYTE attribute; // attribute byte (unused) - BYTE beatspertrack; - BYTE numchannels; // number of channels used - BYTE panpos[32]; // voice pan positions -} MTMHEADER; - - -#pragma pack() - - -BOOL CSoundFile::ReadMTM(LPCBYTE lpStream, DWORD dwMemLength) -//----------------------------------------------------------- -{ - MTMHEADER *pmh = (MTMHEADER *)lpStream; - DWORD dwMemPos = 66; - - if ((!lpStream) || (dwMemLength < 0x100)) return FALSE; - if ((strncmp(pmh->id, "MTM", 3)) || (pmh->numchannels > 32) - || (pmh->numsamples >= MAX_SAMPLES) || (!pmh->numsamples) - || (!pmh->numtracks) || (!pmh->numchannels) - || (!pmh->lastpattern) || (pmh->lastpattern > MAX_PATTERNS)) - return FALSE; - strncpy(m_szNames[0], pmh->songname, 20); - m_szNames[0][20] = 0; - if (dwMemPos + 37*pmh->numsamples + 128 + 192*pmh->numtracks - + 64 * (pmh->lastpattern+1) + pmh->commentsize >= dwMemLength) - return FALSE; - m_nType = MOD_TYPE_MTM; - m_nSamples = pmh->numsamples; - m_nChannels = pmh->numchannels; - // Reading instruments - for (UINT i=1; i<=m_nSamples; i++) - { - MTMSAMPLE *pms = (MTMSAMPLE *)(lpStream + dwMemPos); - strncpy(m_szNames[i], pms->samplename, 22); - m_szNames[i][22] = 0; - Ins[i].nVolume = pms->volume << 2; - Ins[i].nGlobalVol = 64; - DWORD len = pms->length; - if ((len > 4) && (len <= MAX_SAMPLE_LENGTH)) - { - Ins[i].nLength = len; - Ins[i].nLoopStart = pms->reppos; - Ins[i].nLoopEnd = pms->repend; - if (Ins[i].nLoopEnd > Ins[i].nLength) - Ins[i].nLoopEnd = Ins[i].nLength; - if (Ins[i].nLoopStart + 4 >= Ins[i].nLoopEnd) - Ins[i].nLoopStart = Ins[i].nLoopEnd = 0; - if (Ins[i].nLoopEnd) Ins[i].uFlags |= CHN_LOOP; - Ins[i].nFineTune = MOD2XMFineTune(pms->finetune); - if (pms->attribute & 0x01) - { - Ins[i].uFlags |= CHN_16BIT; - Ins[i].nLength >>= 1; - Ins[i].nLoopStart >>= 1; - Ins[i].nLoopEnd >>= 1; - } - Ins[i].nPan = 128; - } - dwMemPos += 37; - } - // Setting Channel Pan Position - for (UINT ich=0; ichpanpos[ich] & 0x0F) << 4) + 8; - ChnSettings[ich].nVolume = 64; - } - // Reading pattern order - memcpy(Order, lpStream + dwMemPos, pmh->lastorder+1); - dwMemPos += 128; - // Reading Patterns - LPCBYTE pTracks = lpStream + dwMemPos; - dwMemPos += 192 * pmh->numtracks; - LPWORD pSeq = (LPWORD)(lpStream + dwMemPos); - for (UINT pat=0; pat<=pmh->lastpattern; pat++) - { - PatternSize[pat] = 64; - if ((Patterns[pat] = AllocatePattern(64, m_nChannels)) == NULL) break; - for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= pmh->numtracks) && (n < m_nChannels)) - { - LPCBYTE p = pTracks + 192 * (pSeq[n]-1); - MODCOMMAND *m = Patterns[pat] + n; - for (UINT i=0; i<64; i++, m+=m_nChannels, p+=3) - { - if (p[0] & 0xFC) m->note = (p[0] >> 2) + 37; - m->instr = ((p[0] & 0x03) << 4) | (p[1] >> 4); - UINT cmd = p[1] & 0x0F; - UINT param = p[2]; - if (cmd == 0x0A) - { - if (param & 0xF0) param &= 0xF0; else param &= 0x0F; - } - m->command = cmd; - m->param = param; - if ((cmd) || (param)) ConvertModCommand(m); - } - } - pSeq += 32; - } - dwMemPos += 64*(pmh->lastpattern+1); - if ((pmh->commentsize) && (dwMemPos + pmh->commentsize < dwMemLength)) - { - UINT n = pmh->commentsize; - m_lpszSongComments = new char[n+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, n); - m_lpszSongComments[n] = 0; - for (UINT i=0; icommentsize; - // Reading Samples - for (UINT ismp=1; ismp<=m_nSamples; ismp++) - { - if (dwMemPos >= dwMemLength) break; - dwMemPos += ReadSample(&Ins[ismp], (Ins[ismp].uFlags & CHN_16BIT) ? RS_PCM16U : RS_PCM8U, - (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos); - } - m_nMinPeriod = 64; - m_nMaxPeriod = 32767; - return TRUE; -} - diff --git a/jni/load_okt.cpp b/jni/load_okt.cpp deleted file mode 100644 index 7968f0b..0000000 --- a/jni/load_okt.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque , - * Adam Goode (endian and char fixes for PPC) -*/ - -////////////////////////////////////////////// -// Oktalyzer (OKT) module loader // -////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -typedef struct OKTFILEHEADER -{ - DWORD okta; // "OKTA" - DWORD song; // "SONG" - DWORD cmod; // "CMOD" - DWORD fixed8; - BYTE chnsetup[8]; - DWORD samp; // "SAMP" - DWORD samplen; -} OKTFILEHEADER; - - -typedef struct OKTSAMPLE -{ - CHAR name[20]; - DWORD length; - WORD loopstart; - WORD looplen; - BYTE pad1; - BYTE volume; - BYTE pad2; - BYTE pad3; -} OKTSAMPLE; - - -BOOL CSoundFile::ReadOKT(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - const OKTFILEHEADER *pfh = (OKTFILEHEADER *)lpStream; - DWORD dwMemPos = sizeof(OKTFILEHEADER); - UINT nsamples = 0, npatterns = 0, norders = 0; - - if ((!lpStream) || (dwMemLength < 1024)) return FALSE; - if ((pfh->okta != 0x41544B4F) || (pfh->song != 0x474E4F53) - || (pfh->cmod != 0x444F4D43) || (pfh->chnsetup[0]) || (pfh->chnsetup[2]) - || (pfh->chnsetup[4]) || (pfh->chnsetup[6]) || (pfh->fixed8 != 0x08000000) - || (pfh->samp != 0x504D4153)) return FALSE; - m_nType = MOD_TYPE_OKT; - m_nChannels = 4 + pfh->chnsetup[1] + pfh->chnsetup[3] + pfh->chnsetup[5] + pfh->chnsetup[7]; - if (m_nChannels > MAX_CHANNELS) m_nChannels = MAX_CHANNELS; - nsamples = bswapBE32(pfh->samplen) >> 5; - m_nSamples = nsamples; - if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; - // Reading samples - for (UINT smp=1; smp <= nsamples; smp++) - { - if (dwMemPos >= dwMemLength) return TRUE; - if (smp < MAX_SAMPLES) - { - OKTSAMPLE *psmp = (OKTSAMPLE *)(lpStream + dwMemPos); - MODINSTRUMENT *pins = &Ins[smp]; - - memcpy(m_szNames[smp], psmp->name, 20); - pins->uFlags = 0; - pins->nLength = bswapBE32(psmp->length) & ~1; - pins->nLoopStart = bswapBE16(psmp->loopstart); - pins->nLoopEnd = pins->nLoopStart + bswapBE16(psmp->looplen); - if (pins->nLoopStart + 2 < pins->nLoopEnd) pins->uFlags |= CHN_LOOP; - pins->nGlobalVol = 64; - pins->nVolume = psmp->volume << 2; - pins->nC4Speed = 8363; - } - dwMemPos += sizeof(OKTSAMPLE); - } - // SPEE - if (dwMemPos >= dwMemLength) return TRUE; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x45455053) - { - m_nDefaultSpeed = lpStream[dwMemPos+9]; - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // SLEN - if (dwMemPos >= dwMemLength) return TRUE; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C53) - { - npatterns = lpStream[dwMemPos+9]; - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // PLEN - if (dwMemPos >= dwMemLength) return TRUE; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C50) - { - norders = lpStream[dwMemPos+9]; - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // PATT - if (dwMemPos >= dwMemLength) return TRUE; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x54544150) - { - UINT orderlen = norders; - if (orderlen >= MAX_ORDERS) orderlen = MAX_ORDERS-1; - for (UINT i=0; i1; j--) { if (Order[j-1]) break; Order[j-1] = 0xFF; } - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // PBOD - UINT npat = 0; - while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250)) - { - DWORD dwPos = dwMemPos + 10; - UINT rows = lpStream[dwMemPos+9]; - if (!rows) rows = 64; - if (npat < MAX_PATTERNS) - { - if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; - MODCOMMAND *m = Patterns[npat]; - PatternSize[npat] = rows; - UINT imax = m_nChannels*rows; - for (UINT i=0; i dwMemLength) break; - const BYTE *p = lpStream+dwPos; - UINT note = p[0]; - if (note) - { - m->note = note + 48; - m->instr = p[1] + 1; - } - UINT command = p[2]; - UINT param = p[3]; - m->param = param; - switch(command) - { - // 0: no effect - case 0: - break; - // 1: Portamento Up - case 1: - case 17: - case 30: - if (param) m->command = CMD_PORTAMENTOUP; - break; - // 2: Portamento Down - case 2: - case 13: - case 21: - if (param) m->command = CMD_PORTAMENTODOWN; - break; - // 10: Arpeggio - case 10: - case 11: - case 12: - m->command = CMD_ARPEGGIO; - break; - // 15: Filter - case 15: - m->command = CMD_MODCMDEX; - m->param = param & 0x0F; - break; - // 25: Position Jump - case 25: - m->command = CMD_POSITIONJUMP; - break; - // 28: Set Speed - case 28: - m->command = CMD_SPEED; - break; - // 31: Volume Control - case 31: - if (param <= 0x40) m->command = CMD_VOLUME; else - if (param <= 0x50) { m->command = CMD_VOLUMESLIDE; m->param &= 0x0F; if (!m->param) m->param = 0x0F; } else - if (param <= 0x60) { m->command = CMD_VOLUMESLIDE; m->param = (param & 0x0F) << 4; if (!m->param) m->param = 0xF0; } else - if (param <= 0x70) { m->command = CMD_MODCMDEX; m->param = 0xB0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xBF; } else - if (param <= 0x80) { m->command = CMD_MODCMDEX; m->param = 0xA0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xAF; } - break; - } - } - } - npat++; - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // SBOD - UINT nsmp = 1; - while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253)) - { - if (nsmp < MAX_SAMPLES) ReadSample(&Ins[nsmp], RS_PCM8S, (LPSTR)(lpStream+dwMemPos+8), dwMemLength-dwMemPos-8); - dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - nsmp++; - } - return TRUE; -} - diff --git a/jni/load_pat.cpp b/jni/load_pat.cpp deleted file mode 100644 index 85d62dd..0000000 --- a/jni/load_pat.cpp +++ /dev/null @@ -1,1662 +0,0 @@ -/* - - MikMod Sound System - - By Jake Stine of Divine Entertainment (1996-2000) - - Support: - If you find problems with this code, send mail to: - air@divent.org - - Distribution / Code rights: - Use this source code in any fashion you see fit. Giving me credit where - credit is due is optional, depending on your own levels of integrity and - honesty. - - ----------------------------------------- - Module: LOAD_PAT - - PAT sample loader. - by Peter Grootswagers (2006) - - - It's primary purpose is loading samples for the .abc and .mid modules - Can also be used stand alone, in that case a tune (frere Jacques) - is generated using al samples available in the .pat file - - Portability: - All systems - all compilers (hopefully) -*/ - -#include -#include -#include -#include -#include -#ifndef _WIN32 -#include // for PATH_MAX -#include // for sleep -#endif -#ifndef PATH_MAX -#define PATH_MAX 256 -#endif - -#ifdef NEWMIKMOD -#include "mikmod.h" -#include "uniform.h" -typedef UBYTE BYTE; -typedef UWORD WORD; -#else -#include "stdafx.h" -#include "sndfile.h" -#endif - -#include "load_pat.h" - -#ifdef MSC_VER -#define DIRDELIM '\\' -#define TIMIDITYCFG "C:\\TIMIDITY\\TIMIDITY.CFG" -#define PATHFORPAT "C:\\TIMIDITY\\INSTRUMENTS" -#else -#define DIRDELIM '/' -#define TIMIDITYCFG "/usr/local/share/timidity/timidity.cfg" -#define PATHFORPAT "/usr/local/share/timidity/instruments" -#endif - -#define PAT_ENV_PATH2CFG "MMPAT_PATH_TO_CFG" - -// 128 gm and 63 drum -#define MAXSMP 191 -static char midipat[MAXSMP][128]; -static char pathforpat[128]; -static char timiditycfg[128]; - -#pragma pack(1) - -typedef struct { - char header[12]; // ascizz GF1PATCH110 - char gravis_id[10]; // allways ID#000002 - char description[60]; - BYTE instruments; - BYTE voices; - BYTE channels; - WORD waveforms; - WORD master_volume; - DWORD data_size; - char reserved[36]; -} PatchHeader; - -typedef struct { - WORD instrument_id; - char instrument_name[16]; - DWORD instrument_size; - BYTE layers; - char reserved[40]; -} InstrumentHeader; - -typedef struct { - BYTE layer_dup; - BYTE layer_id; - DWORD layer_size; - BYTE samples; - char reserved[40]; -} LayerHeader; - -typedef struct { - char wave_name[7]; - BYTE fractions; - DWORD wave_size; - DWORD start_loop; - DWORD end_loop; - WORD sample_rate; - DWORD low_frequency ; - DWORD high_frequency; - DWORD root_frequency; - short int tune; - BYTE balance; - BYTE envelope_rate[6]; - BYTE envelope_offset[6]; - BYTE tremolo_sweep; - BYTE tremolo_rate; - BYTE tremolo_depth; - BYTE vibrato_sweep; - BYTE vibrato_rate; - BYTE vibrato_depth; - BYTE modes; - DWORD scale_frequency; - DWORD scale_factor; - char reserved[32]; -} WaveHeader; - -// WaveHeader.modes bits -#define PAT_16BIT 1 -#define PAT_UNSIGNED 2 -#define PAT_LOOP 4 -#define PAT_PINGPONG 8 -#define PAT_BACKWARD 16 -#define PAT_SUSTAIN 32 -#define PAT_ENVELOPE 64 -#define PAT_CLAMPED 128 - -#define C4SPD 8363 -#define C4mHz 523251 -#define C4 523.251f -#define PI 3.141592653589793f -#define OMEGA ((2.0f * PI * C4)/(float)C4SPD) - -/************************************************************************** -**************************************************************************/ -#ifdef NEWMIKMOD -static char PAT_Version[] = "Timidity GUS Patch v1.0"; -#endif -static BYTE pat_gm_used[MAXSMP]; -static BYTE pat_loops[MAXSMP]; - -/************************************************************************** -**************************************************************************/ - -typedef struct _PATHANDLE -{ -#ifdef NEWMIKMOD - MM_ALLOC *allochandle; -#endif - char patname[16]; - int samples; -} PATHANDLE; - -#ifndef HAVE_SINF -static inline float sinf(float x) { -/* default to double version */ - return((float)sin((double)x)); -} -#endif - -// local prototypes -static int pat_getopt(const char *s, const char *o, int dflt); - -static void pat_message(const char *s1, const char *s2) -{ - char txt[256]; - if( strlen(s1) + strlen(s2) > 255 ) return; - sprintf(txt, s1, s2); -#ifdef NEWMIKMOD - _mmlog(txt); -#else - fprintf(stderr, "load_pat > %s\n", txt); -#endif -} - -void pat_resetsmp(void) -{ - int i; - for( i=0; i MAXSMP ) { - sprintf(buf, "invalid gm %d", gm); - return buf; - } - return midipat[gm - 1]; -} - -int pat_gm_drumnr(int n) -{ - if( n < 25 ) return 129; - if( n+129-25 < MAXSMP ) - return 129+n-25; // timidity.cfg drum patches start at 25 - return MAXSMP; -} - -int pat_gm_drumnote(int n) -{ - char *p; - p = strchr(midipat[pat_gm_drumnr(n)-1], ':'); - if( p ) return pat_getopt(p+1, "note", n); - return n; -} - -static float pat_sinus(int i) -{ - float res = sinf(OMEGA * (float)i); - return res; -} - -static float pat_square(int i) -{ - float res = 30.0f * sinf(OMEGA * (float)i); - if( res > 0.99f ) return 0.99f; - if( res < -0.99f ) return -0.99f; - return res; -} - -static float pat_sawtooth(int i) -{ - float res = OMEGA * (float)i; - while( res > 2 * PI ) - res -= 2 * PI; - i = 2; - if( res > PI ) { - res = PI - res; - i = -2; - } - res = (float)i * res / PI; - if( res > 0.9f ) return 1.0f - res; - if( res < -0.9f ) return 1.0f + res; - return res; -} - -typedef float (*PAT_SAMPLE_FUN)(int); - -static PAT_SAMPLE_FUN pat_fun[] = { pat_sinus, pat_square, pat_sawtooth }; - -#ifdef NEWMIKMOD - -#define MMFILE MMSTREAM -#define mmftell(x) _mm_ftell(x) -#define mmfseek(f,p,w) _mm_fseek(f,p,w) -#define mmreadUBYTES(buf,sz,f) _mm_read_UBYTES(buf,sz,f) - -#else - -#if defined(WIN32) && defined(_mm_free) -#undef _mm_free -#endif - -#define MMSTREAM FILE -#define _mm_fopen(name,mode) fopen(name,mode) -#define _mm_fgets(f,buf,sz) fgets(buf,sz,f) -#define _mm_fseek(f,pos,whence) fseek(f,pos,whence) -#define _mm_ftell(f) ftell(f) -#define _mm_read_UBYTES(buf,sz,f) fread(buf,sz,1,f) -#define _mm_read_SBYTES(buf,sz,f) fread(buf,sz,1,f) -#define _mm_feof(f) feof(f) -#define _mm_fclose(f) fclose(f) -#define DupStr(h,buf,sz) strdup(buf) -#define _mm_calloc(h,n,sz) calloc(n,sz) -#define _mm_recalloc(h,buf,sz,elsz) realloc(buf,sz) -#define _mm_free(h,p) free(p) - -typedef struct { - char *mm; - int sz; - int pos; - int error; -} MMFILE; - -static long mmftell(MMFILE *mmfile) -{ - return mmfile->pos; -} - -static void mmfseek(MMFILE *mmfile, long p, int whence) -{ - int newpos = mmfile->pos; - switch(whence) { - case SEEK_SET: - newpos = p; - break; - case SEEK_CUR: - newpos += p; - break; - case SEEK_END: - newpos = mmfile->sz + p; - break; - } - if (newpos < mmfile->sz) - mmfile->pos = newpos; - else { - mmfile->error = 1; -// printf("WARNING: seeking too far\n"); - } -} - -static void mmreadUBYTES(BYTE *buf, long sz, MMFILE *mmfile) -{ - // do not overread. - if (sz > mmfile->sz - mmfile->pos) - sz = mmfile->sz - mmfile->pos; - memcpy(buf, &mmfile->mm[mmfile->pos], sz); - mmfile->pos += sz; -} - -static void mmreadSBYTES(char *buf, long sz, MMFILE *mmfile) -{ - // do not overread. - if (sz > mmfile->sz - mmfile->pos) - sz = mmfile->sz - mmfile->pos; - memcpy(buf, &mmfile->mm[mmfile->pos], sz); - mmfile->pos += sz; -} - -#endif - -long _mm_getfsize(MMSTREAM *mmpat) { - long fsize; - _mm_fseek(mmpat, 0L, SEEK_END); - fsize = _mm_ftell(mmpat); - _mm_fseek(mmpat, 0L, SEEK_SET); - return(fsize); -} - -void pat_init_patnames(void) -{ - int z, i, nsources, isdrumset, nskip, pfnlen; - char *p, *q; - char line[PATH_MAX]; - char cfgsources[5][PATH_MAX] = {{0}, {0}, {0}, {0}, {0}}; - MMSTREAM *mmcfg; - strcpy(pathforpat, PATHFORPAT); - strcpy(timiditycfg, TIMIDITYCFG); - p = getenv(PAT_ENV_PATH2CFG); - if( p ) { - strcpy(timiditycfg,p); - strcpy(pathforpat,p); - strcat(timiditycfg,"/timidity.cfg"); - strcat(pathforpat,"/instruments"); - } - strncpy(cfgsources[0], timiditycfg, PATH_MAX); - nsources = 1; - - for( i=0; i= 0 && *p != '#' ) { - q = isdrumset ? midipat[pat_gm_drumnr(i)-1] : midipat[i]; - pfnlen = 0; - while( *p && !isspace(*p) && *p != '#' && pfnlen < 128 ) { - pfnlen ++; - *q++ = *p++; - } - if( isblank(*p) && *(p+1) != '#' && pfnlen < 128 ) { - *q++ = ':'; pfnlen ++; - while( isspace(*p) ) { - while( isspace(*p) ) p++; - if ( *p == '#' ) { // comment - - } else while( *p && !isspace(*p) && pfnlen < 128 ) { - pfnlen ++; - *q++ = *p++; - } - if( isspace(*p) ) { *q++ = ' '; pfnlen++; } - } - } - *q++ = '\0'; - } - } - if( !strncmp(line,"drumset",7) ) isdrumset = 1; - if( !strncmp(line,"source",6) && nsources < 5 ) { - q = cfgsources[nsources]; - p = &line[7]; - while ( isspace(*p) ) p ++; - pfnlen = 0; - while ( *p && *p != '#' && !isspace(*p) && pfnlen < 128 ) { - pfnlen ++; - *q++ = *p++; - } - *q = 0; // null termination - nsources++; - } - _mm_fgets(mmcfg, line, PATH_MAX); - - } /* end file parsing */ - _mm_fclose(mmcfg); - } - } - q = midipat[0]; - nskip = 0; - // make all empty patches duplicates the previous valid one. - for( i=0; i 0; ) { - if( midipat[i][0] ) q = midipat[i]; - else if( midipat[i] != q ) - strcpy(midipat[i], q); - } - } -} - -static char *pat_build_path(char *fname, int pat) -{ - char *ps; - char *patfile = midipat[pat]; - int isabspath = (patfile[0] == '/'); - if ( isabspath ) patfile ++; - ps = strrchr(patfile, ':'); - if( ps ) { - sprintf(fname, "%s%c%s", isabspath ? "" : pathforpat, DIRDELIM, patfile); - strcpy(strrchr(fname, ':'), ".pat"); - return ps; - } - sprintf(fname, "%s%c%s.pat", isabspath ? "" : pathforpat, DIRDELIM, patfile); - return 0; -} - -static void pat_read_patname(PATHANDLE *h, MMFILE *mmpat) { - InstrumentHeader ih; - mmfseek(mmpat,sizeof(PatchHeader), SEEK_SET); - mmreadUBYTES((BYTE *)&ih, sizeof(InstrumentHeader), mmpat); - strncpy(h->patname, ih.instrument_name, 16); - h->patname[15] = '\0'; -} - -static void pat_read_layerheader(MMSTREAM *mmpat, LayerHeader *hl) -{ - _mm_fseek(mmpat,sizeof(PatchHeader)+sizeof(InstrumentHeader), SEEK_SET); - _mm_read_UBYTES((BYTE *)hl, sizeof(LayerHeader), mmpat); -} - -static void pat_get_layerheader(MMFILE *mmpat, LayerHeader *hl) -{ - InstrumentHeader ih; - mmfseek(mmpat,sizeof(PatchHeader), SEEK_SET); - mmreadUBYTES((BYTE *)&ih, sizeof(InstrumentHeader), mmpat); - mmreadUBYTES((BYTE *)hl, sizeof(LayerHeader), mmpat); - strncpy(hl->reserved, ih.instrument_name, 40); -} - -static int pat_read_numsmp(MMFILE *mmpat) { - LayerHeader hl; - pat_get_layerheader(mmpat, &hl); - return hl.samples; -} - -static void pat_read_waveheader(MMSTREAM *mmpat, WaveHeader *hw, int layer) -{ - long int pos, bestpos=0; - LayerHeader hl; - ULONG bestfreq, freqdist; - int i; - // read the very first and maybe only sample - pat_read_layerheader(mmpat, &hl); - if( hl.samples > 1 ) { - if( layer ) { - if( layer > hl.samples ) layer = hl.samples; // you don't fool me.... - for( i=1; iwave_size, SEEK_CUR); - } - } - else { - bestfreq = C4mHz * 1000; // big enough - for( i=0; iroot_frequency > C4mHz ) - freqdist = hw->root_frequency - C4mHz; - else - freqdist = 2 * (C4mHz - hw->root_frequency); - if( freqdist < bestfreq ) { - bestfreq = freqdist; - bestpos = pos; - } - _mm_fseek(mmpat, hw->wave_size, SEEK_CUR); - } - _mm_fseek(mmpat, bestpos, SEEK_SET); - } - } - _mm_read_UBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat); - strncpy(hw->reserved, hl.reserved, 36); - if( hw->start_loop >= hw->wave_size ) { - hw->start_loop = 0; - hw->end_loop = 0; - hw->modes &= ~PAT_LOOP; // mask off loop indicator - } - if( hw->end_loop > hw->wave_size ) - hw->end_loop = hw->wave_size; -} - -#ifndef NEWMIKMOD -static void pat_get_waveheader(MMFILE *mmpat, WaveHeader *hw, int layer) -{ - long int pos, bestpos=0; - LayerHeader hl; - ULONG bestfreq, freqdist; - int i; - // read the very first and maybe only sample - pat_get_layerheader(mmpat, &hl); - if( hl.samples > 1 ) { - if( layer ) { - if( layer > hl.samples ) layer = hl.samples; // you don't fool me.... - for( i=1; iwave_size, SEEK_CUR); - if ( mmpat->error ) { - hw->wave_size = 0; - return; - } - } - } - else { - bestfreq = C4mHz * 1000; // big enough - for( i=0; iroot_frequency > C4mHz ) - freqdist = hw->root_frequency - C4mHz; - else - freqdist = 2 * (C4mHz - hw->root_frequency); - if( freqdist < bestfreq ) { - bestfreq = freqdist; - bestpos = pos; - } - mmfseek(mmpat, hw->wave_size, SEEK_CUR); - } - mmfseek(mmpat, bestpos, SEEK_SET); - } - } - mmreadUBYTES((BYTE *)hw, sizeof(WaveHeader), mmpat); - if( hw->start_loop >= hw->wave_size ) { - hw->start_loop = 0; - hw->end_loop = 0; - hw->modes &= ~PAT_LOOP; // mask off loop indicator - } - if( hw->end_loop > hw->wave_size ) - hw->end_loop = hw->wave_size; -} -#endif - -static int pat_readpat_attr(int pat, WaveHeader *hw, int layer) -{ - char fname[128]; - int fsize; - MMSTREAM *mmpat; - pat_build_path(fname, pat); - mmpat = _mm_fopen(fname, "r"); - if( !mmpat ) - return 0; - fsize = _mm_getfsize(mmpat); - pat_read_waveheader(mmpat, hw, layer); - _mm_fclose(mmpat); - if (hw->wave_size > fsize) - return 0; - return 1; -} - -static void pat_amplify(char *b, int num, int amp, int m) -{ - char *pb; - BYTE *pu; - short int *pi; - WORD *pw; - int i,n,v; - n = num; - if( m & PAT_16BIT ) { // 16 bit - n >>= 1; - if( m & 2 ) { // unsigned - pw = (WORD *)b; - for( i=0; i 0x7fff ) v = 0x7fff; - *pw++ = v + 0x8000; - } - } - else { - pi = (short int *)b; - for( i=0; i 0x7fff ) v = 0x7fff; - *pi++ = v; - } - } - } - else { - if( m & 2 ) { // unsigned - pu = (BYTE *)b; - for( i=0; i 0x7f ) v = 0x7f; - *pu++ = v + 0x80; - } - } - else { - pb = (char *)b; - for( i=0; i 0x7f ) v = 0x7f; - *pb++ = v; - } - } - } -} - -static int pat_getopt(const char *s, const char *o, int dflt) -{ - const char *p; - if( !s ) return dflt; - p = strstr(s,o); - if( !p ) return dflt; - return atoi(strchr(p,'=')+1); -} - -static void pat_readpat(int pat, char *dest, int num) -{ - static int readlasttime = 0, wavesize = 0; - static MMSTREAM *mmpat = 0; - static char *opt = 0; - int amp; - char fname[128]; - WaveHeader hw; -#ifdef NEWMIKMOD - static int patlast = MAXSMP; - if( !dest ) { // reset - if( mmpat ) _mm_fclose(mmpat); - readlasttime = 0; - wavesize = 0; - mmpat = 0; - patlast = MAXSMP; - return; - } - if( pat != patlast ) { // reset for other instrument - if( mmpat ) _mm_fclose(mmpat); - readlasttime = 0; - patlast = pat; - } -#endif - if( !readlasttime ) { - opt=pat_build_path(fname, pat); - mmpat = _mm_fopen(fname, "r"); - if( !mmpat ) - return; - pat_read_waveheader(mmpat, &hw, 0); - wavesize = hw.wave_size; - } - _mm_read_SBYTES(dest, num, mmpat); - amp = pat_getopt(opt,"amp",100); - if( amp != 100 ) pat_amplify(dest, num, amp, hw.modes); - readlasttime += num; - if( readlasttime < wavesize ) return; - readlasttime = 0; - _mm_fclose(mmpat); - mmpat = 0; -} - -#ifdef NEWMIKMOD -// next code pinched from dec_raw.c and rebuild to load bytes from different places -// ===================================================================================== -static void *dec_pat_Init(MMSTREAM *mmfp) -{ - pat_readpat(0,0,0); // initialize pat loader - return (void *)mmfp; -} - -static void dec_pat_Cleanup(void *raw) -{ -} - -static BOOL dec_pat_Decompress16Bit(void *raw, short int *dest, int cbcount, MMSTREAM *mmfp) -{ - long samplenum = _mm_ftell(mmfp) - 1; -#else -static BOOL dec_pat_Decompress16Bit(short int *dest, int cbcount, int samplenum) -{ -#endif - int i; - PAT_SAMPLE_FUN f; - if( samplenum < MAXSMP ) pat_readpat(samplenum, (char *)dest, cbcount*2); - else { - f = pat_fun[(samplenum - MAXSMP) % 3]; - for( i=0; iallochandle) { - _mmalloc_close(handle->allochandle); - handle->allochandle = 0; - } -#else - if(handle) { - free(handle); - } -#endif -} - -static char tune[] = "c d e c|c d e c|e f g..|e f g..|gagfe c|gagfe c|c G c..|c G c..|"; -static int pat_note(int abc) -{ - switch( abc ) { - case 'C': return 48; - case 'D': return 50; - case 'E': return 52; - case 'F': return 53; - case 'G': return 55; - case 'A': return 57; - case 'B': return 59; - case 'c': return 60; - case 'd': return 62; - case 'e': return 64; - case 'f': return 65; - case 'g': return 67; - case 'a': return 69; - case 'b': return 71; - default: - break; - } - return 0; -} - -int pat_modnote(int midinote) -{ - int n; - n = midinote; -#ifdef NEWMIKMOD - if( n < 12 ) n++; - else n-=11; -#else - n += 13; -#endif - return n; -} - -// ===================================================================================== -#ifdef NEWMIKMOD -static void PAT_ReadPatterns(UNIMOD *of, PATHANDLE *h, int numpat) -// ===================================================================================== -{ - int pat,row,i,ch; - BYTE n,ins,vol; - int t; - int tt1, tt2; - UNITRK_EFFECT eff; - - tt2 = (h->samples - 1) * 16 + 128; - for( pat = 0; pat < numpat; pat++ ) { - utrk_reset(of->ut); - for( row = 0; row < 64; row++ ) { - tt1 = (pat * 64 + row); - for( ch = 0; ch < h->samples; ch++ ) { - t = tt1 - ch * 16; - if( t >= 0 ) { - i = tt2 - 16 * ((h->samples - 1 - ch) & 3); - if( tt1 < i ) { - t = t % 64; - if( isalpha(tune[t]) ) { - utrk_settrack(of->ut, ch); - n = pat_modnote(pat_note(tune[t])); - ins = ch; - vol = 100; - if( (t % 16) == 0 ) { - vol += vol / 10; - if( vol > 127 ) vol = 127; - } - utrk_write_inst(of->ut, ins); - utrk_write_note(of->ut, n); // <- normal note - pt_write_effect(of->ut, 0xc, vol); - } - if( tt1 == i - 1 && ch == 0 && row < 63 ) { - eff.effect = UNI_GLOB_PATBREAK; - eff.param.u = 0; - eff.framedly = UFD_RUNONCE; - utrk_write_global(of->ut, &eff, UNIMEM_NONE); - } - } - else { - if( tt1 == i ) { - eff.param.u = 0; - eff.effect = UNI_NOTEKILL; - utrk_write_local(of->ut, &eff, UNIMEM_NONE); - } - } - } - } - utrk_newline(of->ut); - } - if(!utrk_dup_pattern(of->ut,of)) return; - } -} - -#else - -static void PAT_ReadPatterns(MODCOMMAND *pattern[], WORD psize[], PATHANDLE *h, int numpat) -// ===================================================================================== -{ - int pat,row,i,ch; - BYTE n,ins,vol; - int t; - int tt1, tt2; - MODCOMMAND *m; - if( numpat > MAX_PATTERNS ) numpat = MAX_PATTERNS; - - tt2 = (h->samples - 1) * 16 + 128; - for( pat = 0; pat < numpat; pat++ ) { - pattern[pat] = CSoundFile::AllocatePattern(64, h->samples); - if( !pattern[pat] ) return; - psize[pat] = 64; - for( row = 0; row < 64; row++ ) { - tt1 = (pat * 64 + row); - for( ch = 0; ch < h->samples; ch++ ) { - t = tt1 - ch * 16; - m = &pattern[pat][row * h->samples + ch]; - m->param = 0; - m->command = CMD_NONE; - if( t >= 0 ) { - i = tt2 - 16 * ((h->samples - 1 - ch) & 3); - if( tt1 < i ) { - t = t % 64; - if( isalpha(tune[t]) ) { - n = pat_modnote(pat_note(tune[t])); - ins = ch + 1; - vol = 40; - if( (t % 16) == 0 ) { - vol += vol / 10; - if( vol > 64 ) vol = 64; - } - m->instr = ins; - m->note = n; // <- normal note - m->volcmd = VOLCMD_VOLUME; - m->vol = vol; - } - if( tt1 == i - 1 && ch == 0 && row < 63 ) { - m->command = CMD_PATTERNBREAK; - } - } - else { - if( tt1 == i ) { - m->param = 0; - m->command = CMD_KEYOFF; - m->volcmd = VOLCMD_VOLUME; - m->vol = 0; - } - } - } - } - } - } -} - -#endif - -// calculate the best speed that approximates the pat root frequency as a C note -static ULONG pat_patrate_to_C4SPD(ULONG patRate , ULONG patMilliHz) -{ - ULONG u; - double x, y; - u = patMilliHz; - x = 0.1 * patRate; - x = x * C4mHz; - y = u * 0.4; - x = x / y; - u = (ULONG)(x+0.5); - return u; -} - -// return relative position in samples for the rate starting with offset start ending with offset end -static int pat_envelope_rpos(int rate, int start, int end) -{ - int r, p, t, s; - // rate byte is 3 bits exponent and 6 bits increment size - // eeiiiiii - // every 8 to the power ee the volume is incremented/decremented by iiiiii - // Thank you Gravis for this weirdness... - r = 3 - ((rate >> 6) & 3) * 3; - p = rate & 0x3f; - if( !p ) return 0; - t = end - start; - if( !t ) return 0; - if (t < 0) t = -t; - s = (t << r)/ p; - return s; -} - -static void pat_modenv(WaveHeader *hw, int mpos[6], int mvol[6]) -{ - int i, sum, s; - BYTE *prate = hw->envelope_rate, *poffset = hw->envelope_offset; - for( i=0; i<6; i++ ) { - mpos[i] = 0; - mvol[i] = 64; - } - if( !memcmp(prate, "??????", 6) || poffset[5] >= 100 ) return; // weird rates or high env end volume - if( !(hw->modes & PAT_SUSTAIN) ) return; // no sustain thus no need for envelope - s = hw->wave_size; - if (s == 0) return; - if( hw->modes & PAT_16BIT ) - s >>= 1; - // offsets 0 1 2 3 4 5 are distributed over 0 2 4 6 8 10, the odd numbers are set in between - sum = 0; - for( i=0; i<6; i++ ) { - mvol[i] = poffset[i]; - mpos[i] = pat_envelope_rpos(prate[i], i? poffset[i-1]: 0, poffset[i]); - sum += mpos[i]; - } - if( sum == 0 ) return; - if( sum > s ) { - for( i=0; i<6; i++ ) - mpos[i] = (s * mpos[i]) / sum; - } - for( i=1; i<6; i++ ) - mpos[i] += mpos[i-1]; - for( i=0; i<6 ; i++ ) { - mpos[i] = (256 * mpos[i]) / s; - mpos[i]++; - if( i > 0 && mpos[i] <= mpos[i-1] ) { - if( mvol[i] == mvol[i-1] ) mpos[i] = mpos[i-1]; - else mpos[i] = mpos[i-1] + 1; - } - if( mpos[i] > 256 ) mpos[i] = 256; - } - mvol[5] = 0; // kill Bill.... -} - -#ifdef NEWMIKMOD -static void pat_setpat_inst(WaveHeader *hw, INSTRUMENT *d, int smp) -{ - int u, inuse; - int envpoint[6], envvolume[6]; - for(u=0; u<120; u++) { - d->samplenumber[u] = smp; - d->samplenote[u] = smp; - } - d->globvol = 64; - d->volfade = 0; - d->volflg = EF_CARRY; - d->panflg = EF_CARRY; - if( hw->modes & PAT_ENVELOPE ) d->volflg |= EF_ON; - if( hw->modes & PAT_SUSTAIN ) d->volflg |= EF_SUSTAIN; - if( (hw->modes & PAT_LOOP) && (hw->start_loop != hw->end_loop) ) d->volflg |= EF_LOOP; - d->volsusbeg = 1; - d->volsusend = 1; - d->volbeg = 1; - d->volend = 2; - d->volpts = 6; - // scale volume envelope: - inuse = 0; - pat_modenv(hw, envpoint, envvolume); - for(u=0; u<6; u++) - { - if( envvolume[u] != 64 ) inuse = 1; - d->volenv[u].val = envvolume[u]<<2; - d->volenv[u].pos = envpoint[u]; - } - if(!inuse) d->volpts = 0; - d->pansusbeg = 0; - d->pansusend = 0; - d->panbeg = 0; - d->panend = 0; - d->panpts = 0; - // scale panning envelope: - for(u=0; u<12; u++) - { - d->panenv[u].val = 0; - d->panenv[u].pos = 0; - } - d->panpts = 0; -} -#else -static void pat_setpat_inst(WaveHeader *hw, INSTRUMENTHEADER *d, int smp) -{ - int u, inuse; - int envpoint[6], envvolume[6]; - d->nMidiProgram = 0; - d->nFadeOut = 0; - d->nPan = 128; - d->nPPC = 5*12; - d->dwFlags = 0; - if( hw->modes & PAT_ENVELOPE ) d->dwFlags |= ENV_VOLUME; - if( hw->modes & PAT_SUSTAIN ) d->dwFlags |= ENV_VOLSUSTAIN; - if( (hw->modes & PAT_LOOP) && (hw->start_loop != hw->end_loop) ) d->dwFlags |= ENV_VOLLOOP; - d->nVolEnv = 6; - //if (!d->nVolEnv) d->dwFlags &= ~ENV_VOLUME; - d->nPanEnv = 0; - d->nVolSustainBegin = 1; - d->nVolSustainEnd = 1; - d->nVolLoopStart = 1; - d->nVolLoopEnd = 2; - d->nPanSustainBegin = 0; - d->nPanSustainEnd = 0; - d->nPanLoopStart = 0; - d->nPanLoopEnd = 0; - d->nGlobalVol = 64; - pat_modenv(hw, envpoint, envvolume); - inuse = 0; - for( u=0; u<6; u++) - { - if( envvolume[u] != 64 ) inuse = 1; - d->VolPoints[u] = envpoint[u]; - d->VolEnv[u] = envvolume[u]; - d->PanPoints[u] = 0; - d->PanEnv[u] = 0; - if (u) - { - if (d->VolPoints[u] < d->VolPoints[u-1]) - { - d->VolPoints[u] &= 0xFF; - d->VolPoints[u] += d->VolPoints[u-1] & 0xFF00; - if (d->VolPoints[u] < d->VolPoints[u-1]) d->VolPoints[u] += 0x100; - } - } - } - if( !inuse ) d->nVolEnv = 0; - for( u=0; u<128; u++) - { - d->NoteMap[u] = u+1; - d->Keyboard[u] = smp; - } -} -#endif -#ifdef NEWMIKMOD -static void PATinst(UNIMOD *of, INSTRUMENT *d, int smp, int gm) -#else -static void PATinst(INSTRUMENTHEADER *d, int smp, int gm) -#endif -{ - WaveHeader hw; - char s[32]; - memset(s,0,32); - if( pat_readpat_attr(gm-1, &hw, 0) ) { - pat_setpat_inst(&hw, d, smp); - } - else { - hw.modes = PAT_16BIT|PAT_ENVELOPE|PAT_SUSTAIN|PAT_LOOP; - hw.start_loop = 0; - hw.end_loop = 30000; - hw.wave_size = 30000; -// envelope rates and offsets pinched from timidity's acpiano.pat sample no 1 - hw.envelope_rate[0] = 0x3f; - hw.envelope_rate[1] = 0x3f; - hw.envelope_rate[2] = 0x3f; - hw.envelope_rate[3] = 0x08|(3<<6); - hw.envelope_rate[4] = 0x3f; - hw.envelope_rate[5] = 0x3f; - hw.envelope_offset[0] = 246; - hw.envelope_offset[1] = 246; - hw.envelope_offset[2] = 246; - hw.envelope_offset[3] = 0; - hw.envelope_offset[4] = 0; - hw.envelope_offset[5] = 0; - strncpy(hw.reserved, midipat[gm-1], sizeof(hw.reserved)); - pat_setpat_inst(&hw, d, smp); - } - if( hw.reserved[0] ) - strncpy(s, hw.reserved, 32); - else - strncpy(s, midipat[gm-1], 32); -#ifdef NEWMIKMOD - d->insname = DupStr(of->allochandle, s,28); -#else - s[31] = '\0'; - memset(d->name, 0, 32); - strcpy((char *)d->name, s); - strncpy(s, midipat[gm-1], 12); - s[11] = '\0'; - memset(d->filename, 0, 12); - strcpy((char *)d->filename, s); -#endif -} - -#ifdef NEWMIKMOD -static void pat_setpat_attr(WaveHeader *hw, UNISAMPLE *q, int gm) -{ - q->seekpos = gm; // dec_pat expects the midi samplenumber in this - q->speed = pat_patrate_to_C4SPD(hw->sample_rate , hw->root_frequency); - q->length = hw->wave_size; - q->loopstart = hw->start_loop; - q->loopend = hw->end_loop; - q->volume = 0x40; - if( hw->modes & PAT_16BIT ) { - q->format |= SF_16BITS; - q->length >>= 1; - q->loopstart >>= 1; - q->loopend >>= 1; - q->speed <<= 1; - } - if( (hw->modes & PAT_UNSIGNED)==0 ) q->format |= SF_SIGNED; - if( hw->modes & PAT_LOOP ) { - q->flags |= SL_LOOP; - if( hw->modes & PAT_PINGPONG ) q->flags |= SL_SUSTAIN_BIDI; - if( hw->modes & PAT_SUSTAIN ) q->flags |= SL_SUSTAIN_LOOP; - } -} -#else -static void pat_setpat_attr(WaveHeader *hw, MODINSTRUMENT *q) -{ - q->nC4Speed = pat_patrate_to_C4SPD(hw->sample_rate , hw->root_frequency); - q->nLength = hw->wave_size; - q->nLoopStart = hw->start_loop; - q->nLoopEnd = hw->end_loop; - q->nVolume = 256; - if( hw->modes & PAT_16BIT ) { - q->nLength >>= 1; - q->nLoopStart >>= 1; - q->nLoopEnd >>= 1; - } - if( hw->modes & PAT_LOOP ) { - q->uFlags |= CHN_LOOP; - if( hw->modes & PAT_PINGPONG ) q->uFlags |= CHN_PINGPONGSUSTAIN; - if( hw->modes & PAT_SUSTAIN ) q->uFlags |= CHN_SUSTAINLOOP; - } -} -#endif - -// ========================== -// Load those darned Samples! -#ifdef NEWMIKMOD -static void PATsample(UNIMOD *of, UNISAMPLE *q, int smp, int gm) -#else -static void PATsample(CSoundFile *cs, MODINSTRUMENT *q, int smp, int gm) -#endif -{ - WaveHeader hw; - char s[256]; - sprintf(s, "%d:%s", smp-1, midipat[gm-1]); -#ifdef NEWMIKMOD - q->samplename = DupStr(of->allochandle, s,28); - if( pat_readpat_attr(gm-1, &hw, 0) ) { - pat_setpat_attr(&hw, q, gm); - pat_loops[smp-1] = (q->flags & (SL_LOOP | SL_SUSTAIN_LOOP))? 1: 0; - } - else { - q->seekpos = smp + MAXSMP + 1; // dec_pat expects the samplenumber in this - q->speed = C4SPD; - q->length = 30000; - q->loopstart = 0; - q->loopend = 30000; - q->volume = 0x40; - - // Enable aggressive declicking for songs that do not loop and that - // are long enough that they won't be adversely affected. - - q->flags |= SL_LOOP; - q->format |= SF_16BITS; - q->format |= SF_SIGNED; - } - if(!(q->flags & (SL_LOOP | SL_SUSTAIN_LOOP)) && (q->length > 5000)) - q->flags |= SL_DECLICK; -#else - s[31] = '\0'; - memset(cs->m_szNames[smp], 0, 32); - strcpy(cs->m_szNames[smp], s); - q->nGlobalVol = 64; - q->nPan = 128; - q->uFlags = CHN_16BIT; - if( pat_readpat_attr(gm-1, &hw, 0) ) { - char *p; - pat_setpat_attr(&hw, q); - pat_loops[smp-1] = (q->uFlags & CHN_LOOP)? 1: 0; - if( hw.modes & PAT_16BIT ) p = (char *)malloc(hw.wave_size); - else p = (char *)malloc(hw.wave_size * sizeof(short int)); - if( p ) { - if( hw.modes & PAT_16BIT ) { - dec_pat_Decompress16Bit((short int *)p, hw.wave_size>>1, gm - 1); - cs->ReadSample(q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size); - } - else { - dec_pat_Decompress8Bit((short int *)p, hw.wave_size, gm - 1); - cs->ReadSample(q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size * sizeof(short int)); - } - free(p); - } - } - else { - char *p; - q->nC4Speed = C4SPD; - q->nLength = 30000; - q->nLoopStart = 0; - q->nLoopEnd = 30000; - q->nVolume = 256; - q->uFlags |= CHN_LOOP; - q->uFlags |= CHN_16BIT; - p = (char *)malloc(q->nLength*sizeof(short int)); - if( p ) { - dec_pat_Decompress8Bit((short int *)p, q->nLength, smp + MAXSMP - 1); - cs->ReadSample(q, RS_PCM16S, (LPSTR)p, q->nLength*2); - free(p); - } - } -#endif -} - -// ===================================================================================== -BOOL PAT_Load_Instruments(void *c) -{ - uint32_t t; -#ifdef NEWMIKMOD - UNIMOD *of = (UNIMOD *)c; - INSTRUMENT *d; - UNISAMPLE *q; - if( !pat_numsmp() ) pat_gmtosmp(1); // make sure there is a sample - of->numsmp = pat_numsmp(); - of->numins = pat_numinstr(); - if(!AllocInstruments(of)) return FALSE; - if(!AllocSamples(of, 0)) return FALSE; - d = of->instruments; - for(t=1; t<=of->numins; t++) { - PATinst(of, d, t, pat_smptogm(t)); - d++; - } - q = of->samples; - for(t=1; t<=of->numsmp; t++) { - PATsample(of, q, t, pat_smptogm(t)); - q++; - } - SL_RegisterDecompressor(&dec_pat); // fool him to generate samples -#else - CSoundFile *of=(CSoundFile *)c; - if( !pat_numsmp() ) pat_gmtosmp(1); // make sure there is a sample - of->m_nSamples = pat_numsmp() + 1; // xmms modplug does not use slot zero - of->m_nInstruments = pat_numinstr() + 1; - for(t=1; tm_nInstruments; t++) { // xmms modplug doesn't use slot zero - if( (of->Headers[t] = new INSTRUMENTHEADER) == NULL ) return FALSE; - memset(of->Headers[t], 0, sizeof(INSTRUMENTHEADER)); - PATinst(of->Headers[t], t, pat_smptogm(t)); - } - for(t=1; tm_nSamples; t++) { // xmms modplug doesn't use slot zero - PATsample(of, &of->Ins[t], t, pat_smptogm(t)); - } - // copy last of the mohicans to entry 0 for XMMS modinfo to work.... - t = of->m_nInstruments - 1; - if( (of->Headers[0] = new INSTRUMENTHEADER) == NULL ) return FALSE; - memcpy(of->Headers[0], of->Headers[t], sizeof(INSTRUMENTHEADER)); - memset(of->Headers[0]->name, 0, 32); - strncpy((char *)of->Headers[0]->name, "Timidity GM patches", 32); - t = of->m_nSamples - 1; - memcpy(&of->Ins[0], &of->Ins[t], sizeof(MODINSTRUMENT)); -#endif - return TRUE; -} -// ===================================================================================== -#ifdef NEWMIKMOD -BOOL PAT_Load(PATHANDLE *h, UNIMOD *of, MMSTREAM *mmfile) -#else -BOOL CSoundFile::ReadPAT(const BYTE *lpStream, DWORD dwMemLength) -#endif -{ - static int avoid_reentry = 0; - char buf[60]; - int t; -#ifdef NEWMIKMOD - UNISAMPLE *q; - INSTRUMENT *d; -#define m_nDefaultTempo of->inittempo -#else - PATHANDLE *h; - int numpat; - MMFILE mm, *mmfile; - MODINSTRUMENT *q; - INSTRUMENTHEADER *d; - if( !TestPAT(lpStream, dwMemLength) ) return FALSE; - h = PAT_Init(); - if( !h ) return FALSE; - mmfile = &mm; - mm.mm = (char *)lpStream; - mm.sz = dwMemLength; - mm.pos = 0; - mm.error = 0; -#endif - while( avoid_reentry ) sleep(1); - avoid_reentry = 1; - pat_read_patname(h, mmfile); - h->samples = pat_read_numsmp(mmfile); - if( strlen(h->patname) ) - sprintf(buf,"%s canon %d-v (Fr. Jacques)", h->patname, h->samples); - else - sprintf(buf,"%d-voice canon (Fr. Jacques)", h->samples); -#ifdef NEWMIKMOD - of->songname = DupStr(of->allochandle, buf, strlen(buf)); -#else - if( strlen(buf) > 31 ) buf[31] = '\0'; // chop it of - strcpy(m_szNames[0], buf); -#endif - m_nDefaultTempo = 60; // 120 / 2 - t = (h->samples - 1) * 16 + 128; - if( t % 64 ) t += 64; - t = t / 64; -#ifdef NEWMIKMOD - of->memsize = PTMEM_LAST; // Number of memory slots to reserve! - of->modtype = _mm_strdup(of->allochandle, PAT_Version); - of->reppos = 0; - of->numins = h->samples; - of->numsmp = h->samples; - of->initspeed = 6; - of->numchn = h->samples; - of->numpat = t; - of->numpos = of->numpat; // one repeating pattern - of->numtrk = of->numpat * of->numchn; - of->initvolume = 64; - of->pansep=128; - // allocate resources - if(!AllocPositions(of, of->numpos)) { - avoid_reentry = 0; - return FALSE; - } - if(!AllocInstruments(of)) { - avoid_reentry = 0; - return FALSE; - } - if(!AllocSamples(of, 0)) { - avoid_reentry = 0; - return FALSE; - } - // orderlist - for(t=0; tnumpos; t++) - of->positions[t] = t; - d = of->instruments; - for(t=1; t<=of->numins; t++) { - WaveHeader hw; - char s[32]; - sprintf(s, "%s", h->patname); - d->insname = DupStr(of->allochandle, s,28); - pat_read_waveheader(mmfile, &hw, t); - pat_setpat_inst(&hw, d, t); - } - q = of->samples; - for(t=1; t<=of->numsmp; t++) { - WaveHeader hw; - char s[28]; - pat_read_waveheader(mmfile, &hw, t); - pat_setpat_attr(&hw, q, _mm_ftell(mmfile)); - memset(s,0,28); - if( hw.wave_name[0] ) - sprintf(s, "%d:%s", t, hw.wave_name); - else - sprintf(s, "%d:%s", t, h->patname); - q->samplename = DupStr(of->allochandle, s,28); - if(!(q->flags & (SL_LOOP | SL_SUSTAIN_LOOP)) && (q->length > 5000)) - q->flags |= SL_DECLICK; - q++; - } -#else - m_nType = MOD_TYPE_PAT; - m_nInstruments = h->samples + 1; // we know better but use each sample in the pat... - m_nSamples = h->samples + 1; // xmms modplug does not use slot zero - m_nDefaultSpeed = 6; - m_nChannels = h->samples; - numpat = t; - - m_dwSongFlags = SONG_LINEARSLIDES; - m_nMinPeriod = 28 << 2; - m_nMaxPeriod = 1712 << 3; - // orderlist - for(t=0; t < numpat; t++) - Order[t] = t; - for(t=1; t<(int)m_nInstruments; t++) { // xmms modplug doesn't use slot zero - WaveHeader hw; - char s[32]; - if( (d = new INSTRUMENTHEADER) == NULL ) { - avoid_reentry = 0; - return FALSE; - } - memset(d, 0, sizeof(INSTRUMENTHEADER)); - Headers[t] = d; - sprintf(s, "%s", h->patname); - s[31] = '\0'; - memset(d->name, 0, 32); - strcpy((char *)d->name, s); - s[11] = '\0'; - memset(d->filename, 0, 12); - strcpy((char *)d->filename, s); - pat_get_waveheader(mmfile, &hw, t); - pat_setpat_inst(&hw, d, t); - } - for(t=1; t<(int)m_nSamples; t++) { // xmms modplug doesn't use slot zero - WaveHeader hw; - char s[32]; - char *p; - q = &Ins[t]; // we do not use slot zero - q->nGlobalVol = 64; - q->nPan = 128; - q->uFlags = CHN_16BIT; - pat_get_waveheader(mmfile, &hw, t); - pat_setpat_attr(&hw, q); - memset(s,0,32); - if( hw.wave_name[0] ) - sprintf(s, "%d:%s", t, hw.wave_name); - else { - if( h->patname[0] ) - sprintf(s, "%d:%s", t, h->patname); - else - sprintf(s, "%d:Untitled GM patch", t); - } - s[31] = '\0'; - memset(m_szNames[t], 0, 32); - strcpy(m_szNames[t], s); - if( hw.modes & PAT_16BIT ) p = (char *)malloc(hw.wave_size); - else p = (char *)malloc(hw.wave_size * sizeof(short int)); - if( p ) { - mmreadSBYTES(p, hw.wave_size, mmfile); - if( hw.modes & PAT_16BIT ) { - ReadSample(q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size); - } - else { - pat_blowup_to16bit((short int *)p, hw.wave_size); - ReadSample(q, (hw.modes&PAT_UNSIGNED)?RS_PCM16U:RS_PCM16S, (LPSTR)p, hw.wave_size * sizeof(short int)); - } - free(p); - } - } - // copy last of the mohicans to entry 0 for XMMS modinfo to work.... - t = m_nInstruments - 1; - if( (Headers[0] = new INSTRUMENTHEADER) == NULL ) { - avoid_reentry = 0; - return FALSE; - } - memcpy(Headers[0], Headers[t], sizeof(INSTRUMENTHEADER)); - memset(Headers[0]->name, 0, 32); - if( h->patname[0] ) - strncpy((char *)Headers[0]->name, h->patname, 32); - else - strncpy((char *)Headers[0]->name, "Timidity GM patch", 32); - t = m_nSamples - 1; - memcpy(&Ins[0], &Ins[t], sizeof(MODINSTRUMENT)); -#endif -#ifdef NEWMIKMOD - // ============================== - // Load the pattern info now! - if(!AllocTracks(of)) return 0; - if(!AllocPatterns(of)) return 0; - of->ut = utrk_init(of->numchn, h->allochandle); - utrk_memory_reset(of->ut); - utrk_local_memflag(of->ut, PTMEM_PORTAMENTO, TRUE, FALSE); - PAT_ReadPatterns(of, h, of->numpat); - // ============================================================ - // set panning positions - for(t=0; tnumchn; t++) { - of->panning[t] = PAN_LEFT+((t+2)%5)*((PAN_RIGHT - PAN_LEFT)/5); // 0x30 = std s3m val - } -#else - // ============================== - // Load the pattern info now! - PAT_ReadPatterns(Patterns, PatternSize, h, numpat); - // ============================================================ - // set panning positions - for(t=0; t<(int)m_nChannels; t++) { - ChnSettings[t].nPan = 0x30+((t+2)%5)*((0xD0 - 0x30)/5); // 0x30 = std s3m val - ChnSettings[t].nVolume = 64; - } -#endif - avoid_reentry = 0; // it is safe now, I'm finished -#ifndef NEWMIKMOD - PAT_Cleanup(h); // we dont need it anymore -#endif - return 1; -} - -#ifdef NEWMIKMOD -// ===================================================================================== -CHAR *PAT_LoadTitle(MMSTREAM *mmfile) -// ===================================================================================== -{ - PATHANDLE dummy; - pat_read_patname(&dummy, mmfile); - return(DupStr(NULL, dummy.patname,strlen(dummy.patname))); -} - -MLOADER load_pat = -{ - "PAT", - "PAT loader 1.0", - 0x30, - NULL, - PAT_Test, - (void *(*)(void))PAT_Init, - (void (*)(ML_HANDLE *))PAT_Cleanup, - /* Every single loader seems to need one of these! */ - (BOOL (*)(ML_HANDLE *, UNIMOD *, MMSTREAM *))PAT_Load, - PAT_LoadTitle -}; -#endif diff --git a/jni/load_pat.h b/jni/load_pat.h deleted file mode 100644 index 21db1f7..0000000 --- a/jni/load_pat.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef LOAD_PAT_H -#define LOAD_PAT_H - -#ifdef __cplusplus -extern "C" { -#endif - -void pat_init_patnames(void); -void pat_resetsmp(void); -int pat_numinstr(void); -int pat_numsmp(void); -int pat_smptogm(int smp); -int pat_gmtosmp(int gm); -int pat_gm_drumnr(int n); -int pat_gm_drumnote(int n); -const char *pat_gm_name(int gm); -int pat_modnote(int midinote); -int pat_smplooped(int smp); -//#ifdef NEWMIKMOD -BOOL PAT_Load_Instruments(void *c); -//#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/jni/load_psm.cpp b/jni/load_psm.cpp deleted file mode 100644 index 9f3f339..0000000 --- a/jni/load_psm.cpp +++ /dev/null @@ -1,866 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - - -/////////////////////////////////////////////////// -// -// PSM module loader -// -/////////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#define PSM_LOG - -#define PSM_ID_NEW 0x204d5350 -#define PSM_ID_OLD 0xfe4d5350 -#define IFFID_FILE 0x454c4946 -#define IFFID_TITL 0x4c544954 -#define IFFID_SDFT 0x54464453 -#define IFFID_PBOD 0x444f4250 -#define IFFID_SONG 0x474e4f53 -#define IFFID_PATT 0x54544150 -#define IFFID_DSMP 0x504d5344 -#define IFFID_OPLH 0x484c504f - -#pragma pack(1) - -typedef struct _PSMCHUNK -{ - DWORD id; - DWORD len; - DWORD listid; -} PSMCHUNK; - -void swap_PSMCHUNK(PSMCHUNK* p){ - p->id = bswapLE32(p->id); - p->len = bswapLE32(p->len); - p->listid = bswapLE32(p->listid); -} - -typedef struct _PSMSONGHDR -{ - CHAR songname[8]; // "MAINSONG" - BYTE reserved1; - BYTE reserved2; - BYTE channels; -} PSMSONGHDR; - -typedef struct _PSMPATTERN -{ - DWORD size; - DWORD name; - WORD rows; - WORD reserved1; - BYTE data[4]; -} PSMPATTERN; - -void swap_PSMPATTERN(PSMPATTERN* p){ - p->size = bswapLE32(p->size); - p->name = bswapLE32(p->name); - p->rows = bswapLE16(p->rows); -} - -typedef struct _PSMSAMPLE -{ - BYTE flags; - CHAR songname[8]; - DWORD smpid; - CHAR samplename[34]; - DWORD reserved1; - BYTE reserved2; - BYTE insno; - BYTE reserved3; - DWORD length; - DWORD loopstart; - DWORD loopend; - WORD reserved4; - BYTE defvol; - DWORD reserved5; - DWORD samplerate; - BYTE reserved6[19]; -} PSMSAMPLE; - -void swap_PSMSAMPLE(PSMSAMPLE* p){ - p->smpid = bswapLE32(p->smpid); - p->length = bswapLE32(p->length); - p->loopstart = bswapLE32(p->loopstart); - p->loopend = bswapLE32(p->loopend); - p->samplerate = bswapLE32(p->samplerate); -} - -#pragma pack() - - -BOOL CSoundFile::ReadPSM(LPCBYTE lpStream, DWORD dwMemLength) -//----------------------------------------------------------- -{ - PSMCHUNK *pfh = (PSMCHUNK *)lpStream; - DWORD dwMemPos, dwSongPos; - DWORD smpnames[MAX_SAMPLES]; - DWORD patptrs[MAX_PATTERNS]; - BYTE samplemap[MAX_SAMPLES]; - UINT nPatterns; - - // Swap chunk - swap_PSMCHUNK(pfh); - - // Chunk0: "PSM ",filesize,"FILE" - if (dwMemLength < 256) return FALSE; - if (pfh->id == PSM_ID_OLD) - { - #ifdef PSM_LOG - Log("Old PSM format not supported\n"); - #endif - return FALSE; - } - if ((pfh->id != PSM_ID_NEW) || (pfh->len+12 > dwMemLength) || (pfh->listid != IFFID_FILE)) return FALSE; - m_nType = MOD_TYPE_PSM; - m_nChannels = 16; - m_nSamples = 0; - nPatterns = 0; - dwMemPos = 12; - dwSongPos = 0; - for (UINT iChPan=0; iChPan<16; iChPan++) - { - UINT pan = (((iChPan & 3) == 1) || ((iChPan&3)==2)) ? 0xC0 : 0x40; - ChnSettings[iChPan].nPan = pan; - } - while (dwMemPos+8 < dwMemLength) - { - PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos); - swap_PSMCHUNK(pchunk); - if ((pchunk->len >= dwMemLength - 8) || (dwMemPos + pchunk->len + 8 > dwMemLength)) break; - dwMemPos += 8; - PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos); - ULONG len = pchunk->len; - if (len) switch(pchunk->id) - { - // "TITL": Song title - case IFFID_TITL: - if (!pdata[0]) { pdata++; len--; } - memcpy(m_szNames[0], pdata, (len>31) ? 31 : len); - m_szNames[0][31] = 0; - break; - // "PBOD": Pattern - case IFFID_PBOD: - if ((len >= 12) && (nPatterns < MAX_PATTERNS)) - { - patptrs[nPatterns++] = dwMemPos-8; - } - break; - // "SONG": Song description - case IFFID_SONG: - if ((len >= sizeof(PSMSONGHDR)+8) && (!dwSongPos)) - { - dwSongPos = dwMemPos - 8; - } - break; - // "DSMP": Sample Data - case IFFID_DSMP: - if ((len >= sizeof(PSMSAMPLE)) && (m_nSamples+1 < MAX_SAMPLES)) - { - m_nSamples++; - MODINSTRUMENT *pins = &Ins[m_nSamples]; - PSMSAMPLE *psmp = (PSMSAMPLE *)pdata; - swap_PSMSAMPLE(psmp); - smpnames[m_nSamples] = psmp->smpid; - memcpy(m_szNames[m_nSamples], psmp->samplename, 31); - m_szNames[m_nSamples][31] = 0; - samplemap[m_nSamples-1] = (BYTE)m_nSamples; - // Init sample - pins->nGlobalVol = 0x40; - pins->nC4Speed = psmp->samplerate; - pins->nLength = psmp->length; - pins->nLoopStart = psmp->loopstart; - pins->nLoopEnd = psmp->loopend; - pins->nPan = 128; - pins->nVolume = (psmp->defvol+1) * 2; - pins->uFlags = (psmp->flags & 0x80) ? CHN_LOOP : 0; - if (pins->nLoopStart > 0) pins->nLoopStart--; - // Point to sample data - pdata += 0x60; - len -= 0x60; - // Load sample data - if ((pins->nLength > 3) && (len > 3)) - { - ReadSample(pins, RS_PCM8D, (LPCSTR)pdata, len); - } else - { - pins->nLength = 0; - } - } - break; - #if 0 - default: - { - CHAR s[8], s2[64]; - *(DWORD *)s = pchunk->id; - s[4] = 0; - wsprintf(s2, "%s: %4d bytes @ %4d\n", s, pchunk->len, dwMemPos); - OutputDebugString(s2); - } - #endif - } - dwMemPos += pchunk->len; - } - // Step #1: convert song structure - PSMSONGHDR *pSong = (PSMSONGHDR *)(lpStream+dwSongPos+8); - if ((!dwSongPos) || (pSong->channels < 2) || (pSong->channels > 32)) return TRUE; - m_nChannels = pSong->channels; - // Valid song header -> convert attached chunks - { - DWORD dwSongEnd = dwSongPos + 8 + *(DWORD *)(lpStream+dwSongPos+4); - dwMemPos = dwSongPos + 8 + 11; // sizeof(PSMCHUNK)+sizeof(PSMSONGHDR) - while (dwMemPos + 8 < dwSongEnd) - { - PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos); - swap_PSMCHUNK(pchunk); - dwMemPos += 8; - if ((pchunk->len > dwSongEnd) || (dwMemPos + pchunk->len > dwSongEnd)) break; - PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos); - ULONG len = pchunk->len; - switch(pchunk->id) - { - case IFFID_OPLH: - if (len >= 0x20) - { - UINT pos = len - 3; - while (pos > 5) - { - BOOL bFound = FALSE; - pos -= 5; - DWORD dwName = *(DWORD *)(pdata+pos); - for (UINT i=0; iname; - if (dwName == dwPatName) - { - bFound = TRUE; - break; - } - } - if ((!bFound) && (pdata[pos+1] > 0) && (pdata[pos+1] <= 0x10) - && (pdata[pos+3] > 0x40) && (pdata[pos+3] < 0xC0)) - { - m_nDefaultSpeed = pdata[pos+1]; - m_nDefaultTempo = pdata[pos+3]; - break; - } - } - UINT iOrd = 0; - while ((pos+5name; - if (dwName == dwPatName) - { - Order[iOrd++] = i; - break; - } - } - pos += 5; - } - } - break; - } - dwMemPos += pchunk->len; - } - } - - // Step #2: convert patterns - for (UINT nPat=0; nPatrows; - if (len > pPsmPat->size) len = pPsmPat->size; - if ((nRows < 64) || (nRows > 256)) nRows = 64; - PatternSize[nPat] = nRows; - if ((Patterns[nPat] = AllocatePattern(nRows, m_nChannels)) == NULL) break; - MODCOMMAND *m = Patterns[nPat]; - BYTE *p = pPsmPat->data; - UINT pos = 0; - UINT row = 0; - UINT oldch = 0; - BOOL bNewRow = FALSE; - #ifdef PSM_LOG - Log("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream)); - #endif - while ((row < nRows) && (pos+1 < len)) - { - UINT flags = p[pos++]; - UINT ch = p[pos++]; - - #ifdef PSM_LOG - //Log("flags+ch: %02X.%02X\n", flags, ch); - #endif - if (((flags & 0xf0) == 0x10) && (ch <= oldch) /*&& (!bNewRow)*/) - { - if ((pos+1= len) || (row >= nRows)) break; - if (!(flags & 0xf0)) - { - #ifdef PSM_LOG - //if (!nPat) Log("EOR(%d): %02X.%02X\n", row, p[pos], p[pos+1]); - #endif - row++; - m += m_nChannels; - bNewRow = TRUE; - oldch = ch; - continue; - } - bNewRow = FALSE; - if (ch >= m_nChannels) - { - #ifdef PSM_LOG - if (!nPat) Log("Invalid channel row=%d (0x%02X.0x%02X)\n", row, flags, ch); - #endif - ch = 0; - } - // Note + Instr - if ((flags & 0x40) && (pos+1 < len)) - { - UINT note = p[pos++]; - UINT nins = p[pos++]; - #ifdef PSM_LOG - //if (!nPat) Log("note+ins: %02X.%02X\n", note, nins); - if ((!nPat) && (nins >= m_nSamples)) Log("WARNING: invalid instrument number (%d)\n", nins); - #endif - if ((note) && (note < 0x80)) note = (note>>4)*12+(note&0x0f)+12+1; - m[ch].instr = samplemap[nins]; - m[ch].note = note; - } - // Volume - if ((flags & 0x20) && (pos < len)) - { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = p[pos++] / 2; - } - // Effect - if ((flags & 0x10) && (pos+1 < len)) - { - UINT command = p[pos++]; - UINT param = p[pos++]; - // Convert effects - switch(command) - { - // 01: fine volslide up - case 0x01: command = CMD_VOLUMESLIDE; param |= 0x0f; break; - // 04: fine volslide down - case 0x04: command = CMD_VOLUMESLIDE; param>>=4; param |= 0xf0; break; - // 0C: portamento up - case 0x0C: command = CMD_PORTAMENTOUP; param = (param+1)/2; break; - // 0E: portamento down - case 0x0E: command = CMD_PORTAMENTODOWN; param = (param+1)/2; break; - // 33: Position Jump - case 0x33: command = CMD_POSITIONJUMP; break; - // 34: Pattern break - case 0x34: command = CMD_PATTERNBREAK; break; - // 3D: speed - case 0x3D: command = CMD_SPEED; break; - // 3E: tempo - case 0x3E: command = CMD_TEMPO; break; - // Unknown - default: - #ifdef PSM_LOG - Log("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param); - #endif - command = param = 0; - } - m[ch].command = (BYTE)command; - m[ch].param = (BYTE)param; - } - oldch = ch; - } - #ifdef PSM_LOG - if (pos < len) - { - Log("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos); - } - #endif - } - - // Done (finally!) - return TRUE; -} - - -////////////////////////////////////////////////////////////// -// -// PSM Old Format -// - -/* - -CONST - c_PSM_MaxOrder = $FF; - c_PSM_MaxSample = $FF; - c_PSM_MaxChannel = $0F; - - TYPE - PPSM_Header = ^TPSM_Header; - TPSM_Header = RECORD - PSM_Sign : ARRAY[01..04] OF CHAR; { PSM + #254 } - PSM_SongName : ARRAY[01..58] OF CHAR; - PSM_Byte00 : BYTE; - PSM_Byte1A : BYTE; - PSM_Unknown00 : BYTE; - PSM_Unknown01 : BYTE; - PSM_Unknown02 : BYTE; - PSM_Speed : BYTE; - PSM_Tempo : BYTE; - PSM_Unknown03 : BYTE; - PSM_Unknown04 : WORD; - PSM_OrderLength : WORD; - PSM_PatternNumber : WORD; - PSM_SampleNumber : WORD; - PSM_ChannelNumber : WORD; - PSM_ChannelUsed : WORD; - PSM_OrderPosition : LONGINT; - PSM_ChannelSettingPosition : LONGINT; - PSM_PatternPosition : LONGINT; - PSM_SamplePosition : LONGINT; - { *** perhaps there are some more infos in a larger header, - but i have not decoded it and so it apears here NOT } - END; - - PPSM_Sample = ^TPSM_Sample; - TPSM_Sample = RECORD - PSM_SampleFileName : ARRAY[01..12] OF CHAR; - PSM_SampleByte00 : BYTE; - PSM_SampleName : ARRAY[01..22] OF CHAR; - PSM_SampleUnknown00 : ARRAY[01..02] OF BYTE; - PSM_SamplePosition : LONGINT; - PSM_SampleUnknown01 : ARRAY[01..04] OF BYTE; - PSM_SampleNumber : BYTE; - PSM_SampleFlags : WORD; - PSM_SampleLength : LONGINT; - PSM_SampleLoopBegin : LONGINT; - PSM_SampleLoopEnd : LONGINT; - PSM_Unknown03 : BYTE; - PSM_SampleVolume : BYTE; - PSM_SampleC5Speed : WORD; - END; - - PPSM_SampleList = ^TPSM_SampleList; - TPSM_SampleList = ARRAY[01..c_PSM_MaxSample] OF TPSM_Sample; - - PPSM_Order = ^TPSM_Order; - TPSM_Order = ARRAY[00..c_PSM_MaxOrder] OF BYTE; - - PPSM_ChannelSettings = ^TPSM_ChannelSettings; - TPSM_ChannelSettings = ARRAY[00..c_PSM_MaxChannel] OF BYTE; - - CONST - PSM_NotesInPattern : BYTE = $00; - PSM_ChannelInPattern : BYTE = $00; - - CONST - c_PSM_SetSpeed = 60; - - FUNCTION PSM_Size(FileName : STRING;FilePosition : LONGINT) : LONGINT; - BEGIN - END; - - PROCEDURE PSM_UnpackPattern(VAR Source,Destination;PatternLength : WORD); - VAR - Witz : ARRAY[00..04] OF WORD; - I1,I2 : WORD; - I3,I4 : WORD; - TopicalByte : ^BYTE; - Pattern : PUnpackedPattern; - ChannelP : BYTE; - NoteP : BYTE; - InfoByte : BYTE; - CodeByte : BYTE; - InfoWord : WORD; - Effect : BYTE; - Opperand : BYTE; - Panning : BYTE; - Volume : BYTE; - PrevInfo : BYTE; - InfoIndex : BYTE; - BEGIN - Pattern := @Destination; - TopicalByte := @Source; - { *** Initialize patttern } - FOR I2 := 0 TO c_Maximum_NoteIndex DO - FOR I3 := 0 TO c_Maximum_ChannelIndex DO - BEGIN - Pattern^[I2,I3,c_Pattern_NoteIndex] := $FF; - Pattern^[I2,I3,c_Pattern_SampleIndex] := $00; - Pattern^[I2,I3,c_Pattern_VolumeIndex] := $FF; - Pattern^[I2,I3,c_Pattern_PanningIndex] := $FF; - Pattern^[I2,I3,c_Pattern_EffectIndex] := $00; - Pattern^[I2,I3,c_Pattern_OpperandIndex] := $00; - END; - { *** Byte-pointer on first pattern-entry } - ChannelP := $00; - NoteP := $00; - InfoByte := $00; - PrevInfo := $00; - InfoIndex := $02; - { *** read notes in pattern } - PSM_NotesInPattern := TopicalByte^; INC(TopicalByte); DEC(PatternLength); INC(InfoIndex); - PSM_ChannelInPattern := TopicalByte^; INC(TopicalByte); DEC(PatternLength); INC(InfoIndex); - { *** unpack pattern } - WHILE (INTEGER(PatternLength) > 0) AND (NoteP < c_Maximum_NoteIndex) DO - BEGIN - { *** Read info-byte } - InfoByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength); INC(InfoIndex); - IF InfoByte <> $00 THEN - BEGIN - ChannelP := InfoByte AND $0F; - IF InfoByte AND 128 = 128 THEN { note and sample } - BEGIN - { *** read note } - CodeByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength); - DEC(CodeByte); - CodeByte := CodeByte MOD 12 * 16 + CodeByte DIV 12 + 2; - Pattern^[NoteP,ChannelP,c_Pattern_NoteIndex] := CodeByte; - { *** read sample } - CodeByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength); - Pattern^[NoteP,ChannelP,c_Pattern_SampleIndex] := CodeByte; - END; - IF InfoByte AND 64 = 64 THEN { Volume } - BEGIN - CodeByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength); - Pattern^[NoteP,ChannelP,c_Pattern_VolumeIndex] := CodeByte; - END; - IF InfoByte AND 32 = 32 THEN { effect AND opperand } - BEGIN - Effect := TopicalByte^; INC(TopicalByte); DEC(PatternLength); - Opperand := TopicalByte^; INC(TopicalByte); DEC(PatternLength); - CASE Effect OF - c_PSM_SetSpeed: - BEGIN - Effect := c_I_Set_Speed; - END; - ELSE - BEGIN - Effect := c_I_NoEffect; - Opperand := $00; - END; - END; - Pattern^[NoteP,ChannelP,c_Pattern_EffectIndex] := Effect; - Pattern^[NoteP,ChannelP,c_Pattern_OpperandIndex] := Opperand; - END; - END ELSE INC(NoteP); - END; - END; - - PROCEDURE PSM_Load(FileName : STRING;FilePosition : LONGINT;VAR Module : PModule;VAR ErrorCode : WORD); - { *** caution : Module has to be inited before!!!! } - VAR - Header : PPSM_Header; - Sample : PPSM_SampleList; - Order : PPSM_Order; - ChannelSettings : PPSM_ChannelSettings; - MultiPurposeBuffer : PByteArray; - PatternBuffer : PUnpackedPattern; - TopicalParaPointer : WORD; - - InFile : FILE; - I1,I2 : WORD; - I3,I4 : WORD; - TempW : WORD; - TempB : BYTE; - TempP : PByteArray; - TempI : INTEGER; - { *** copy-vars for loop-extension } - CopySource : LONGINT; - CopyDestination : LONGINT; - CopyLength : LONGINT; - BEGIN - { *** try to open file } - ASSIGN(InFile,FileName); -{$I-} - RESET(InFile,1); -{$I+} - IF IORESULT <> $00 THEN - BEGIN - EXIT; - END; -{$I-} - { *** seek start of module } - IF FILESIZE(InFile) < FilePosition THEN - BEGIN - EXIT; - END; - SEEK(InFile,FilePosition); - { *** look for enough memory for temporary variables } - IF MEMAVAIL < SIZEOF(TPSM_Header) + SIZEOF(TPSM_SampleList) + - SIZEOF(TPSM_Order) + SIZEOF(TPSM_ChannelSettings) + - SIZEOF(TByteArray) + SIZEOF(TUnpackedPattern) - THEN - BEGIN - EXIT; - END; - { *** init dynamic variables } - NEW(Header); - NEW(Sample); - NEW(Order); - NEW(ChannelSettings); - NEW(MultiPurposeBuffer); - NEW(PatternBuffer); - { *** read header } - BLOCKREAD(InFile,Header^,SIZEOF(TPSM_Header)); - { *** test if this is a DSM-file } - IF NOT ((Header^.PSM_Sign[1] = 'P') AND (Header^.PSM_Sign[2] = 'S') AND - (Header^.PSM_Sign[3] = 'M') AND (Header^.PSM_Sign[4] = #254)) THEN - BEGIN - ErrorCode := c_NoValidFileFormat; - CLOSE(InFile); - EXIT; - END; - { *** read order } - SEEK(InFile,FilePosition + Header^.PSM_OrderPosition); - BLOCKREAD(InFile,Order^,Header^.PSM_OrderLength); - { *** read channelsettings } - SEEK(InFile,FilePosition + Header^.PSM_ChannelSettingPosition); - BLOCKREAD(InFile,ChannelSettings^,SIZEOF(TPSM_ChannelSettings)); - { *** read samplelist } - SEEK(InFile,FilePosition + Header^.PSM_SamplePosition); - BLOCKREAD(InFile,Sample^,Header^.PSM_SampleNumber * SIZEOF(TPSM_Sample)); - { *** copy header to intern NTMIK-structure } - Module^.Module_Sign := 'MF'; - Module^.Module_FileFormatVersion := $0100; - Module^.Module_SampleNumber := Header^.PSM_SampleNumber; - Module^.Module_PatternNumber := Header^.PSM_PatternNumber; - Module^.Module_OrderLength := Header^.PSM_OrderLength; - Module^.Module_ChannelNumber := Header^.PSM_ChannelNumber+1; - Module^.Module_Initial_GlobalVolume := 64; - Module^.Module_Initial_MasterVolume := $C0; - Module^.Module_Initial_Speed := Header^.PSM_Speed; - Module^.Module_Initial_Tempo := Header^.PSM_Tempo; -{ *** paragraph 01 start } - Module^.Module_Flags := c_Module_Flags_ZeroVolume * BYTE(1) + - c_Module_Flags_Stereo * BYTE(1) + - c_Module_Flags_ForceAmigaLimits * BYTE(0) + - c_Module_Flags_Panning * BYTE(1) + - c_Module_Flags_Surround * BYTE(1) + - c_Module_Flags_QualityMixing * BYTE(1) + - c_Module_Flags_FastVolumeSlides * BYTE(0) + - c_Module_Flags_SpecialCustomData * BYTE(0) + - c_Module_Flags_SongName * BYTE(1); - I1 := $01; - WHILE (Header^.PSM_SongName[I1] > #00) AND (I1 < c_Module_SongNameLength) DO - BEGIN - Module^.Module_Name[I1] := Header^.PSM_SongName[I1]; - INC(I1); - END; - Module^.Module_Name[c_Module_SongNameLength] := #00; - { *** Init channelsettings } - FOR I1 := 0 TO c_Maximum_ChannelIndex DO - BEGIN - IF I1 < Header^.PSM_ChannelUsed THEN - BEGIN - { *** channel enabled } - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_GlobalVolume := 64; - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Panning := (ChannelSettings^[I1]) * $08; - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Code := I1 + $10 * BYTE(ChannelSettings^[I1] > $08) + - c_ChannelSettings_Code_ChannelEnabled * BYTE(1) + - c_ChannelSettings_Code_ChannelDigital * BYTE(1); - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Controls := - c_ChannelSettings_Controls_EnhancedMode * BYTE(1) + - c_ChannelSettings_Controls_SurroundMode * BYTE(0); - END - ELSE - BEGIN - { *** channel disabled } - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_GlobalVolume := $00; - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Panning := $00; - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Code := $00; - Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Controls := $00; - END; - END; - { *** init and copy order } - FILLCHAR(Module^.Module_OrderPointer^,c_Maximum_OrderIndex+1,$FF); - MOVE(Order^,Module^.Module_OrderPointer^,Header^.PSM_OrderLength); - { *** read pattern } - SEEK(InFile,FilePosition + Header^.PSM_PatternPosition); - NTMIK_LoaderPatternNumber := Header^.PSM_PatternNumber-1; - FOR I1 := 0 TO Header^.PSM_PatternNumber-1 DO - BEGIN - NTMIK_LoadPatternProcedure; - { *** read length } - BLOCKREAD(InFile,TempW,2); - { *** read pattern } - BLOCKREAD(InFile,MultiPurposeBuffer^,TempW-2); - { *** unpack pattern and set notes per channel to 64 } - PSM_UnpackPattern(MultiPurposeBuffer^,PatternBuffer^,TempW); - NTMIK_PackPattern(MultiPurposeBuffer^,PatternBuffer^,PSM_NotesInPattern); - TempW := WORD(256) * MultiPurposeBuffer^[01] + MultiPurposeBuffer^[00]; - GETMEM(Module^.Module_PatternPointer^[I1],TempW); - MOVE(MultiPurposeBuffer^,Module^.Module_PatternPointer^[I1]^,TempW); - { *** next pattern } - END; - { *** read samples } - NTMIK_LoaderSampleNumber := Header^.PSM_SampleNumber; - FOR I1 := 1 TO Header^.PSM_SampleNumber DO - BEGIN - NTMIK_LoadSampleProcedure; - { *** get index for sample } - I3 := Sample^[I1].PSM_SampleNumber; - { *** clip PSM-sample } - IF Sample^[I1].PSM_SampleLoopEnd > Sample^[I1].PSM_SampleLength - THEN Sample^[I1].PSM_SampleLoopEnd := Sample^[I1].PSM_SampleLength; - { *** init intern sample } - NEW(Module^.Module_SamplePointer^[I3]); - FILLCHAR(Module^.Module_SamplePointer^[I3]^,SIZEOF(TSample),$00); - FILLCHAR(Module^.Module_SamplePointer^[I3]^.Sample_SampleName,c_Sample_SampleNameLength,#32); - FILLCHAR(Module^.Module_SamplePointer^[I3]^.Sample_FileName,c_Sample_FileNameLength,#32); - { *** copy informations to intern sample } - I2 := $01; - WHILE (Sample^[I1].PSM_SampleName[I2] > #00) AND (I2 < c_Sample_SampleNameLength) DO - BEGIN - Module^.Module_SamplePointer^[I3]^.Sample_SampleName[I2] := Sample^[I1].PSM_SampleName[I2]; - INC(I2); - END; - Module^.Module_SamplePointer^[I3]^.Sample_Sign := 'DF'; - Module^.Module_SamplePointer^[I3]^.Sample_FileFormatVersion := $00100; - Module^.Module_SamplePointer^[I3]^.Sample_Position := $00000000; - Module^.Module_SamplePointer^[I3]^.Sample_Selector := $0000; - Module^.Module_SamplePointer^[I3]^.Sample_Volume := Sample^[I1].PSM_SampleVolume; - Module^.Module_SamplePointer^[I3]^.Sample_LoopCounter := $00; - Module^.Module_SamplePointer^[I3]^.Sample_C5Speed := Sample^[I1].PSM_SampleC5Speed; - Module^.Module_SamplePointer^[I3]^.Sample_Length := Sample^[I1].PSM_SampleLength; - Module^.Module_SamplePointer^[I3]^.Sample_LoopBegin := Sample^[I1].PSM_SampleLoopBegin; - Module^.Module_SamplePointer^[I3]^.Sample_LoopEnd := Sample^[I1].PSM_SampleLoopEnd; - { *** now it's time for the flags } - Module^.Module_SamplePointer^[I3]^.Sample_Flags := - c_Sample_Flags_DigitalSample * BYTE(1) + - c_Sample_Flags_8BitSample * BYTE(1) + - c_Sample_Flags_UnsignedSampleData * BYTE(1) + - c_Sample_Flags_Packed * BYTE(0) + - c_Sample_Flags_LoopCounter * BYTE(0) + - c_Sample_Flags_SampleName * BYTE(1) + - c_Sample_Flags_LoopActive * - BYTE(Sample^[I1].PSM_SampleFlags AND (LONGINT(1) SHL 15) = (LONGINT(1) SHL 15)); - { *** alloc memory for sample-data } - E_Getmem(Module^.Module_SamplePointer^[I3]^.Sample_Selector, - Module^.Module_SamplePointer^[I3]^.Sample_Position, - Module^.Module_SamplePointer^[I3]^.Sample_Length + c_LoopExtensionSize); - { *** read out data } - EPT(TempP).p_Selector := Module^.Module_SamplePointer^[I3]^.Sample_Selector; - EPT(TempP).p_Offset := $0000; - SEEK(InFile,Sample^[I1].PSM_SamplePosition); - E_BLOCKREAD(InFile,TempP^,Module^.Module_SamplePointer^[I3]^.Sample_Length); - { *** 'coz the samples are signed in a DSM-file -> PC-fy them } - IF Module^.Module_SamplePointer^[I3]^.Sample_Length > 4 THEN - BEGIN - CopyLength := Module^.Module_SamplePointer^[I3]^.Sample_Length; - { *** decode sample } - ASM - DB 066h; MOV CX,WORD PTR CopyLength - { *** load sample selector } - MOV ES,WORD PTR TempP[00002h] - DB 066h; XOR SI,SI - DB 066h; XOR DI,DI - XOR AH,AH - { *** conert all bytes } - @@MainLoop: - DB 026h; DB 067h; LODSB - ADD AL,AH - MOV AH,AL - DB 067h; STOSB - DB 066h; LOOP @@MainLoop - END; - { *** make samples unsigned } - ASM - DB 066h; MOV CX,WORD PTR CopyLength - { *** load sample selector } - MOV ES,WORD PTR TempP[00002h] - DB 066h; XOR SI,SI - DB 066h; XOR DI,DI - { *** conert all bytes } - @@MainLoop: - DB 026h; DB 067h; LODSB - SUB AL,080h - DB 067h; STOSB - DB 066h; LOOP @@MainLoop - END; - { *** Create Loop-Extension } - IF Module^.Module_SamplePointer^[I3]^.Sample_Flags AND c_Sample_Flags_LoopActive = c_Sample_Flags_LoopActive THEN - BEGIN - CopySource := Module^.Module_SamplePointer^[I3]^.Sample_LoopBegin; - CopyDestination := Module^.Module_SamplePointer^[I3]^.Sample_LoopEnd; - CopyLength := CopyDestination - CopySource; - ASM - { *** load sample-selector } - MOV ES,WORD PTR TempP[00002h] - DB 066h; MOV DI,WORD PTR CopyDestination - { *** calculate number of full sample-loops to copy } - XOR DX,DX - MOV AX,c_LoopExtensionSize - MOV BX,WORD PTR CopyLength - DIV BX - OR AX,AX - JE @@NoFullLoop - { *** copy some full-loops (size=bx) } - MOV CX,AX - @@InnerLoop: - PUSH CX - DB 066h; MOV SI,WORD PTR CopySource - MOV CX,BX - DB 0F3h; DB 026h,067h,0A4h { REP MOVS BYTE PTR ES:[EDI],ES:[ESI] } - POP CX - LOOP @@InnerLoop - @@NoFullLoop: - { *** calculate number of rest-bytes to copy } - DB 066h; MOV SI,WORD PTR CopySource - MOV CX,DX - DB 0F3h; DB 026h,067h,0A4h { REP MOVS BYTE PTR ES:[EDI],ES:[ESI] } - END; - END - ELSE - BEGIN - CopyDestination := Module^.Module_SamplePointer^[I3]^.Sample_Length; - ASM - { *** load sample-selector } - MOV ES,WORD PTR TempP[00002h] - DB 066h; MOV DI,WORD PTR CopyDestination - { *** clear extension } - MOV CX,c_LoopExtensionSize - MOV AL,080h - DB 0F3h; DB 067h,0AAh { REP STOS BYTE PTR ES:[EDI] } - END; - END; - END; - { *** next sample } - END; - { *** init period-ranges } - NTMIK_MaximumPeriod := $0000D600 SHR 1; - NTMIK_MinimumPeriod := $0000D600 SHR 8; - { *** close file } - CLOSE(InFile); - { *** dispose all dynamic variables } - DISPOSE(Header); - DISPOSE(Sample); - DISPOSE(Order); - DISPOSE(ChannelSettings); - DISPOSE(MultiPurposeBuffer); - DISPOSE(PatternBuffer); - { *** set errorcode to noerror } - ErrorCode := c_NoError; - END; - -*/ - diff --git a/jni/load_ptm.cpp b/jni/load_ptm.cpp deleted file mode 100644 index ebdeee7..0000000 --- a/jni/load_ptm.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque , - * Adam Goode (endian and char fixes for PPC) -*/ - -////////////////////////////////////////////// -// PTM PolyTracker module loader // -////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#pragma pack(1) - -typedef struct PTMFILEHEADER -{ - CHAR songname[28]; // name of song, asciiz string - CHAR eof; // 26 - BYTE version_lo; // 03 version of file, currently 0203h - BYTE version_hi; // 02 - BYTE reserved1; // reserved, set to 0 - WORD norders; // number of orders (0..256) - WORD nsamples; // number of instruments (1..255) - WORD npatterns; // number of patterns (1..128) - WORD nchannels; // number of channels (voices) used (1..32) - WORD fileflags; // set to 0 - WORD reserved2; // reserved, set to 0 - DWORD ptmf_id; // song identification, 'PTMF' or 0x464d5450 - BYTE reserved3[16]; // reserved, set to 0 - BYTE chnpan[32]; // channel panning settings, 0..15, 0 = left, 7 = middle, 15 = right - BYTE orders[256]; // order list, valid entries 0..nOrders-1 - WORD patseg[128]; // pattern offsets (*16) -} PTMFILEHEADER, *LPPTMFILEHEADER; - -#define SIZEOF_PTMFILEHEADER 608 - - -typedef struct PTMSAMPLE -{ - BYTE sampletype; // sample type (bit array) - CHAR filename[12]; // name of external sample file - BYTE volume; // default volume - WORD nC4Spd; // C4 speed - WORD sampleseg; // sample segment (used internally) - WORD fileofs[2]; // offset of sample data - WORD length[2]; // sample size (in bytes) - WORD loopbeg[2]; // start of loop - WORD loopend[2]; // end of loop - WORD gusdata[8]; - char samplename[28]; // name of sample, asciiz // changed from CHAR - DWORD ptms_id; // sample identification, 'PTMS' or 0x534d5450 -} PTMSAMPLE; - -#define SIZEOF_PTMSAMPLE 80 - -#pragma pack() - - -static uint32_t BS2WORD(uint16_t w[2]) { - uint32_t u32 = (w[1] << 16) + w[0]; - return(bswapLE32(u32)); -} - -BOOL CSoundFile::ReadPTM(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - DWORD dwMemPos; - UINT nOrders; - - if ((!lpStream) || (dwMemLength < sizeof(PTMFILEHEADER))) return FALSE; - PTMFILEHEADER pfh = *(LPPTMFILEHEADER)lpStream; - - pfh.norders = bswapLE16(pfh.norders); - pfh.nsamples = bswapLE16(pfh.nsamples); - pfh.npatterns = bswapLE16(pfh.npatterns); - pfh.nchannels = bswapLE16(pfh.nchannels); - pfh.fileflags = bswapLE16(pfh.fileflags); - pfh.reserved2 = bswapLE16(pfh.reserved2); - pfh.ptmf_id = bswapLE32(pfh.ptmf_id); - for (UINT j=0; j<128; j++) - { - pfh.patseg[j] = bswapLE16(pfh.patseg[j]); - } - - if ((pfh.ptmf_id != 0x464d5450) || (!pfh.nchannels) - || (pfh.nchannels > 32) - || (pfh.norders > 256) || (!pfh.norders) - || (!pfh.nsamples) || (pfh.nsamples > 255) - || (!pfh.npatterns) || (pfh.npatterns > 128) - || (SIZEOF_PTMFILEHEADER+pfh.nsamples*SIZEOF_PTMSAMPLE >= (int)dwMemLength)) return FALSE; - memcpy(m_szNames[0], pfh.songname, 28); - m_szNames[0][28] = 0; - m_nType = MOD_TYPE_PTM; - m_nChannels = pfh.nchannels; - m_nSamples = (pfh.nsamples < MAX_SAMPLES) ? pfh.nsamples : MAX_SAMPLES-1; - dwMemPos = SIZEOF_PTMFILEHEADER; - nOrders = (pfh.norders < MAX_ORDERS) ? pfh.norders : MAX_ORDERS-1; - memcpy(Order, pfh.orders, nOrders); - for (UINT ipan=0; ipansamplename, 28); - memcpy(pins->name, psmp->filename, 12); - pins->name[12] = 0; - pins->nGlobalVol = 64; - pins->nPan = 128; - pins->nVolume = psmp->volume << 2; - pins->nC4Speed = bswapLE16(psmp->nC4Spd) << 1; - pins->uFlags = 0; - if ((psmp->sampletype & 3) == 1) - { - UINT smpflg = RS_PCM8D; - pins->nLength = BS2WORD(psmp->length); - pins->nLoopStart = BS2WORD(psmp->loopbeg); - pins->nLoopEnd = BS2WORD(psmp->loopend); - DWORD samplepos = BS2WORD(psmp->fileofs); - if (psmp->sampletype & 4) pins->uFlags |= CHN_LOOP; - if (psmp->sampletype & 8) pins->uFlags |= CHN_PINGPONGLOOP; - if (psmp->sampletype & 16) - { - pins->uFlags |= CHN_16BIT; - pins->nLength >>= 1; - pins->nLoopStart >>= 1; - pins->nLoopEnd >>= 1; - smpflg = RS_PTM8DTO16; - } - if ((pins->nLength) && (samplepos) && (samplepos < dwMemLength)) - { - ReadSample(pins, smpflg, (LPSTR)(lpStream+samplepos), dwMemLength-samplepos); - } - } - } - // Reading Patterns - for (UINT ipat=0; ipat= dwMemLength)) continue; - PatternSize[ipat] = 64; - if ((Patterns[ipat] = AllocatePattern(64, m_nChannels)) == NULL) break; - // - MODCOMMAND *m = Patterns[ipat]; - for (UINT row=0; ((row < 64) && (dwMemPos < dwMemLength)); ) - { - UINT b = lpStream[dwMemPos++]; - - if (dwMemPos >= dwMemLength) break; - if (b) - { - UINT nChn = b & 0x1F; - - if (b & 0x20) - { - if (dwMemPos + 2 > dwMemLength) break; - m[nChn].note = lpStream[dwMemPos++]; - m[nChn].instr = lpStream[dwMemPos++]; - } - if (b & 0x40) - { - if (dwMemPos + 2 > dwMemLength) break; - m[nChn].command = lpStream[dwMemPos++]; - m[nChn].param = lpStream[dwMemPos++]; - if ((m[nChn].command == 0x0E) && ((m[nChn].param & 0xF0) == 0x80)) - { - m[nChn].command = CMD_S3MCMDEX; - } else - if (m[nChn].command < 0x10) - { - ConvertModCommand(&m[nChn]); - } else - { - switch(m[nChn].command) - { - case 16: - m[nChn].command = CMD_GLOBALVOLUME; - break; - case 17: - m[nChn].command = CMD_RETRIG; - break; - case 18: - m[nChn].command = CMD_FINEVIBRATO; - break; - default: - m[nChn].command = 0; - } - } - } - if (b & 0x80) - { - if (dwMemPos >= dwMemLength) break; - m[nChn].volcmd = VOLCMD_VOLUME; - m[nChn].vol = lpStream[dwMemPos++]; - } - } else - { - row++; - m += m_nChannels; - } - } - } - return TRUE; -} - diff --git a/jni/load_s3m.cpp b/jni/load_s3m.cpp deleted file mode 100644 index 8678236..0000000 --- a/jni/load_s3m.cpp +++ /dev/null @@ -1,666 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque , - * Adam Goode (endian and char fixes for PPC) -*/ - -#include "stdafx.h" -#include "sndfile.h" -#include "tables.h" - -#ifdef _MSC_VER -//#pragma warning(disable:4244) -#endif - -////////////////////////////////////////////////////// -// ScreamTracker S3M file support - -#pragma pack(1) -typedef struct tagS3MSAMPLESTRUCT -{ - BYTE type; - CHAR dosname[12]; - BYTE hmem; - WORD memseg; - DWORD length; - DWORD loopbegin; - DWORD loopend; - BYTE vol; - BYTE bReserved; - BYTE pack; - BYTE flags; - DWORD finetune; - DWORD dwReserved; - WORD intgp; - WORD int512; - DWORD lastused; - CHAR name[28]; - CHAR scrs[4]; -} S3MSAMPLESTRUCT; - - -typedef struct tagS3MFILEHEADER -{ - CHAR name[28]; - BYTE b1A; - BYTE type; - WORD reserved1; - WORD ordnum; - WORD insnum; - WORD patnum; - WORD flags; - WORD cwtv; - WORD version; - DWORD scrm; // "SCRM" = 0x4D524353 - BYTE globalvol; - BYTE speed; - BYTE tempo; - BYTE mastervol; - BYTE ultraclicks; - BYTE panning_present; - BYTE reserved2[8]; - WORD special; - BYTE channels[32]; -} S3MFILEHEADER; - - -void CSoundFile::S3MConvert(MODCOMMAND *m, BOOL bIT) const -//-------------------------------------------------------- -{ - UINT command = m->command; - UINT param = m->param; - switch (command + 0x40) - { - case 'A': command = CMD_SPEED; break; - case 'B': command = CMD_POSITIONJUMP; break; - case 'C': command = CMD_PATTERNBREAK; if (!bIT) param = (param >> 4) * 10 + (param & 0x0F); break; - case 'D': command = CMD_VOLUMESLIDE; break; - case 'E': command = CMD_PORTAMENTODOWN; break; - case 'F': command = CMD_PORTAMENTOUP; break; - case 'G': command = CMD_TONEPORTAMENTO; break; - case 'H': command = CMD_VIBRATO; break; - case 'I': command = CMD_TREMOR; break; - case 'J': command = CMD_ARPEGGIO; break; - case 'K': command = CMD_VIBRATOVOL; break; - case 'L': command = CMD_TONEPORTAVOL; break; - case 'M': command = CMD_CHANNELVOLUME; break; - case 'N': command = CMD_CHANNELVOLSLIDE; break; - case 'O': command = CMD_OFFSET; break; - case 'P': command = CMD_PANNINGSLIDE; break; - case 'Q': command = CMD_RETRIG; break; - case 'R': command = CMD_TREMOLO; break; - case 'S': command = CMD_S3MCMDEX; break; - case 'T': command = CMD_TEMPO; break; - case 'U': command = CMD_FINEVIBRATO; break; - case 'V': command = CMD_GLOBALVOLUME; break; - case 'W': command = CMD_GLOBALVOLSLIDE; break; - case 'X': command = CMD_PANNING8; break; - case 'Y': command = CMD_PANBRELLO; break; - case 'Z': command = CMD_MIDI; break; - default: command = 0; - } - m->command = command; - m->param = param; -} - - -void CSoundFile::S3MSaveConvert(UINT *pcmd, UINT *pprm, BOOL bIT) const -//--------------------------------------------------------------------- -{ - UINT command = *pcmd; - UINT param = *pprm; - switch(command) - { - case CMD_SPEED: command = 'A'; break; - case CMD_POSITIONJUMP: command = 'B'; break; - case CMD_PATTERNBREAK: command = 'C'; if (!bIT) param = ((param / 10) << 4) + (param % 10); break; - case CMD_VOLUMESLIDE: command = 'D'; break; - case CMD_PORTAMENTODOWN: command = 'E'; if ((param >= 0xE0) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM))) param = 0xDF; break; - case CMD_PORTAMENTOUP: command = 'F'; if ((param >= 0xE0) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM))) param = 0xDF; break; - case CMD_TONEPORTAMENTO: command = 'G'; break; - case CMD_VIBRATO: command = 'H'; break; - case CMD_TREMOR: command = 'I'; break; - case CMD_ARPEGGIO: command = 'J'; break; - case CMD_VIBRATOVOL: command = 'K'; break; - case CMD_TONEPORTAVOL: command = 'L'; break; - case CMD_CHANNELVOLUME: command = 'M'; break; - case CMD_CHANNELVOLSLIDE: command = 'N'; break; - case CMD_OFFSET: command = 'O'; break; - case CMD_PANNINGSLIDE: command = 'P'; break; - case CMD_RETRIG: command = 'Q'; break; - case CMD_TREMOLO: command = 'R'; break; - case CMD_S3MCMDEX: command = 'S'; break; - case CMD_TEMPO: command = 'T'; break; - case CMD_FINEVIBRATO: command = 'U'; break; - case CMD_GLOBALVOLUME: command = 'V'; break; - case CMD_GLOBALVOLSLIDE: command = 'W'; break; - case CMD_PANNING8: - command = 'X'; - if ((bIT) && (m_nType != MOD_TYPE_IT) && (m_nType != MOD_TYPE_XM)) - { - if (param == 0xA4) { command = 'S'; param = 0x91; } else - if (param <= 0x80) { param <<= 1; if (param > 255) param = 255; } else - command = param = 0; - } else - if ((!bIT) && ((m_nType == MOD_TYPE_IT) || (m_nType == MOD_TYPE_XM))) - { - param >>= 1; - } - break; - case CMD_PANBRELLO: command = 'Y'; break; - case CMD_MIDI: command = 'Z'; break; - case CMD_XFINEPORTAUPDOWN: - if (param & 0x0F) switch(param & 0xF0) - { - case 0x10: command = 'F'; param = (param & 0x0F) | 0xE0; break; - case 0x20: command = 'E'; param = (param & 0x0F) | 0xE0; break; - case 0x90: command = 'S'; break; - default: command = param = 0; - } else command = param = 0; - break; - case CMD_MODCMDEX: - command = 'S'; - switch(param & 0xF0) - { - case 0x00: command = param = 0; break; - case 0x10: command = 'F'; param |= 0xF0; break; - case 0x20: command = 'E'; param |= 0xF0; break; - case 0x30: param = (param & 0x0F) | 0x10; break; - case 0x40: param = (param & 0x0F) | 0x30; break; - case 0x50: param = (param & 0x0F) | 0x20; break; - case 0x60: param = (param & 0x0F) | 0xB0; break; - case 0x70: param = (param & 0x0F) | 0x40; break; - case 0x90: command = 'Q'; param &= 0x0F; break; - case 0xA0: if (param & 0x0F) { command = 'D'; param = (param << 4) | 0x0F; } else command=param=0; break; - case 0xB0: if (param & 0x0F) { command = 'D'; param |= 0xF0; } else command=param=0; break; - } - break; - default: command = param = 0; - } - command &= ~0x40; - *pcmd = command; - *pprm = param; -} - -static DWORD boundInput(DWORD input, DWORD smin, DWORD smax) -{ - if (input > smax) input = smax; - else if (input < smin) input = 0; - return(input); -} - - -BOOL CSoundFile::ReadS3M(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - UINT insnum,patnum,nins,npat; - DWORD insfile[MAX_SAMPLES]; - WORD ptr[256]; - DWORD dwMemPos; - BYTE insflags[MAX_SAMPLES], inspack[MAX_SAMPLES]; - - if ((!lpStream) || (dwMemLength <= sizeof(S3MFILEHEADER)+sizeof(S3MSAMPLESTRUCT)+64)) return FALSE; - S3MFILEHEADER psfh = *(S3MFILEHEADER *)lpStream; - - psfh.reserved1 = bswapLE16(psfh.reserved1); - psfh.ordnum = bswapLE16(psfh.ordnum); - psfh.insnum = bswapLE16(psfh.insnum); - psfh.patnum = bswapLE16(psfh.patnum); - psfh.flags = bswapLE16(psfh.flags); - psfh.cwtv = bswapLE16(psfh.cwtv); - psfh.version = bswapLE16(psfh.version); - psfh.scrm = bswapLE32(psfh.scrm); - psfh.special = bswapLE16(psfh.special); - - if (psfh.scrm != 0x4D524353) return FALSE; - dwMemPos = 0x60; - m_nType = MOD_TYPE_S3M; - memset(m_szNames,0,sizeof(m_szNames)); - memcpy(m_szNames[0], psfh.name, 28); - // Speed - m_nDefaultSpeed = psfh.speed; - if (m_nDefaultSpeed < 1) m_nDefaultSpeed = 6; - if (m_nDefaultSpeed > 0x1F) m_nDefaultSpeed = 0x1F; - // Tempo - m_nDefaultTempo = psfh.tempo; - if (m_nDefaultTempo < 40) m_nDefaultTempo = 40; - if (m_nDefaultTempo > 240) m_nDefaultTempo = 240; - // Global Volume - m_nDefaultGlobalVolume = psfh.globalvol << 2; - if ((!m_nDefaultGlobalVolume) || (m_nDefaultGlobalVolume > 256)) m_nDefaultGlobalVolume = 256; - m_nSongPreAmp = psfh.mastervol & 0x7F; - // Channels - m_nChannels = 4; - for (UINT ich=0; ich<32; ich++) - { - ChnSettings[ich].nPan = 128; - ChnSettings[ich].nVolume = 64; - - ChnSettings[ich].dwFlags = CHN_MUTE; - if (psfh.channels[ich] != 0xFF) - { - m_nChannels = ich+1; - UINT b = psfh.channels[ich] & 0x0F; - ChnSettings[ich].nPan = (b & 8) ? 0xC0 : 0x40; - ChnSettings[ich].dwFlags = 0; - } - } - if (m_nChannels < 4) m_nChannels = 4; - if ((psfh.cwtv < 0x1320) || (psfh.flags & 0x40)) m_dwSongFlags |= SONG_FASTVOLSLIDES; - // Reading pattern order - UINT iord = psfh.ordnum; - if (iord<1) iord = 1; - if (iord > MAX_ORDERS) iord = MAX_ORDERS; - if (iord) - { - memcpy(Order, lpStream+dwMemPos, iord); - dwMemPos += iord; - } - if ((iord & 1) && (lpStream[dwMemPos] == 0xFF)) dwMemPos++; - // Reading file pointers - insnum = nins = psfh.insnum; - if (insnum >= MAX_SAMPLES) insnum = MAX_SAMPLES-1; - m_nSamples = insnum; - patnum = npat = psfh.patnum; - if (patnum > MAX_PATTERNS) patnum = MAX_PATTERNS; - memset(ptr, 0, sizeof(ptr)); - - // Ignore file if it has a corrupted header. - if (nins+npat > 256) return FALSE; - - if (nins+npat) - { - memcpy(ptr, lpStream+dwMemPos, 2*(nins+npat)); - dwMemPos += 2*(nins+npat); - for (UINT j = 0; j < (nins+npat); ++j) { - ptr[j] = bswapLE16(ptr[j]); - } - if (psfh.panning_present == 252) - { - const BYTE *chnpan = lpStream+dwMemPos; - for (UINT i=0; i<32; i++) if (chnpan[i] & 0x20) - { - ChnSettings[i].nPan = ((chnpan[i] & 0x0F) << 4) + 8; - } - } - } - if (!m_nChannels) return TRUE; - // Reading instrument headers - memset(insfile, 0, sizeof(insfile)); - for (UINT iSmp=1; iSmp<=insnum; iSmp++) - { - UINT nInd = ((DWORD)ptr[iSmp-1])*16; - if ((!nInd) || (nInd + 0x50 > dwMemLength)) continue; - S3MSAMPLESTRUCT pSmp; - memcpy(&pSmp, lpStream+nInd, 0x50); - memcpy(Ins[iSmp].name, &pSmp.dosname, 12); - insflags[iSmp-1] = pSmp.flags; - inspack[iSmp-1] = pSmp.pack; - memcpy(m_szNames[iSmp], pSmp.name, 28); - m_szNames[iSmp][28] = 0; - if ((pSmp.type==1) && (pSmp.scrs[2]=='R') && (pSmp.scrs[3]=='S')) - { - Ins[iSmp].nLength = boundInput(bswapLE32(pSmp.length), 4, MAX_SAMPLE_LENGTH); - Ins[iSmp].nLoopStart = boundInput(bswapLE32(pSmp.loopbegin), 4, Ins[iSmp].nLength - 1); - Ins[iSmp].nLoopEnd = boundInput(bswapLE32(pSmp.loopend), 4, Ins[iSmp].nLength); - Ins[iSmp].nVolume = boundInput(pSmp.vol, 0, 64) << 2; - Ins[iSmp].nGlobalVol = 64; - if (pSmp.flags&1) Ins[iSmp].uFlags |= CHN_LOOP; - UINT j = bswapLE32(pSmp.finetune); - if (!j) j = 8363; - if (j < 1024) j = 1024; - Ins[iSmp].nC4Speed = j; - insfile[iSmp] = (pSmp.hmem << 20) + (bswapLE16(pSmp.memseg) << 4); - // offset is invalid - ignore this sample. - if (insfile[iSmp] > dwMemLength) insfile[iSmp] = 0; - else if (insfile[iSmp]) { - // ignore duplicate samples. - for (int z=iSmp-1; z>=0; z--) - if (insfile[iSmp] == insfile[z]) - insfile[iSmp] = 0; - } - if ((Ins[iSmp].nLoopStart >= Ins[iSmp].nLoopEnd) || (Ins[iSmp].nLoopEnd - Ins[iSmp].nLoopStart < 8)) - Ins[iSmp].nLoopStart = Ins[iSmp].nLoopEnd = 0; - Ins[iSmp].nPan = 0x80; - } - } - // Reading patterns - for (UINT iPat=0; iPat dwMemLength) continue; - WORD len = bswapLE16(*((WORD *)(lpStream+nInd))); - nInd += 2; - PatternSize[iPat] = 64; - if ((!len) || (nInd + len > dwMemLength - 6) - || ((Patterns[iPat] = AllocatePattern(64, m_nChannels)) == NULL)) continue; - LPBYTE src = (LPBYTE)(lpStream+nInd); - // Unpacking pattern - MODCOMMAND *p = Patterns[iPat]; - UINT row = 0; - UINT j = 0; - while (j < len) - { - BYTE b = src[j++]; - if (!b) - { - if (++row >= 64) break; - } else - { - UINT chn = b & 0x1F; - if (chn < m_nChannels) - { - MODCOMMAND *m = &p[row*m_nChannels+chn]; - if (b & 0x20) - { - m->note = src[j++]; - if (m->note < 0xF0) m->note = (m->note & 0x0F) + 12*(m->note >> 4) + 13; - else if (m->note == 0xFF) m->note = 0; - m->instr = src[j++]; - } - if (b & 0x40) - { - UINT vol = src[j++]; - if ((vol >= 128) && (vol <= 192)) - { - vol -= 128; - m->volcmd = VOLCMD_PANNING; - } else - { - if (vol > 64) vol = 64; - m->volcmd = VOLCMD_VOLUME; - } - m->vol = vol; - } - if (b & 0x80) - { - m->command = src[j++]; - m->param = src[j++]; - if (m->command) S3MConvert(m, FALSE); - } - } else - { - if (b & 0x20) j += 2; - if (b & 0x40) j++; - if (b & 0x80) j += 2; - } - if (j >= len) break; - } - } - } - // Reading samples - for (UINT iRaw=1; iRaw<=insnum; iRaw++) if ((Ins[iRaw].nLength) && (insfile[iRaw])) - { - UINT flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U; - if (insflags[iRaw-1] & 4) flags += 5; - if (insflags[iRaw-1] & 2) flags |= RSF_STEREO; - if (inspack[iRaw-1] == 4) flags = RS_ADPCM4; - dwMemPos = insfile[iRaw]; - if (dwMemPos < dwMemLength) - dwMemPos += ReadSample(&Ins[iRaw], flags, (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos); - } - m_nMinPeriod = 64; - m_nMaxPeriod = 32767; - if (psfh.flags & 0x10) m_dwSongFlags |= SONG_AMIGALIMITS; - return TRUE; -} - - -#ifndef MODPLUG_NO_FILESAVE - -#ifdef _MSC_VER -#pragma warning(disable:4100) -#endif - -static BYTE S3MFiller[16] = -{ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 -}; - - -BOOL CSoundFile::SaveS3M(LPCSTR lpszFileName, UINT nPacking) -//---------------------------------------------------------- -{ - FILE *f; - BYTE header[0x60]; - UINT nbo,nbi,nbp,i; - WORD patptr[128]; - WORD insptr[128]; - BYTE buffer[5*1024]; - S3MSAMPLESTRUCT insex[128]; - - if ((!m_nChannels) || (!lpszFileName)) return FALSE; - if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE; - // Writing S3M header - memset(header, 0, sizeof(header)); - memset(insex, 0, sizeof(insex)); - memcpy(header, m_szNames[0], 0x1C); - header[0x1B] = 0; - header[0x1C] = 0x1A; - header[0x1D] = 0x10; - nbo = (GetNumPatterns() + 15) & 0xF0; - if (!nbo) nbo = 16; - header[0x20] = nbo & 0xFF; - header[0x21] = nbo >> 8; - nbi = m_nInstruments; - if (!nbi) nbi = m_nSamples; - if (nbi > 99) nbi = 99; - header[0x22] = nbi & 0xFF; - header[0x23] = nbi >> 8; - nbp = 0; - for (i=0; Patterns[i]; i++) { nbp = i+1; if (nbp >= MAX_PATTERNS) break; } - for (i=0; i= nbp)) nbp = Order[i] + 1; - header[0x24] = nbp & 0xFF; - header[0x25] = nbp >> 8; - if (m_dwSongFlags & SONG_FASTVOLSLIDES) header[0x26] |= 0x40; - if ((m_nMaxPeriod < 20000) || (m_dwSongFlags & SONG_AMIGALIMITS)) header[0x26] |= 0x10; - header[0x28] = 0x20; - header[0x29] = 0x13; - header[0x2A] = 0x02; // Version = 1 => Signed samples - header[0x2B] = 0x00; - header[0x2C] = 'S'; - header[0x2D] = 'C'; - header[0x2E] = 'R'; - header[0x2F] = 'M'; - header[0x30] = m_nDefaultGlobalVolume >> 2; - header[0x31] = m_nDefaultSpeed; - header[0x32] = m_nDefaultTempo; - header[0x33] = ((m_nSongPreAmp < 0x20) ? 0x20 : m_nSongPreAmp) | 0x80; // Stereo - header[0x35] = 0xFC; - for (i=0; i<32; i++) - { - if (i < m_nChannels) - { - UINT tmp = (i & 0x0F) >> 1; - header[0x40+i] = (i & 0x10) | ((i & 1) ? 8+tmp : tmp); - } else header[0x40+i] = 0xFF; - } - fwrite(header, 0x60, 1, f); - fwrite(Order, nbo, 1, f); - memset(patptr, 0, sizeof(patptr)); - memset(insptr, 0, sizeof(insptr)); - UINT ofs0 = 0x60 + nbo; - UINT ofs1 = ((0x60 + nbo + nbi*2 + nbp*2 + 15) & 0xFFF0) + 0x20; - UINT ofs = ofs1; - - for (i=0; i> 4); - } - fwrite(chnpan, 0x20, 1, f); - } - if ((nbi*2+nbp*2) & 0x0F) - { - fwrite(S3MFiller, 0x10 - ((nbi*2+nbp*2) & 0x0F), 1, f); - } - ofs1 = ftell(f); - fwrite(insex, nbi, 0x50, f); - // Packing patterns - ofs += nbi*0x50; - for (i=0; inote; - UINT volcmd = m->volcmd; - UINT vol = m->vol; - UINT command = m->command; - UINT param = m->param; - - if ((note) || (m->instr)) b |= 0x20; - if (!note) note = 0xFF; else - if (note >= 0xFE) note = 0xFE; else - if (note < 13) note = 0; else note -= 13; - if (note < 0xFE) note = (note % 12) + ((note / 12) << 4); - if (command == CMD_VOLUME) - { - command = 0; - if (param > 64) param = 64; - volcmd = VOLCMD_VOLUME; - vol = param; - } - if (volcmd == VOLCMD_VOLUME) b |= 0x40; else - if (volcmd == VOLCMD_PANNING) { vol |= 0x80; b |= 0x40; } - if (command) - { - S3MSaveConvert(&command, ¶m, FALSE); - if (command) b |= 0x80; - } - if (b & 0xE0) - { - buffer[len++] = b; - if (b & 0x20) - { - buffer[len++] = note; - buffer[len++] = m->instr; - } - if (b & 0x40) - { - buffer[len++] = vol; - } - if (b & 0x80) - { - buffer[len++] = command; - buffer[len++] = param; - } - if (len > sizeof(buffer) - 20) break; - } - } - buffer[len++] = 0; - if (len > sizeof(buffer) - 20) break; - } - } - buffer[0] = (len - 2) & 0xFF; - buffer[1] = (len - 2) >> 8; - len = (len+15) & (~0x0F); - fwrite(buffer, len, 1, f); - ofs += len; - } - // Writing samples - for (i=1; i<=nbi; i++) - { - MODINSTRUMENT *pins = &Ins[i]; - if (m_nInstruments) - { - pins = Ins; - if (Headers[i]) - { - for (UINT j=0; j<128; j++) - { - UINT n = Headers[i]->Keyboard[j]; - if ((n) && (n < MAX_INSTRUMENTS)) - { - pins = &Ins[n]; - break; - } - } - } - } - memcpy(insex[i-1].dosname, pins->name, 12); - memcpy(insex[i-1].name, m_szNames[i], 28); - memcpy(insex[i-1].scrs, "SCRS", 4); - insex[i-1].hmem = (BYTE)((DWORD)ofs >> 20); - insex[i-1].memseg = (WORD)((DWORD)ofs >> 4); - if (pins->pSample) - { - insex[i-1].type = 1; - insex[i-1].length = pins->nLength; - insex[i-1].loopbegin = pins->nLoopStart; - insex[i-1].loopend = pins->nLoopEnd; - insex[i-1].vol = pins->nVolume / 4; - insex[i-1].flags = (pins->uFlags & CHN_LOOP) ? 1 : 0; - if (pins->nC4Speed) - insex[i-1].finetune = pins->nC4Speed; - else - insex[i-1].finetune = TransposeToFrequency(pins->RelativeTone, pins->nFineTune); - UINT flags = RS_PCM8U; -#ifndef NO_PACKING - if (nPacking) - { - if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample((char *)pins->pSample, pins->nLength, nPacking))) - { - insex[i-1].pack = 4; - flags = RS_ADPCM4; - } - } else -#endif // NO_PACKING - { - if (pins->uFlags & CHN_16BIT) - { - insex[i-1].flags |= 4; - flags = RS_PCM16U; - } - if (pins->uFlags & CHN_STEREO) - { - insex[i-1].flags |= 2; - flags = (pins->uFlags & CHN_16BIT) ? RS_STPCM16U : RS_STPCM8U; - } - } - DWORD len = WriteSample(f, pins, flags); - if (len & 0x0F) - { - fwrite(S3MFiller, 0x10 - (len & 0x0F), 1, f); - } - ofs += (len + 15) & (~0x0F); - } else - { - insex[i-1].length = 0; - } - } - // Updating parapointers - fseek(f, ofs0, SEEK_SET); - fwrite(insptr, nbi, 2, f); - fwrite(patptr, nbp, 2, f); - fseek(f, ofs1, SEEK_SET); - fwrite(insex, 0x50, nbi, f); - fclose(f); - return TRUE; -} - -#ifdef _MSC_VER -#pragma warning(default:4100) -#endif - -#endif // MODPLUG_NO_FILESAVE - diff --git a/jni/load_stm.cpp b/jni/load_stm.cpp deleted file mode 100644 index 1e84c80..0000000 --- a/jni/load_stm.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#pragma pack(1) - -typedef struct tagSTMNOTE -{ - BYTE note; - BYTE insvol; - BYTE volcmd; - BYTE cmdinf; -} STMNOTE; - - -// Raw STM sampleinfo struct: -typedef struct tagSTMSAMPLE -{ - CHAR filename[14]; // Can't have long comments - just filename comments :) - WORD reserved; // ISA in memory when in ST 2 - WORD length; // Sample length - WORD loopbeg; // Loop start point - WORD loopend; // Loop end point - BYTE volume; // Volume - BYTE reserved2; // More reserved crap - WORD c2spd; // Good old c2spd - BYTE reserved3[6]; // Yet more of PSi's reserved crap -} STMSAMPLE; - - -// Raw STM header struct: -typedef struct tagSTMHEADER -{ - char songname[20]; // changed from CHAR - char trackername[8]; // !SCREAM! for ST 2.xx // changed from CHAR - CHAR unused; // 0x1A - CHAR filetype; // 1=song, 2=module (only 2 is supported, of course) :) - CHAR ver_major; // Like 2 - CHAR ver_minor; // "ditto" - BYTE inittempo; // initspeed= stm inittempo>>4 - BYTE numpat; // number of patterns - BYTE globalvol; // <- WoW! a RiGHT TRiANGLE =8*) - BYTE reserved[13]; // More of PSi's internal crap - STMSAMPLE sample[31]; // STM sample data - BYTE patorder[128]; // Docs say 64 - actually 128 -} STMHEADER; - -#pragma pack() - - - -BOOL CSoundFile::ReadSTM(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - const STMHEADER *phdr = (STMHEADER *)lpStream; - DWORD dwMemPos = 0; - - if ((!lpStream) || (dwMemLength < sizeof(STMHEADER))) return FALSE; - if ((phdr->filetype != 2) || (phdr->unused != 0x1A) - || ((strnicmp(phdr->trackername, "!SCREAM!", 8)) - && (strnicmp(phdr->trackername, "BMOD2STM", 8)))) return FALSE; - memcpy(m_szNames[0], phdr->songname, 20); - // Read STM header - m_nType = MOD_TYPE_STM; - m_nSamples = 31; - m_nChannels = 4; - m_nInstruments = 0; - m_nMinPeriod = 64; - m_nMaxPeriod = 0x7FFF; - m_nDefaultSpeed = phdr->inittempo >> 4; - if (m_nDefaultSpeed < 1) m_nDefaultSpeed = 1; - m_nDefaultTempo = 125; - m_nDefaultGlobalVolume = phdr->globalvol << 2; - if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256; - memcpy(Order, phdr->patorder, 128); - // Setting up channels - for (UINT nSet=0; nSet<4; nSet++) - { - ChnSettings[nSet].dwFlags = 0; - ChnSettings[nSet].nVolume = 64; - ChnSettings[nSet].nPan = (nSet & 1) ? 0x40 : 0xC0; - } - // Reading samples - for (UINT nIns=0; nIns<31; nIns++) - { - MODINSTRUMENT *pIns = &Ins[nIns+1]; - const STMSAMPLE *pStm = &phdr->sample[nIns]; // STM sample data - memcpy(pIns->name, pStm->filename, 13); - memcpy(m_szNames[nIns+1], pStm->filename, 12); - pIns->nC4Speed = bswapLE16(pStm->c2spd); - pIns->nGlobalVol = 64; - pIns->nVolume = pStm->volume << 2; - if (pIns->nVolume > 256) pIns->nVolume = 256; - pIns->nLength = bswapLE16(pStm->length); - if ((pIns->nLength < 4) || (!pIns->nVolume)) pIns->nLength = 0; - pIns->nLoopStart = bswapLE16(pStm->loopbeg); - pIns->nLoopEnd = bswapLE16(pStm->loopend); - if ((pIns->nLoopEnd > pIns->nLoopStart) && (pIns->nLoopEnd != 0xFFFF)) pIns->uFlags |= CHN_LOOP; - } - dwMemPos = sizeof(STMHEADER); - for (UINT nOrd=0; nOrd= 99) Order[nOrd] = 0xFF; - UINT nPatterns = phdr->numpat; - for (UINT nPat=0; nPat dwMemLength) return TRUE; - PatternSize[nPat] = 64; - if ((Patterns[nPat] = AllocatePattern(64, m_nChannels)) == NULL) return TRUE; - MODCOMMAND *m = Patterns[nPat]; - const STMNOTE *p = (const STMNOTE *)(lpStream + dwMemPos); - for (UINT n=0; n<64*4; n++, p++, m++) - { - UINT note,ins,vol,cmd; - // extract the various information from the 4 bytes that - // make up a single note - note = p->note; - ins = p->insvol >> 3; - vol = (p->insvol & 0x07) + (p->volcmd >> 1); - cmd = p->volcmd & 0x0F; - if ((ins) && (ins < 32)) m->instr = ins; - // special values of [SBYTE0] are handled here -> - // we have no idea if these strange values will ever be encountered - // but it appears as though stms sound correct. - if ((note == 0xFE) || (note == 0xFC)) m->note = 0xFE; else - // if note < 251, then all three bytes are stored in the file - if (note < 0xFC) m->note = (note >> 4)*12 + (note&0xf) + 37; - if (vol <= 64) { m->volcmd = VOLCMD_VOLUME; m->vol = vol; } - m->param = p->cmdinf; - switch(cmd) - { - // Axx set speed to xx - case 1: m->command = CMD_SPEED; m->param >>= 4; break; - // Bxx position jump - case 2: m->command = CMD_POSITIONJUMP; break; - // Cxx patternbreak to row xx - case 3: m->command = CMD_PATTERNBREAK; m->param = (m->param & 0xF0) * 10 + (m->param & 0x0F); break; - // Dxy volumeslide - case 4: m->command = CMD_VOLUMESLIDE; break; - // Exy toneslide down - case 5: m->command = CMD_PORTAMENTODOWN; break; - // Fxy toneslide up - case 6: m->command = CMD_PORTAMENTOUP; break; - // Gxx Tone portamento,speed xx - case 7: m->command = CMD_TONEPORTAMENTO; break; - // Hxy vibrato - case 8: m->command = CMD_VIBRATO; break; - // Ixy tremor, ontime x, offtime y - case 9: m->command = CMD_TREMOR; break; - // Jxy arpeggio - case 10: m->command = CMD_ARPEGGIO; break; - // Kxy Dual command H00 & Dxy - case 11: m->command = CMD_VIBRATOVOL; break; - // Lxy Dual command G00 & Dxy - case 12: m->command = CMD_TONEPORTAVOL; break; - // Xxx amiga command 8xx - case 0x18: m->command = CMD_PANNING8; break; - default: - m->command = m->param = 0; - } - } - dwMemPos += 64*4*4; - } - // Reading Samples - for (UINT nSmp=1; nSmp<=31; nSmp++) - { - MODINSTRUMENT *pIns = &Ins[nSmp]; - dwMemPos = (dwMemPos + 15) & (~15); - if (pIns->nLength) - { - UINT nPos = ((UINT)phdr->sample[nSmp-1].reserved) << 4; - if ((nPos >= sizeof(STMHEADER)) && (nPos+pIns->nLength <= dwMemLength)) dwMemPos = nPos; - if (dwMemPos < dwMemLength) - { - dwMemPos += ReadSample(pIns, RS_PCM8S, (LPSTR)(lpStream+dwMemPos),dwMemLength-dwMemPos); - } - } - } - return TRUE; -} - diff --git a/jni/load_ult.cpp b/jni/load_ult.cpp deleted file mode 100644 index 83024f2..0000000 --- a/jni/load_ult.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -#include "stdafx.h" -#include "sndfile.h" - -//#pragma warning(disable:4244) - -#define ULT_16BIT 0x04 -#define ULT_LOOP 0x08 -#define ULT_BIDI 0x10 - -#pragma pack(1) - -// Raw ULT header struct: -typedef struct tagULTHEADER -{ - char id[15]; // changed from CHAR - char songtitle[32]; // changed from CHAR - BYTE reserved; -} ULTHEADER; - - -// Raw ULT sampleinfo struct: -typedef struct tagULTSAMPLE -{ - CHAR samplename[32]; - CHAR dosname[12]; - LONG loopstart; - LONG loopend; - LONG sizestart; - LONG sizeend; - BYTE volume; - BYTE flags; - WORD finetune; -} ULTSAMPLE; - -#pragma pack() - - -BOOL CSoundFile::ReadUlt(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - ULTHEADER *pmh = (ULTHEADER *)lpStream; - ULTSAMPLE *pus; - UINT nos, nop; - DWORD dwMemPos = 0; - - // try to read module header - if ((!lpStream) || (dwMemLength < 0x100)) return FALSE; - if (strncmp(pmh->id,"MAS_UTrack_V00",14)) return FALSE; - // Warning! Not supported ULT format, trying anyway - // if ((pmh->id[14] < '1') || (pmh->id[14] > '4')) return FALSE; - m_nType = MOD_TYPE_ULT; - m_nDefaultSpeed = 6; - m_nDefaultTempo = 125; - memcpy(m_szNames[0], pmh->songtitle, 32); - m_szNames[0][31] = '\0'; - // read songtext - dwMemPos = sizeof(ULTHEADER); - if ((pmh->reserved) && (dwMemPos + pmh->reserved * 32 < dwMemLength)) - { - UINT len = pmh->reserved * 32; - m_lpszSongComments = new char[len + 1 + pmh->reserved]; - if (m_lpszSongComments) - { - for (UINT l=0; lreserved; l++) - { - memcpy(m_lpszSongComments+l*33, lpStream+dwMemPos+l*32, 32); - m_lpszSongComments[l*33+32] = 0x0D; - } - m_lpszSongComments[len] = 0; - } - dwMemPos += len; - } - if (dwMemPos >= dwMemLength) return TRUE; - nos = lpStream[dwMemPos++]; - m_nSamples = nos; - if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; - UINT smpsize = 64; - if (pmh->id[14] >= '4') smpsize += 2; - if (dwMemPos + nos*smpsize + 256 + 2 > dwMemLength) return TRUE; - for (UINT ins=1; ins<=nos; ins++, dwMemPos+=smpsize) if (ins<=m_nSamples) - { - pus = (ULTSAMPLE *)(lpStream+dwMemPos); - MODINSTRUMENT *pins = &Ins[ins]; - memcpy(m_szNames[ins], pus->samplename, 32); - m_szNames[ins][31] = '\0'; - memcpy(pins->name, pus->dosname, 12); - pins->nLoopStart = pus->loopstart; - pins->nLoopEnd = pus->loopend; - pins->nLength = pus->sizeend - pus->sizestart; - pins->nVolume = pus->volume; - pins->nGlobalVol = 64; - pins->nC4Speed = 8363; - if (pmh->id[14] >= '4') - { - pins->nC4Speed = pus->finetune; - } - if (pus->flags & ULT_LOOP) pins->uFlags |= CHN_LOOP; - if (pus->flags & ULT_BIDI) pins->uFlags |= CHN_PINGPONGLOOP; - if (pus->flags & ULT_16BIT) - { - pins->uFlags |= CHN_16BIT; - pins->nLoopStart >>= 1; - pins->nLoopEnd >>= 1; - } - } - memcpy(Order, lpStream+dwMemPos, 256); - dwMemPos += 256; - m_nChannels = lpStream[dwMemPos] + 1; - nop = lpStream[dwMemPos+1] + 1; - dwMemPos += 2; - if (m_nChannels > 32) m_nChannels = 32; - // Default channel settings - for (UINT nSet=0; nSetid[14]>='3') - { - if (dwMemPos + m_nChannels > dwMemLength) return TRUE; - for(UINT t=0; t 256) ChnSettings[t].nPan = 256; - } - } - // Allocating Patterns - for (UINT nAllocPat=0; nAllocPat dwMemLength) return TRUE; - UINT rep = 1; - UINT note = lpStream[dwMemPos++]; - if (note == 0xFC) - { - rep = lpStream[dwMemPos]; - note = lpStream[dwMemPos+1]; - dwMemPos += 2; - } - UINT instr = lpStream[dwMemPos++]; - UINT eff = lpStream[dwMemPos++]; - UINT dat1 = lpStream[dwMemPos++]; - UINT dat2 = lpStream[dwMemPos++]; - UINT cmd1 = eff & 0x0F; - UINT cmd2 = eff >> 4; - if (cmd1 == 0x0C) dat1 >>= 2; else - if (cmd1 == 0x0B) { cmd1 = dat1 = 0; } - if (cmd2 == 0x0C) dat2 >>= 2; else - if (cmd2 == 0x0B) { cmd2 = dat2 = 0; } - while ((rep != 0) && (row < 64)) - { - if (pat) - { - pat->instr = instr; - if (note) pat->note = note + 36; - if (cmd1 | dat1) - { - if (cmd1 == 0x0C) - { - pat->volcmd = VOLCMD_VOLUME; - pat->vol = dat1; - } else - { - pat->command = cmd1; - pat->param = dat1; - ConvertModCommand(pat); - } - } - if (cmd2 == 0x0C) - { - pat->volcmd = VOLCMD_VOLUME; - pat->vol = dat2; - } else - if ((cmd2 | dat2) && (!pat->command)) - { - pat->command = cmd2; - pat->param = dat2; - ConvertModCommand(pat); - } - pat += m_nChannels; - } - row++; - rep--; - } - } - } - } - // Reading Instruments - for (UINT smp=1; smp<=m_nSamples; smp++) if (Ins[smp].nLength) - { - if (dwMemPos >= dwMemLength) return TRUE; - UINT flags = (Ins[smp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; - dwMemPos += ReadSample(&Ins[smp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos); - } - return TRUE; -} - diff --git a/jni/load_umx.cpp b/jni/load_umx.cpp deleted file mode 100644 index 8913c74..0000000 --- a/jni/load_umx.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -#include "stdafx.h" -#include "sndfile.h" - -#define MODMAGIC_OFFSET (20+31*30+130) - - -BOOL CSoundFile::ReadUMX(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - if ((!lpStream) || (dwMemLength < 0x800)) return FALSE; - // Rip Mods from UMX - if ((bswapLE32(*((DWORD *)(lpStream+0x20))) < dwMemLength) - && (bswapLE32(*((DWORD *)(lpStream+0x18))) <= dwMemLength - 0x10) - && (bswapLE32(*((DWORD *)(lpStream+0x18))) >= dwMemLength - 0x200)) - { - for (UINT uscan=0x40; uscan<0x500; uscan++) - { - DWORD dwScan = bswapLE32(*((DWORD *)(lpStream+uscan))); - // IT - if (dwScan == 0x4D504D49) - { - DWORD dwRipOfs = uscan; - return ReadIT(lpStream + dwRipOfs, dwMemLength - dwRipOfs); - } - // S3M - if (dwScan == 0x4D524353) - { - DWORD dwRipOfs = uscan - 44; - return ReadS3M(lpStream + dwRipOfs, dwMemLength - dwRipOfs); - } - // XM - if (!strnicmp((LPCSTR)(lpStream+uscan), "Extended Module", 15)) - { - DWORD dwRipOfs = uscan; - return ReadXM(lpStream + dwRipOfs, dwMemLength - dwRipOfs); - } - // MOD - if ((uscan > MODMAGIC_OFFSET) && (dwScan == 0x2e4b2e4d)) - { - DWORD dwRipOfs = uscan - MODMAGIC_OFFSET; - return ReadMod(lpStream+dwRipOfs, dwMemLength-dwRipOfs); - } - } - } - return FALSE; -} - diff --git a/jni/load_wav.cpp b/jni/load_wav.cpp deleted file mode 100644 index 0399cba..0000000 --- a/jni/load_wav.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -#include "stdafx.h" -#include "sndfile.h" - -#ifndef WAVE_FORMAT_EXTENSIBLE -#define WAVE_FORMAT_EXTENSIBLE 0xFFFE -#endif - -///////////////////////////////////////////////////////////// -// WAV file support - -BOOL CSoundFile::ReadWav(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - DWORD dwMemPos = 0; - WAVEFILEHEADER *phdr = (WAVEFILEHEADER *)lpStream; - WAVEFORMATHEADER *pfmt = (WAVEFORMATHEADER *)(lpStream + sizeof(WAVEFILEHEADER)); - if ((!lpStream) || (dwMemLength < (DWORD)sizeof(WAVEFILEHEADER))) return FALSE; - if ((phdr->id_RIFF != IFFID_RIFF) || (phdr->id_WAVE != IFFID_WAVE) - || (pfmt->id_fmt != IFFID_fmt)) return FALSE; - dwMemPos = sizeof(WAVEFILEHEADER) + 8 + pfmt->hdrlen; - if ((dwMemPos + 8 >= dwMemLength) - || ((pfmt->format != WAVE_FORMAT_PCM) && (pfmt->format != WAVE_FORMAT_EXTENSIBLE)) - || (pfmt->channels > 4) - || (!pfmt->channels) - || (!pfmt->freqHz) - || (pfmt->bitspersample & 7) - || (pfmt->bitspersample < 8) - || (pfmt->bitspersample > 32)) return FALSE; - WAVEDATAHEADER *pdata; - for (;;) - { - pdata = (WAVEDATAHEADER *)(lpStream + dwMemPos); - if (pdata->id_data == IFFID_data) break; - dwMemPos += pdata->length + 8; - if (dwMemPos + 8 >= dwMemLength) return FALSE; - } - m_nType = MOD_TYPE_WAV; - m_nSamples = 0; - m_nInstruments = 0; - m_nChannels = 4; - m_nDefaultSpeed = 8; - m_nDefaultTempo = 125; - m_dwSongFlags |= SONG_LINEARSLIDES; // For no resampling - Order[0] = 0; - Order[1] = 0xFF; - PatternSize[0] = PatternSize[1] = 64; - if ((Patterns[0] = AllocatePattern(64, 4)) == NULL) return TRUE; - if ((Patterns[1] = AllocatePattern(64, 4)) == NULL) return TRUE; - UINT samplesize = (pfmt->channels * pfmt->bitspersample) >> 3; - UINT len = pdata->length, bytelen; - if (len > dwMemLength - 8 - dwMemPos) len = dwMemLength - dwMemPos - 8; - len /= samplesize; - bytelen = len; - if (pfmt->bitspersample >= 16) bytelen *= 2; - if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH; - if (!len) return TRUE; - // Setting up module length - DWORD dwTime = ((len * 50) / pfmt->freqHz) + 1; - DWORD framesperrow = (dwTime + 63) / 63; - if (framesperrow < 4) framesperrow = 4; - UINT norders = 1; - while (framesperrow >= 0x20) - { - Order[norders++] = 1; - Order[norders] = 0xFF; - framesperrow = (dwTime + (64 * norders - 1)) / (64 * norders); - if (norders >= MAX_ORDERS-1) break; - } - m_nDefaultSpeed = framesperrow; - for (UINT iChn=0; iChn<4; iChn++) - { - ChnSettings[iChn].nPan = (iChn & 1) ? 256 : 0; - ChnSettings[iChn].nVolume = 64; - ChnSettings[iChn].dwFlags = 0; - } - // Setting up speed command - MODCOMMAND *pcmd = Patterns[0]; - pcmd[0].command = CMD_SPEED; - pcmd[0].param = (BYTE)m_nDefaultSpeed; - pcmd[0].note = 5*12+1; - pcmd[0].instr = 1; - pcmd[1].note = pcmd[0].note; - pcmd[1].instr = pcmd[0].instr; - m_nSamples = pfmt->channels; - // Support for Multichannel Wave - for (UINT nChn=0; nChnnLength = len; - pins->nC4Speed = pfmt->freqHz; - pins->nVolume = 256; - pins->nPan = 128; - pins->nGlobalVol = 64; - pins->uFlags = (WORD)((pfmt->bitspersample >= 16) ? CHN_16BIT : 0); - pins->uFlags |= CHN_PANNING; - if (m_nSamples > 1) - { - switch(nChn) - { - case 0: pins->nPan = 0; break; - case 1: pins->nPan = 256; break; - case 2: pins->nPan = (WORD)((m_nSamples == 3) ? 128 : 64); pcmd[nChn].command = CMD_S3MCMDEX; pcmd[nChn].param = 0x91; break; - case 3: pins->nPan = 192; pcmd[nChn].command = CMD_S3MCMDEX; pcmd[nChn].param = 0x91; break; - default: pins->nPan = 128; break; - } - } - if ((pins->pSample = AllocateSample(bytelen+8)) == NULL) return TRUE; - if (pfmt->bitspersample >= 16) - { - int slsize = pfmt->bitspersample >> 3; - signed short *p = (signed short *)pins->pSample; - signed char *psrc = (signed char *)(lpStream+dwMemPos+8+nChn*slsize+slsize-2); - for (UINT i=0; ipSample; - signed char *psrc = (signed char *)(lpStream+dwMemPos+8+nChn); - for (UINT i=0; i dwBytes)) return FALSE; - nPos = 0; - while ((nPos < nLen) && (dwBytes > 4)) - { - int nIndex; - value = *((short int *)psrc); - nIndex = psrc[2]; - psrc += 4; - dwBytes -= 4; - pdest[nPos++] = (short int)value; - for (UINT i=0; ((i<(pkBlkAlign-4)*2) && (nPos < nLen) && (dwBytes)); i++) - { - BYTE delta; - if (i & 1) - { - delta = (BYTE)(((*(psrc++)) >> 4) & 0x0F); - dwBytes--; - } else - { - delta = (BYTE)((*psrc) & 0x0F); - } - int v = gIMAUnpackTable[nIndex] >> 3; - if (delta & 1) v += gIMAUnpackTable[nIndex] >> 2; - if (delta & 2) v += gIMAUnpackTable[nIndex] >> 1; - if (delta & 4) v += gIMAUnpackTable[nIndex]; - if (delta & 8) value -= v; else value += v; - nIndex += gIMAIndexTab[delta & 7]; - if (nIndex < 0) nIndex = 0; else - if (nIndex > 88) nIndex = 88; - if (value > 32767) value = 32767; else - if (value < -32768) value = -32768; - pdest[nPos++] = (short int)value; - } - } - return TRUE; -} - - - diff --git a/jni/load_xm.cpp b/jni/load_xm.cpp deleted file mode 100644 index f6f2b35..0000000 --- a/jni/load_xm.cpp +++ /dev/null @@ -1,893 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque , - * Adam Goode (endian and char fixes for PPC) -*/ - -#include "stdafx.h" -#include "sndfile.h" - -//////////////////////////////////////////////////////// -// FastTracker II XM file support - -#ifdef MSC_VER -#pragma warning(disable:4244) -#endif - -#pragma pack(1) -typedef struct tagXMFILEHEADER -{ - DWORD size; - WORD norder; - WORD restartpos; - WORD channels; - WORD patterns; - WORD instruments; - WORD flags; - WORD speed; - WORD tempo; - BYTE order[256]; -} XMFILEHEADER; - - -typedef struct tagXMINSTRUMENTHEADER -{ - DWORD size; - CHAR name[22]; - BYTE type; - BYTE samples; - BYTE samplesh; -} XMINSTRUMENTHEADER; - - -typedef struct tagXMSAMPLEHEADER -{ - DWORD shsize; - BYTE snum[96]; - WORD venv[24]; - WORD penv[24]; - BYTE vnum, pnum; - BYTE vsustain, vloops, vloope, psustain, ploops, ploope; - BYTE vtype, ptype; - BYTE vibtype, vibsweep, vibdepth, vibrate; - WORD volfade; - WORD res; - BYTE reserved1[20]; -} XMSAMPLEHEADER; - -typedef struct tagXMSAMPLESTRUCT -{ - DWORD samplen; - DWORD loopstart; - DWORD looplen; - BYTE vol; - signed char finetune; - BYTE type; - BYTE pan; - signed char relnote; - BYTE res; - char name[22]; -} XMSAMPLESTRUCT; -#pragma pack() - - -BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength) -//-------------------------------------------------------------- -{ - XMSAMPLEHEADER xmsh; - XMSAMPLESTRUCT xmss; - DWORD dwMemPos, dwHdrSize; - WORD norders=0, restartpos=0, channels=0, patterns=0, instruments=0; - WORD xmflags=0, deftempo=125, defspeed=6; - BOOL InstUsed[256]; - BYTE channels_used[MAX_CHANNELS]; - BYTE pattern_map[256]; - BOOL samples_used[MAX_SAMPLES]; - UINT unused_samples; - tagXMFILEHEADER xmhead; - - m_nChannels = 0; - if ((!lpStream) || (dwMemLength < 0x200)) return FALSE; - if (strnicmp((LPCSTR)lpStream, "Extended Module", 15)) return FALSE; - - memcpy(m_szNames[0], lpStream+17, 20); - xmhead = *(tagXMFILEHEADER *)(lpStream+60); - dwHdrSize = bswapLE32(xmhead.size); - norders = bswapLE16(xmhead.norder); - if ((!norders) || (norders > MAX_ORDERS)) return FALSE; - restartpos = bswapLE16(xmhead.restartpos); - channels = bswapLE16(xmhead.channels); - if ((!channels) || (channels > 64)) return FALSE; - m_nType = MOD_TYPE_XM; - m_nMinPeriod = 27; - m_nMaxPeriod = 54784; - m_nChannels = channels; - if (restartpos < norders) m_nRestartPos = restartpos; - patterns = bswapLE16(xmhead.patterns); - if (patterns > 256) patterns = 256; - instruments = bswapLE16(xmhead.instruments); - if (instruments >= MAX_INSTRUMENTS) instruments = MAX_INSTRUMENTS-1; - m_nInstruments = instruments; - m_nSamples = 0; - xmflags = bswapLE16(xmhead.flags); - if (xmflags & 1) m_dwSongFlags |= SONG_LINEARSLIDES; - if (xmflags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE; - defspeed = bswapLE16(xmhead.speed); - deftempo = bswapLE16(xmhead.tempo); - if ((deftempo >= 32) && (deftempo < 256)) m_nDefaultTempo = deftempo; - if ((defspeed > 0) && (defspeed < 40)) m_nDefaultSpeed = defspeed; - memcpy(Order, lpStream+80, norders); - memset(InstUsed, 0, sizeof(InstUsed)); - if (patterns > MAX_PATTERNS) - { - UINT i, j; - for (i=0; i= dwMemLength) return TRUE; - // Reading patterns - memset(channels_used, 0, sizeof(channels_used)); - for (UINT ipat=0; ipat= dwMemLength) || (dwSize & 0xFFFFFF00)) - { - if (dwMemPos + 4 >= dwMemLength) break; - dwMemPos++; - dwSize = bswapLE32(*((DWORD *)(lpStream+dwMemPos))); - } - rows = bswapLE16(*((WORD *)(lpStream+dwMemPos+5))); - if ((!rows) || (rows > 256)) rows = 64; - packsize = bswapLE16(*((WORD *)(lpStream+dwMemPos+7))); - if (dwMemPos + dwSize + 4 > dwMemLength) return TRUE; - dwMemPos += dwSize; - if (dwMemPos + packsize + 4 > dwMemLength) return TRUE; - MODCOMMAND *p; - if (ipatmap < MAX_PATTERNS) - { - PatternSize[ipatmap] = rows; - if ((Patterns[ipatmap] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; - if (!packsize) continue; - p = Patterns[ipatmap]; - } else p = NULL; - const BYTE *src = lpStream+dwMemPos; - UINT j=0; - for (UINT row=0; rownote = src[j++]; - if (b & 2) p->instr = src[j++]; - if (b & 4) vol = src[j++]; - if (b & 8) p->command = src[j++]; - if (b & 16) p->param = src[j++]; - } else - { - p->note = b; - p->instr = src[j++]; - vol = src[j++]; - p->command = src[j++]; - p->param = src[j++]; - } - if (p->note == 97) p->note = 0xFF; else - if ((p->note) && (p->note < 97)) p->note += 12; - if (p->note) channels_used[chn] = 1; - if (p->command | p->param) ConvertModCommand(p); - if (p->instr == 0xff) p->instr = 0; - if (p->instr) InstUsed[p->instr] = TRUE; - if ((vol >= 0x10) && (vol <= 0x50)) - { - p->volcmd = VOLCMD_VOLUME; - p->vol = vol - 0x10; - } else - if (vol >= 0x60) - { - UINT v = vol & 0xF0; - vol &= 0x0F; - p->vol = vol; - switch(v) - { - // 60-6F: Volume Slide Down - case 0x60: p->volcmd = VOLCMD_VOLSLIDEDOWN; break; - // 70-7F: Volume Slide Up: - case 0x70: p->volcmd = VOLCMD_VOLSLIDEUP; break; - // 80-8F: Fine Volume Slide Down - case 0x80: p->volcmd = VOLCMD_FINEVOLDOWN; break; - // 90-9F: Fine Volume Slide Up - case 0x90: p->volcmd = VOLCMD_FINEVOLUP; break; - // A0-AF: Set Vibrato Speed - case 0xA0: p->volcmd = VOLCMD_VIBRATOSPEED; break; - // B0-BF: Vibrato - case 0xB0: p->volcmd = VOLCMD_VIBRATO; break; - // C0-CF: Set Panning - case 0xC0: p->volcmd = VOLCMD_PANNING; p->vol = (vol << 2) + 2; break; - // D0-DF: Panning Slide Left - case 0xD0: p->volcmd = VOLCMD_PANSLIDELEFT; break; - // E0-EF: Panning Slide Right - case 0xE0: p->volcmd = VOLCMD_PANSLIDERIGHT; break; - // F0-FF: Tone Portamento - case 0xF0: p->volcmd = VOLCMD_TONEPORTAMENTO; break; - } - } - p++; - } else - if (j < packsize) - { - BYTE b = src[j++]; - if (b & 0x80) - { - if (b & 1) j++; - if (b & 2) j++; - if (b & 4) j++; - if (b & 8) j++; - if (b & 16) j++; - } else j += 4; - } else break; - } - } - dwMemPos += packsize; - } - // Wrong offset check - while (dwMemPos + 4 < dwMemLength) - { - DWORD d = bswapLE32(*((DWORD *)(lpStream+dwMemPos))); - if (d < 0x300) break; - dwMemPos++; - } - memset(samples_used, 0, sizeof(samples_used)); - unused_samples = 0; - // Reading instruments - for (UINT iIns=1; iIns<=instruments; iIns++) - { - XMINSTRUMENTHEADER *pih; - BYTE flags[32]; - DWORD samplesize[32]; - UINT samplemap[32]; - WORD nsamples; - - if (dwMemPos + sizeof(XMINSTRUMENTHEADER) >= dwMemLength) return TRUE; - pih = (XMINSTRUMENTHEADER *)(lpStream+dwMemPos); - if (dwMemPos + bswapLE32(pih->size) > dwMemLength) return TRUE; - if ((Headers[iIns] = new INSTRUMENTHEADER) == NULL) continue; - memset(Headers[iIns], 0, sizeof(INSTRUMENTHEADER)); - memcpy(Headers[iIns]->name, pih->name, 22); - if ((nsamples = pih->samples) > 0) - { - if (dwMemPos + sizeof(XMSAMPLEHEADER) > dwMemLength) return TRUE; - memcpy(&xmsh, lpStream+dwMemPos+sizeof(XMINSTRUMENTHEADER), sizeof(XMSAMPLEHEADER)); - xmsh.shsize = bswapLE32(xmsh.shsize); - for (int i = 0; i < 24; ++i) { - xmsh.venv[i] = bswapLE16(xmsh.venv[i]); - xmsh.penv[i] = bswapLE16(xmsh.penv[i]); - } - xmsh.volfade = bswapLE16(xmsh.volfade); - xmsh.res = bswapLE16(xmsh.res); - dwMemPos += bswapLE32(pih->size); - } else - { - if (bswapLE32(pih->size)) dwMemPos += bswapLE32(pih->size); - else dwMemPos += sizeof(XMINSTRUMENTHEADER); - continue; - } - memset(samplemap, 0, sizeof(samplemap)); - if (nsamples > 32) return TRUE; - UINT newsamples = m_nSamples; - for (UINT nmap=0; nmap= MAX_SAMPLES) - { - n = m_nSamples; - while (n > 0) - { - if (!Ins[n].pSample) - { - for (UINT xmapchk=0; xmapchk < nmap; xmapchk++) - { - if (samplemap[xmapchk] == n) goto alreadymapped; - } - for (UINT clrs=1; clrsKeyboard[ks] == n) pks->Keyboard[ks] = 0; - } - } - break; - } - alreadymapped: - n--; - } -#ifndef MODPLUG_FASTSOUNDLIB - // Damn! more than 200 samples: look for duplicates - if (!n) - { - if (!unused_samples) - { - unused_samples = DetectUnusedSamples(samples_used); - if (!unused_samples) unused_samples = 0xFFFF; - } - if ((unused_samples) && (unused_samples != 0xFFFF)) - { - for (UINT iext=m_nSamples; iext>=1; iext--) if (!samples_used[iext]) - { - unused_samples--; - samples_used[iext] = TRUE; - DestroySample(iext); - n = iext; - for (UINT mapchk=0; mapchkKeyboard[ks] == n) pks->Keyboard[ks] = 0; - } - } - memset(&Ins[n], 0, sizeof(Ins[0])); - break; - } - } - } -#endif // MODPLUG_FASTSOUNDLIB - } - if (newsamples < n) newsamples = n; - samplemap[nmap] = n; - } - m_nSamples = newsamples; - // Reading Volume Envelope - INSTRUMENTHEADER *penv = Headers[iIns]; - penv->nMidiProgram = pih->type; - penv->nFadeOut = xmsh.volfade; - penv->nPan = 128; - penv->nPPC = 5*12; - if (xmsh.vtype & 1) penv->dwFlags |= ENV_VOLUME; - if (xmsh.vtype & 2) penv->dwFlags |= ENV_VOLSUSTAIN; - if (xmsh.vtype & 4) penv->dwFlags |= ENV_VOLLOOP; - if (xmsh.ptype & 1) penv->dwFlags |= ENV_PANNING; - if (xmsh.ptype & 2) penv->dwFlags |= ENV_PANSUSTAIN; - if (xmsh.ptype & 4) penv->dwFlags |= ENV_PANLOOP; - if (xmsh.vnum > 12) xmsh.vnum = 12; - if (xmsh.pnum > 12) xmsh.pnum = 12; - penv->nVolEnv = xmsh.vnum; - if (!xmsh.vnum) penv->dwFlags &= ~ENV_VOLUME; - if (!xmsh.pnum) penv->dwFlags &= ~ENV_PANNING; - penv->nPanEnv = xmsh.pnum; - penv->nVolSustainBegin = penv->nVolSustainEnd = xmsh.vsustain; - if (xmsh.vsustain >= 12) penv->dwFlags &= ~ENV_VOLSUSTAIN; - penv->nVolLoopStart = xmsh.vloops; - penv->nVolLoopEnd = xmsh.vloope; - if (penv->nVolLoopEnd >= 12) penv->nVolLoopEnd = 0; - if (penv->nVolLoopStart >= penv->nVolLoopEnd) penv->dwFlags &= ~ENV_VOLLOOP; - penv->nPanSustainBegin = penv->nPanSustainEnd = xmsh.psustain; - if (xmsh.psustain >= 12) penv->dwFlags &= ~ENV_PANSUSTAIN; - penv->nPanLoopStart = xmsh.ploops; - penv->nPanLoopEnd = xmsh.ploope; - if (penv->nPanLoopEnd >= 12) penv->nPanLoopEnd = 0; - if (penv->nPanLoopStart >= penv->nPanLoopEnd) penv->dwFlags &= ~ENV_PANLOOP; - penv->nGlobalVol = 64; - for (UINT ienv=0; ienv<12; ienv++) - { - penv->VolPoints[ienv] = (WORD)xmsh.venv[ienv*2]; - penv->VolEnv[ienv] = (BYTE)xmsh.venv[ienv*2+1]; - penv->PanPoints[ienv] = (WORD)xmsh.penv[ienv*2]; - penv->PanEnv[ienv] = (BYTE)xmsh.penv[ienv*2+1]; - if (ienv) - { - if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) - { - penv->VolPoints[ienv] &= 0xFF; - penv->VolPoints[ienv] += penv->VolPoints[ienv-1] & 0xFF00; - if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) penv->VolPoints[ienv] += 0x100; - } - if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) - { - penv->PanPoints[ienv] &= 0xFF; - penv->PanPoints[ienv] += penv->PanPoints[ienv-1] & 0xFF00; - if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) penv->PanPoints[ienv] += 0x100; - } - } - } - for (UINT j=0; j<96; j++) - { - penv->NoteMap[j+12] = j+1+12; - if (xmsh.snum[j] < nsamples) - penv->Keyboard[j+12] = samplemap[xmsh.snum[j]]; - } - // Reading samples - for (UINT ins=0; ins dwMemLength) - || (dwMemPos + xmsh.shsize > dwMemLength)) return TRUE; - memcpy(&xmss, lpStream+dwMemPos, sizeof(xmss)); - xmss.samplen = bswapLE32(xmss.samplen); - xmss.loopstart = bswapLE32(xmss.loopstart); - xmss.looplen = bswapLE32(xmss.looplen); - dwMemPos += xmsh.shsize; - flags[ins] = (xmss.type & 0x10) ? RS_PCM16D : RS_PCM8D; - if (xmss.type & 0x20) flags[ins] = (xmss.type & 0x10) ? RS_STPCM16D : RS_STPCM8D; - samplesize[ins] = xmss.samplen; - if (!samplemap[ins]) continue; - if (xmss.type & 0x10) - { - xmss.looplen >>= 1; - xmss.loopstart >>= 1; - xmss.samplen >>= 1; - } - if (xmss.type & 0x20) - { - xmss.looplen >>= 1; - xmss.loopstart >>= 1; - xmss.samplen >>= 1; - } - if (xmss.samplen > MAX_SAMPLE_LENGTH) xmss.samplen = MAX_SAMPLE_LENGTH; - if (xmss.loopstart >= xmss.samplen) xmss.type &= ~3; - xmss.looplen += xmss.loopstart; - if (xmss.looplen > xmss.samplen) xmss.looplen = xmss.samplen; - if (!xmss.looplen) xmss.type &= ~3; - UINT imapsmp = samplemap[ins]; - memcpy(m_szNames[imapsmp], xmss.name, 22); - m_szNames[imapsmp][22] = 0; - MODINSTRUMENT *pins = &Ins[imapsmp]; - pins->nLength = (xmss.samplen > MAX_SAMPLE_LENGTH) ? MAX_SAMPLE_LENGTH : xmss.samplen; - pins->nLoopStart = xmss.loopstart; - pins->nLoopEnd = xmss.looplen; - if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength; - if (pins->nLoopStart >= pins->nLoopEnd) - { - pins->nLoopStart = pins->nLoopEnd = 0; - } - if (xmss.type & 3) pins->uFlags |= CHN_LOOP; - if (xmss.type & 2) pins->uFlags |= CHN_PINGPONGLOOP; - pins->nVolume = xmss.vol << 2; - if (pins->nVolume > 256) pins->nVolume = 256; - pins->nGlobalVol = 64; - if ((xmss.res == 0xAD) && (!(xmss.type & 0x30))) - { - flags[ins] = RS_ADPCM4; - samplesize[ins] = (samplesize[ins]+1)/2 + 16; - } - pins->nFineTune = xmss.finetune; - pins->RelativeTone = (int)xmss.relnote; - pins->nPan = xmss.pan; - pins->uFlags |= CHN_PANNING; - pins->nVibType = xmsh.vibtype; - pins->nVibSweep = xmsh.vibsweep; - pins->nVibDepth = xmsh.vibdepth; - pins->nVibRate = xmsh.vibrate; - memcpy(pins->name, xmss.name, 22); - pins->name[21] = 0; - } -#if 0 - if ((xmsh.reserved2 > nsamples) && (xmsh.reserved2 <= 16)) - { - dwMemPos += (((UINT)xmsh.reserved2) - nsamples) * xmsh.shsize; - } -#endif - for (UINT ismpd=0; ismpd= dwMemLength) break; - } - } - // Read song comments: "TEXT" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x74786574)) - { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len < 16384)) - { - m_lpszSongComments = new char[len+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, len); - m_lpszSongComments[len] = 0; - } - dwMemPos += len; - } - } - // Read midi config: "MIDI" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4944494D)) - { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - if (len == sizeof(MODMIDICFG)) - { - memcpy(&m_MidiCfg, lpStream+dwMemPos, len); - m_dwSongFlags |= SONG_EMBEDMIDICFG; - } - } - // Read pattern names: "PNAM" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50)) - { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME)) - { - m_lpszPatternNames = new char[len]; - - if (m_lpszPatternNames) - { - m_nPatternNames = len / MAX_PATTERNNAME; - memcpy(m_lpszPatternNames, lpStream+dwMemPos, len); - } - dwMemPos += len; - } - } - // Read channel names: "CNAM" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43)) - { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= MAX_BASECHANNELS*MAX_CHANNELNAME)) - { - UINT n = len / MAX_CHANNELNAME; - for (UINT i=0; i= header.patterns) && (Order[i] < MAX_PATTERNS)) header.patterns = Order[i]+1; - } - header.instruments = m_nInstruments; - if (!header.instruments) header.instruments = m_nSamples; - header.flags = (m_dwSongFlags & SONG_LINEARSLIDES) ? 0x01 : 0x00; - if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000; - header.tempo = m_nDefaultTempo; - header.speed = m_nDefaultSpeed; - memcpy(header.order, Order, header.norder); - fwrite(&header, 1, sizeof(header), f); - // Writing patterns - for (i=0; i> 8); - for (UINT j=m_nChannels*PatternSize[i]; j; j--,p++) - { - UINT note = p->note; - UINT param = ModSaveCommand(p, TRUE); - UINT command = param >> 8; - param &= 0xFF; - if (note >= 0xFE) note = 97; else - if ((note <= 12) || (note > 96+12)) note = 0; else - note -= 12; - UINT vol = 0; - if (p->volcmd) - { - UINT volcmd = p->volcmd; - switch(volcmd) - { - case VOLCMD_VOLUME: vol = 0x10 + p->vol; break; - case VOLCMD_VOLSLIDEDOWN: vol = 0x60 + (p->vol & 0x0F); break; - case VOLCMD_VOLSLIDEUP: vol = 0x70 + (p->vol & 0x0F); break; - case VOLCMD_FINEVOLDOWN: vol = 0x80 + (p->vol & 0x0F); break; - case VOLCMD_FINEVOLUP: vol = 0x90 + (p->vol & 0x0F); break; - case VOLCMD_VIBRATOSPEED: vol = 0xA0 + (p->vol & 0x0F); break; - case VOLCMD_VIBRATO: vol = 0xB0 + (p->vol & 0x0F); break; - case VOLCMD_PANNING: vol = 0xC0 + (p->vol >> 2); if (vol > 0xCF) vol = 0xCF; break; - case VOLCMD_PANSLIDELEFT: vol = 0xD0 + (p->vol & 0x0F); break; - case VOLCMD_PANSLIDERIGHT: vol = 0xE0 + (p->vol & 0x0F); break; - case VOLCMD_TONEPORTAMENTO: vol = 0xF0 + (p->vol & 0x0F); break; - } - } - if ((note) && (p->instr) && (vol > 0x0F) && (command) && (param)) - { - s[len++] = note; - s[len++] = p->instr; - s[len++] = vol; - s[len++] = command; - s[len++] = param; - } else - { - BYTE b = 0x80; - if (note) b |= 0x01; - if (p->instr) b |= 0x02; - if (vol >= 0x10) b |= 0x04; - if (command) b |= 0x08; - if (param) b |= 0x10; - s[len++] = b; - if (b & 1) s[len++] = note; - if (b & 2) s[len++] = p->instr; - if (b & 4) s[len++] = vol; - if (b & 8) s[len++] = command; - if (b & 16) s[len++] = param; - } - if (len > sizeof(s) - 5) break; - } - xmph[7] = (BYTE)(len & 0xFF); - xmph[8] = (BYTE)(len >> 8); - fwrite(xmph, 1, 9, f); - fwrite(s, 1, len, f); - } else - { - memset(&xmph, 0, sizeof(xmph)); - xmph[0] = 9; - xmph[5] = (BYTE)(PatternSize[i] & 0xFF); - xmph[6] = (BYTE)(PatternSize[i] >> 8); - fwrite(xmph, 1, 9, f); - } - // Writing instruments - for (i=1; i<=header.instruments; i++) - { - MODINSTRUMENT *pins; - BYTE flags[32]; - - memset(&xmih, 0, sizeof(xmih)); - memset(&xmsh, 0, sizeof(xmsh)); - xmih.size = sizeof(xmih) + sizeof(xmsh); - memcpy(xmih.name, m_szNames[i], 22); - xmih.type = 0; - xmih.samples = 0; - if (m_nInstruments) - { - INSTRUMENTHEADER *penv = Headers[i]; - if (penv) - { - memcpy(xmih.name, penv->name, 22); - xmih.type = penv->nMidiProgram; - xmsh.volfade = penv->nFadeOut; - xmsh.vnum = (BYTE)penv->nVolEnv; - xmsh.pnum = (BYTE)penv->nPanEnv; - if (xmsh.vnum > 12) xmsh.vnum = 12; - if (xmsh.pnum > 12) xmsh.pnum = 12; - for (UINT ienv=0; ienv<12; ienv++) - { - xmsh.venv[ienv*2] = penv->VolPoints[ienv]; - xmsh.venv[ienv*2+1] = penv->VolEnv[ienv]; - xmsh.penv[ienv*2] = penv->PanPoints[ienv]; - xmsh.penv[ienv*2+1] = penv->PanEnv[ienv]; - } - if (penv->dwFlags & ENV_VOLUME) xmsh.vtype |= 1; - if (penv->dwFlags & ENV_VOLSUSTAIN) xmsh.vtype |= 2; - if (penv->dwFlags & ENV_VOLLOOP) xmsh.vtype |= 4; - if (penv->dwFlags & ENV_PANNING) xmsh.ptype |= 1; - if (penv->dwFlags & ENV_PANSUSTAIN) xmsh.ptype |= 2; - if (penv->dwFlags & ENV_PANLOOP) xmsh.ptype |= 4; - xmsh.vsustain = (BYTE)penv->nVolSustainBegin; - xmsh.vloops = (BYTE)penv->nVolLoopStart; - xmsh.vloope = (BYTE)penv->nVolLoopEnd; - xmsh.psustain = (BYTE)penv->nPanSustainBegin; - xmsh.ploops = (BYTE)penv->nPanLoopStart; - xmsh.ploope = (BYTE)penv->nPanLoopEnd; - for (UINT j=0; j<96; j++) if (penv->Keyboard[j+12]) - { - UINT k; - for (k=0; kKeyboard[j+12]) break; - if (k == xmih.samples) - { - smptable[xmih.samples++] = penv->Keyboard[j+12]; - } - if (xmih.samples >= 32) break; - xmsh.snum[j] = k; - } -// xmsh.reserved2 = xmih.samples; - } - } else - { - xmih.samples = 1; -// xmsh.reserved2 = 1; - smptable[0] = i; - } - xmsh.shsize = (xmih.samples) ? 40 : 0; - fwrite(&xmih, 1, sizeof(xmih), f); - if (smptable[0]) - { - MODINSTRUMENT *pvib = &Ins[smptable[0]]; - xmsh.vibtype = pvib->nVibType; - xmsh.vibsweep = pvib->nVibSweep; - xmsh.vibdepth = pvib->nVibDepth; - xmsh.vibrate = pvib->nVibRate; - } - fwrite(&xmsh, 1, xmih.size - sizeof(xmih), f); - if (!xmih.samples) continue; - for (UINT ins=0; insnLength; - xmss.loopstart = pins->nLoopStart; - xmss.looplen = pins->nLoopEnd - pins->nLoopStart; - xmss.vol = pins->nVolume / 4; - xmss.finetune = (char)pins->nFineTune; - xmss.type = 0; - if (pins->uFlags & CHN_LOOP) xmss.type = (pins->uFlags & CHN_PINGPONGLOOP) ? 2 : 1; - flags[ins] = RS_PCM8D; -#ifndef NO_PACKING - if (nPacking) - { - if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample((char *)pins->pSample, pins->nLength, nPacking))) - { - flags[ins] = RS_ADPCM4; - xmss.res = 0xAD; - } - } else -#endif - { - if (pins->uFlags & CHN_16BIT) - { - flags[ins] = RS_PCM16D; - xmss.type |= 0x10; - xmss.looplen *= 2; - xmss.loopstart *= 2; - xmss.samplen *= 2; - } - if (pins->uFlags & CHN_STEREO) - { - flags[ins] = (pins->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D; - xmss.type |= 0x20; - xmss.looplen *= 2; - xmss.loopstart *= 2; - xmss.samplen *= 2; - } - } - xmss.pan = 255; - if (pins->nPan < 256) xmss.pan = (BYTE)pins->nPan; - xmss.relnote = (signed char)pins->RelativeTone; - fwrite(&xmss, 1, xmsh.shsize, f); - } - for (UINT ismpd=0; ismpdpSample) - { -#ifndef NO_PACKING - if ((flags[ismpd] == RS_ADPCM4) && (xmih.samples>1)) CanPackSample((char *)pins->pSample, pins->nLength, nPacking); -#endif // NO_PACKING - WriteSample(f, pins, flags[ismpd]); - } - } - } - // Writing song comments - if ((m_lpszSongComments) && (m_lpszSongComments[0])) - { - DWORD d = 0x74786574; - fwrite(&d, 1, 4, f); - d = strlen(m_lpszSongComments); - fwrite(&d, 1, 4, f); - fwrite(m_lpszSongComments, 1, d, f); - } - // Writing midi cfg - if (m_dwSongFlags & SONG_EMBEDMIDICFG) - { - DWORD d = 0x4944494D; - fwrite(&d, 1, 4, f); - d = sizeof(MODMIDICFG); - fwrite(&d, 1, 4, f); - fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); - } - // Writing Pattern Names - if ((m_nPatternNames) && (m_lpszPatternNames)) - { - DWORD dwLen = m_nPatternNames * MAX_PATTERNNAME; - while ((dwLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwLen-MAX_PATTERNNAME])) dwLen -= MAX_PATTERNNAME; - if (dwLen >= MAX_PATTERNNAME) - { - DWORD d = 0x4d414e50; - fwrite(&d, 1, 4, f); - fwrite(&dwLen, 1, 4, f); - fwrite(m_lpszPatternNames, 1, dwLen, f); - } - } - // Writing Channel Names - { - UINT nChnNames = 0; - for (UINT inam=0; inam -*/ - -#include "stdafx.h" -#include "sndfile.h" - -BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength); - -typedef struct MMCMPFILEHEADER -{ - DWORD id_ziRC; // "ziRC" - DWORD id_ONia; // "ONia" - WORD hdrsize; -} MMCMPFILEHEADER, *LPMMCMPFILEHEADER; - -typedef struct MMCMPHEADER -{ - WORD version; - WORD nblocks; - DWORD filesize; - DWORD blktable; - BYTE glb_comp; - BYTE fmt_comp; -} MMCMPHEADER, *LPMMCMPHEADER; - -typedef struct MMCMPBLOCK -{ - DWORD unpk_size; - DWORD pk_size; - DWORD xor_chk; - WORD sub_blk; - WORD flags; - WORD tt_entries; - WORD num_bits; -} MMCMPBLOCK, *LPMMCMPBLOCK; - -typedef struct MMCMPSUBBLOCK -{ - DWORD unpk_pos; - DWORD unpk_size; -} MMCMPSUBBLOCK, *LPMMCMPSUBBLOCK; - -#define MMCMP_COMP 0x0001 -#define MMCMP_DELTA 0x0002 -#define MMCMP_16BIT 0x0004 -#define MMCMP_STEREO 0x0100 -#define MMCMP_ABS16 0x0200 -#define MMCMP_ENDIAN 0x0400 - -typedef struct MMCMPBITBUFFER -{ - UINT bitcount; - DWORD bitbuffer; - LPCBYTE pSrc; - LPCBYTE pEnd; - - DWORD GetBits(UINT nBits); -} MMCMPBITBUFFER; - - -DWORD MMCMPBITBUFFER::GetBits(UINT nBits) -//--------------------------------------- -{ - DWORD d; - if (!nBits) return 0; - while (bitcount < 24) - { - bitbuffer |= ((pSrc < pEnd) ? *pSrc++ : 0) << bitcount; - bitcount += 8; - } - d = bitbuffer & ((1 << nBits) - 1); - bitbuffer >>= nBits; - bitcount -= nBits; - return d; -} - -//#define MMCMP_LOG - -#ifdef MMCMP_LOG -extern void Log(LPCSTR s, ...); -#endif - -const DWORD MMCMP8BitCommands[8] = -{ - 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF8 -}; - -const UINT MMCMP8BitFetch[8] = -{ - 3, 3, 3, 3, 2, 1, 0, 0 -}; - -const DWORD MMCMP16BitCommands[16] = -{ - 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, - 0x1F0, 0x3F0, 0x7F0, 0xFF0, 0x1FF0, 0x3FF0, 0x7FF0, 0xFFF0 -}; - -const UINT MMCMP16BitFetch[16] = -{ - 4, 4, 4, 4, 3, 2, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - - -BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength) -//--------------------------------------------------------- -{ - DWORD dwMemLength = *pdwMemLength; - LPCBYTE lpMemFile = *ppMemFile; - LPBYTE pBuffer; - LPMMCMPFILEHEADER pmfh = (LPMMCMPFILEHEADER)(lpMemFile); - LPMMCMPHEADER pmmh = (LPMMCMPHEADER)(lpMemFile+10); - LPDWORD pblk_table; - DWORD dwFileSize; - - if (PP20_Unpack(ppMemFile, pdwMemLength)) - { - return TRUE; - } - if ((dwMemLength < 256) || (!pmfh) || (pmfh->id_ziRC != 0x4352697A) || (pmfh->id_ONia != 0x61694e4f) || (pmfh->hdrsize < 14) - || (!pmmh->nblocks) || (pmmh->filesize < 16) || (pmmh->filesize > 0x8000000) - || (pmmh->blktable >= dwMemLength) || (pmmh->blktable + 4*pmmh->nblocks > dwMemLength)) return FALSE; - dwFileSize = pmmh->filesize; - if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwFileSize + 31) & ~15)) == NULL) return FALSE; - pblk_table = (LPDWORD)(lpMemFile+pmmh->blktable); - for (UINT nBlock=0; nBlocknblocks; nBlock++) - { - DWORD dwMemPos = pblk_table[nBlock]; - LPMMCMPBLOCK pblk = (LPMMCMPBLOCK)(lpMemFile+dwMemPos); - LPMMCMPSUBBLOCK psubblk = (LPMMCMPSUBBLOCK)(lpMemFile+dwMemPos+20); - - if ((dwMemPos + 20 >= dwMemLength) || (dwMemPos + 20 + pblk->sub_blk*8 >= dwMemLength)) break; - dwMemPos += 20 + pblk->sub_blk*8; -#ifdef MMCMP_LOG - Log("block %d: flags=%04X sub_blocks=%d", nBlock, (UINT)pblk->flags, (UINT)pblk->sub_blk); - Log(" pksize=%d unpksize=%d", pblk->pk_size, pblk->unpk_size); - Log(" tt_entries=%d num_bits=%d\n", pblk->tt_entries, pblk->num_bits); -#endif - // Data is not packed - if (!(pblk->flags & MMCMP_COMP)) - { - for (UINT i=0; isub_blk; i++) - { - if ((psubblk->unpk_pos > dwFileSize) || (psubblk->unpk_pos + psubblk->unpk_size > dwFileSize)) break; -#ifdef MMCMP_LOG - Log(" Unpacked sub-block %d: offset %d, size=%d\n", i, psubblk->unpk_pos, psubblk->unpk_size); -#endif - memcpy(pBuffer+psubblk->unpk_pos, lpMemFile+dwMemPos, psubblk->unpk_size); - dwMemPos += psubblk->unpk_size; - psubblk++; - } - } else - // Data is 16-bit packed - if (pblk->flags & MMCMP_16BIT) - { - MMCMPBITBUFFER bb; - LPWORD pDest = (LPWORD)(pBuffer + psubblk->unpk_pos); - DWORD dwSize = psubblk->unpk_size >> 1; - DWORD dwPos = 0; - UINT numbits = pblk->num_bits; - UINT subblk = 0, oldval = 0; - -#ifdef MMCMP_LOG - Log(" 16-bit block: pos=%d size=%d ", psubblk->unpk_pos, psubblk->unpk_size); - if (pblk->flags & MMCMP_DELTA) Log("DELTA "); - if (pblk->flags & MMCMP_ABS16) Log("ABS16 "); - Log("\n"); -#endif - bb.bitcount = 0; - bb.bitbuffer = 0; - bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries; - bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size; - while (subblk < pblk->sub_blk) - { - UINT newval = 0x10000; - DWORD d = bb.GetBits(numbits+1); - - if (d >= MMCMP16BitCommands[numbits]) - { - UINT nFetch = MMCMP16BitFetch[numbits]; - UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP16BitCommands[numbits]) << nFetch); - if (newbits != numbits) - { - numbits = newbits & 0x0F; - } else - { - if ((d = bb.GetBits(4)) == 0x0F) - { - if (bb.GetBits(1)) break; - newval = 0xFFFF; - } else - { - newval = 0xFFF0 + d; - } - } - } else - { - newval = d; - } - if (newval < 0x10000) - { - newval = (newval & 1) ? (UINT)(-(LONG)((newval+1) >> 1)) : (UINT)(newval >> 1); - if (pblk->flags & MMCMP_DELTA) - { - newval += oldval; - oldval = newval; - } else - if (!(pblk->flags & MMCMP_ABS16)) - { - newval ^= 0x8000; - } - pDest[dwPos++] = (WORD)newval; - } - if (dwPos >= dwSize) - { - subblk++; - dwPos = 0; - dwSize = psubblk[subblk].unpk_size >> 1; - pDest = (LPWORD)(pBuffer + psubblk[subblk].unpk_pos); - } - } - } else - // Data is 8-bit packed - { - MMCMPBITBUFFER bb; - LPBYTE pDest = pBuffer + psubblk->unpk_pos; - DWORD dwSize = psubblk->unpk_size; - DWORD dwPos = 0; - UINT numbits = pblk->num_bits; - UINT subblk = 0, oldval = 0; - LPCBYTE ptable = lpMemFile+dwMemPos; - - bb.bitcount = 0; - bb.bitbuffer = 0; - bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries; - bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size; - while (subblk < pblk->sub_blk) - { - UINT newval = 0x100; - DWORD d = bb.GetBits(numbits+1); - - if (d >= MMCMP8BitCommands[numbits]) - { - UINT nFetch = MMCMP8BitFetch[numbits]; - UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP8BitCommands[numbits]) << nFetch); - if (newbits != numbits) - { - numbits = newbits & 0x07; - } else - { - if ((d = bb.GetBits(3)) == 7) - { - if (bb.GetBits(1)) break; - newval = 0xFF; - } else - { - newval = 0xF8 + d; - } - } - } else - { - newval = d; - } - if (newval < 0x100) - { - int n = ptable[newval]; - if (pblk->flags & MMCMP_DELTA) - { - n += oldval; - oldval = n; - } - pDest[dwPos++] = (BYTE)n; - } - if (dwPos >= dwSize) - { - subblk++; - dwPos = 0; - dwSize = psubblk[subblk].unpk_size; - pDest = pBuffer + psubblk[subblk].unpk_pos; - } - } - } - } - *ppMemFile = pBuffer; - *pdwMemLength = dwFileSize; - return TRUE; -} - - -////////////////////////////////////////////////////////////////////////////// -// -// PowerPack PP20 Unpacker -// - -typedef struct _PPBITBUFFER -{ - UINT bitcount; - ULONG bitbuffer; - LPCBYTE pStart; - LPCBYTE pSrc; - - ULONG GetBits(UINT n); -} PPBITBUFFER; - - -ULONG PPBITBUFFER::GetBits(UINT n) -{ - ULONG result = 0; - - for (UINT i=0; i>= 1; - bitcount--; - } - return result; -} - - -VOID PP20_DoUnpack(const BYTE *pSrc, UINT nSrcLen, BYTE *pDst, UINT nDstLen) -{ - PPBITBUFFER BitBuffer; - ULONG nBytesLeft; - - BitBuffer.pStart = pSrc; - BitBuffer.pSrc = pSrc + nSrcLen - 4; - BitBuffer.bitbuffer = 0; - BitBuffer.bitcount = 0; - BitBuffer.GetBits(pSrc[nSrcLen-1]); - nBytesLeft = nDstLen; - while (nBytesLeft > 0) - { - if (!BitBuffer.GetBits(1)) - { - UINT n = 1; - while (n < nBytesLeft) - { - UINT code = BitBuffer.GetBits(2); - n += code; - if (code != 3) break; - } - for (UINT i=0; i 0x400000) || (dwDstLen > 16*dwMemLength)) return FALSE; - if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwDstLen + 31) & ~15)) == NULL) return FALSE; - PP20_DoUnpack(lpMemFile+4, dwMemLength-4, pBuffer, dwDstLen); - *ppMemFile = pBuffer; - *pdwMemLength = dwDstLen; - return TRUE; -} - - - - - diff --git a/jni/modplug.cpp b/jni/modplug.cpp deleted file mode 100644 index a878112..0000000 --- a/jni/modplug.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Kenton Varda (C interface wrapper) - */ - -#include "modplug.h" -#include "stdafx.h" -#include "sndfile.h" - -struct _ModPlugFile -{ - CSoundFile mSoundFile; -}; - -namespace ModPlug -{ - ModPlug_Settings gSettings = - { - MODPLUG_ENABLE_OVERSAMPLING | - MODPLUG_ENABLE_NOISE_REDUCTION | - MODPLUG_ENABLE_REVERB, - - 2, // mChannels - 16, // mBits - 44100, // mFrequency - MODPLUG_RESAMPLE_LINEAR, //mResamplingMode - - 128, // mStereoSeparation - 32, // mMaxMixChannels - 50, // mReverbDepth - 100, // mReverbDelay - 0, - 0, - 0, - 0, - 0 - }; - - int gSampleSize; - - void UpdateSettings(bool updateBasicConfig) - { - if(gSettings.mFlags & MODPLUG_ENABLE_REVERB) - { - CSoundFile::SetReverbParameters(gSettings.mReverbDepth, - gSettings.mReverbDelay); - } - - if(gSettings.mFlags & MODPLUG_ENABLE_MEGABASS) - { - CSoundFile::SetXBassParameters(gSettings.mBassAmount, - gSettings.mBassRange); - } - else // modplug seems to ignore the SetWaveConfigEx() setting for bass boost - CSoundFile::SetXBassParameters(0, 0); - - if(gSettings.mFlags & MODPLUG_ENABLE_SURROUND) - { - CSoundFile::SetSurroundParameters(gSettings.mSurroundDepth, - gSettings.mSurroundDelay); - } - - if(updateBasicConfig) - { - CSoundFile::SetWaveConfig(gSettings.mFrequency, - gSettings.mBits, - gSettings.mChannels); - CSoundFile::SetMixConfig(gSettings.mStereoSeparation, - gSettings.mMaxMixChannels); - - gSampleSize = gSettings.mBits / 8 * gSettings.mChannels; - } - - CSoundFile::SetWaveConfigEx(gSettings.mFlags & MODPLUG_ENABLE_SURROUND, - !(gSettings.mFlags & MODPLUG_ENABLE_OVERSAMPLING), - gSettings.mFlags & MODPLUG_ENABLE_REVERB, - true, - gSettings.mFlags & MODPLUG_ENABLE_MEGABASS, - gSettings.mFlags & MODPLUG_ENABLE_NOISE_REDUCTION, - false); - CSoundFile::SetResamplingMode(gSettings.mResamplingMode); - } -} - -ModPlugFile* ModPlug_Load(const void* data, int size) -{ - ModPlugFile* result = new ModPlugFile; - ModPlug::UpdateSettings(true); - if(result->mSoundFile.Create((const BYTE*)data, size)) - { - result->mSoundFile.SetRepeatCount(ModPlug::gSettings.mLoopCount); - return result; - } - else - { - delete result; - return NULL; - } -} - -void ModPlug_Unload(ModPlugFile* file) -{ - file->mSoundFile.Destroy(); - delete file; -} - -int ModPlug_Read(ModPlugFile* file, void* buffer, int size) -{ - return file->mSoundFile.Read(buffer, size) * ModPlug::gSampleSize; -} - -const char* ModPlug_GetName(ModPlugFile* file) -{ - return file->mSoundFile.GetTitle(); -} - -int ModPlug_GetLength(ModPlugFile* file) -{ - return file->mSoundFile.GetSongTime() * 1000; -} - -void ModPlug_InitMixerCallback(ModPlugFile* file,ModPlugMixerProc proc) -{ - file->mSoundFile.gpSndMixHook = (LPSNDMIXHOOKPROC)proc ; - return; -} - -void ModPlug_UnloadMixerCallback(ModPlugFile* file) -{ - file->mSoundFile.gpSndMixHook = NULL; - return ; -} - -unsigned int ModPlug_GetMasterVolume(ModPlugFile* file) -{ - return (unsigned int)file->mSoundFile.m_nMasterVolume; -} - -void ModPlug_SetMasterVolume(ModPlugFile* file,unsigned int cvol) -{ - (void)file->mSoundFile.SetMasterVolume( (UINT)cvol, - FALSE ); - return ; -} - -int ModPlug_GetCurrentSpeed(ModPlugFile* file) -{ - return file->mSoundFile.m_nMusicSpeed; -} - -int ModPlug_GetCurrentTempo(ModPlugFile* file) -{ - return file->mSoundFile.m_nMusicTempo; -} - -int ModPlug_GetCurrentOrder(ModPlugFile* file) -{ - return file->mSoundFile.GetCurrentOrder(); -} - -int ModPlug_GetCurrentPattern(ModPlugFile* file) -{ - return file->mSoundFile.GetCurrentPattern(); -} - -int ModPlug_GetCurrentRow(ModPlugFile* file) -{ - return file->mSoundFile.m_nRow; -} - -int ModPlug_GetPlayingChannels(ModPlugFile* file) -{ - return ( file->mSoundFile.m_nMixChannels < file->mSoundFile.m_nMaxMixChannels ? file->mSoundFile.m_nMixChannels : file->mSoundFile.m_nMaxMixChannels ); -} - -void ModPlug_SeekOrder(ModPlugFile* file,int order) -{ - file->mSoundFile.SetCurrentOrder(order); -} - -int ModPlug_GetModuleType(ModPlugFile* file) -{ - return file->mSoundFile.m_nType; -} - -char* ModPlug_GetMessage(ModPlugFile* file) -{ - return file->mSoundFile.m_lpszSongComments; -} - -#ifndef MODPLUG_NO_FILESAVE -char ModPlug_ExportS3M(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveS3M(filepath,0); -} - -char ModPlug_ExportXM(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveXM(filepath,0); -} - -char ModPlug_ExportMOD(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveMod(filepath,0); -} - -char ModPlug_ExportIT(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveIT(filepath,0); -} -#endif // MODPLUG_NO_FILESAVE - -unsigned int ModPlug_NumInstruments(ModPlugFile* file) -{ - return file->mSoundFile.m_nInstruments; -} - -unsigned int ModPlug_NumSamples(ModPlugFile* file) -{ - return file->mSoundFile.m_nSamples; -} - -unsigned int ModPlug_NumPatterns(ModPlugFile* file) -{ - return file->mSoundFile.GetNumPatterns(); -} - -unsigned int ModPlug_NumChannels(ModPlugFile* file) -{ - return file->mSoundFile.GetNumChannels(); -} - -unsigned int ModPlug_SampleName(ModPlugFile* file,unsigned int qual,char* buff) -{ - return file->mSoundFile.GetSampleName(qual,buff); -} - -unsigned int ModPlug_InstrumentName(ModPlugFile* file,unsigned int qual,char* buff) -{ - return file->mSoundFile.GetInstrumentName(qual,buff); -} - -ModPlugNote* ModPlug_GetPattern(ModPlugFile* file,int pattern,unsigned int* numrows) { - if ( patternmSoundFile.Patterns[pattern]) { - if (numrows) *numrows=(unsigned int)file->mSoundFile.PatternSize[pattern]; - return (ModPlugNote*)file->mSoundFile.Patterns[pattern]; - } - } - return NULL; -} - -void ModPlug_Seek(ModPlugFile* file, int millisecond) -{ - int maxpos; - int maxtime = file->mSoundFile.GetSongTime() * 1000; - float postime; - - if(millisecond > maxtime) - millisecond = maxtime; - maxpos = file->mSoundFile.GetMaxPosition(); - postime = (float)maxpos / (float)maxtime; - - file->mSoundFile.SetCurrentPos((int)(millisecond * postime)); -} - -void ModPlug_GetSettings(ModPlug_Settings* settings) -{ - memcpy(settings, &ModPlug::gSettings, sizeof(ModPlug_Settings)); -} - -void ModPlug_SetSettings(const ModPlug_Settings* settings) -{ - memcpy(&ModPlug::gSettings, settings, sizeof(ModPlug_Settings)); - ModPlug::UpdateSettings(false); // do not update basic config. -} diff --git a/jni/modplug.h b/jni/modplug.h deleted file mode 100644 index 46ea02c..0000000 --- a/jni/modplug.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Kenton Varda (C interface wrapper) - */ - -#ifndef MODPLUG_H__INCLUDED -#define MODPLUG_H__INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -struct _ModPlugFile; -typedef struct _ModPlugFile ModPlugFile; - -struct _ModPlugNote { - unsigned char Note; - unsigned char Instrument; - unsigned char VolumeEffect; - unsigned char Effect; - unsigned char Volume; - unsigned char Parameter; -}; -typedef struct _ModPlugNote ModPlugNote; - -typedef void (*ModPlugMixerProc)(int*, unsigned long, unsigned long); - -/* Load a mod file. [data] should point to a block of memory containing the complete - * file, and [size] should be the size of that block. - * Return the loaded mod file on success, or NULL on failure. */ -ModPlugFile* ModPlug_Load(const void* data, int size); -/* Unload a mod file. */ -void ModPlug_Unload(ModPlugFile* file); - -/* Read sample data into the buffer. Returns the number of bytes read. If the end - * of the mod has been reached, zero is returned. */ -int ModPlug_Read(ModPlugFile* file, void* buffer, int size); - -/* Get the name of the mod. The returned buffer is stored within the ModPlugFile - * structure and will remain valid until you unload the file. */ -const char* ModPlug_GetName(ModPlugFile* file); - -/* Get the length of the mod, in milliseconds. Note that this result is not always - * accurate, especially in the case of mods with loops. */ -int ModPlug_GetLength(ModPlugFile* file); - -/* Seek to a particular position in the song. Note that seeking and MODs don't mix very - * well. Some mods will be missing instruments for a short time after a seek, as ModPlug - * does not scan the sequence backwards to find out which instruments were supposed to be - * playing at that time. (Doing so would be difficult and not very reliable.) Also, - * note that seeking is not very exact in some mods -- especially those for which - * ModPlug_GetLength() does not report the full length. */ -void ModPlug_Seek(ModPlugFile* file, int millisecond); - -enum _ModPlug_Flags -{ - MODPLUG_ENABLE_OVERSAMPLING = 1 << 0, /* Enable oversampling (*highly* recommended) */ - MODPLUG_ENABLE_NOISE_REDUCTION = 1 << 1, /* Enable noise reduction */ - MODPLUG_ENABLE_REVERB = 1 << 2, /* Enable reverb */ - MODPLUG_ENABLE_MEGABASS = 1 << 3, /* Enable megabass */ - MODPLUG_ENABLE_SURROUND = 1 << 4 /* Enable surround sound. */ -}; - -enum _ModPlug_ResamplingMode -{ - MODPLUG_RESAMPLE_NEAREST = 0, /* No interpolation (very fast, extremely bad sound quality) */ - MODPLUG_RESAMPLE_LINEAR = 1, /* Linear interpolation (fast, good quality) */ - MODPLUG_RESAMPLE_SPLINE = 2, /* Cubic spline interpolation (high quality) */ - MODPLUG_RESAMPLE_FIR = 3 /* 8-tap fir filter (extremely high quality) */ -}; - -typedef struct _ModPlug_Settings -{ - int mFlags; /* One or more of the MODPLUG_ENABLE_* flags above, bitwise-OR'ed */ - - /* Note that ModPlug always decodes sound at 44100kHz, 32 bit, stereo and then - * down-mixes to the settings you choose. */ - int mChannels; /* Number of channels - 1 for mono or 2 for stereo */ - int mBits; /* Bits per sample - 8, 16, or 32 */ - int mFrequency; /* Sampling rate - 11025, 22050, or 44100 */ - int mResamplingMode; /* One of MODPLUG_RESAMPLE_*, above */ - - int mStereoSeparation; /* Stereo separation, 1 - 256 */ - int mMaxMixChannels; /* Maximum number of mixing channels (polyphony), 32 - 256 */ - - int mReverbDepth; /* Reverb level 0(quiet)-100(loud) */ - int mReverbDelay; /* Reverb delay in ms, usually 40-200ms */ - int mBassAmount; /* XBass level 0(quiet)-100(loud) */ - int mBassRange; /* XBass cutoff in Hz 10-100 */ - int mSurroundDepth; /* Surround level 0(quiet)-100(heavy) */ - int mSurroundDelay; /* Surround delay in ms, usually 5-40ms */ - int mLoopCount; /* Number of times to loop. Zero prevents looping. - -1 loops forever. */ -} ModPlug_Settings; - -/* Get and set the mod decoder settings. All options, except for channels, bits-per-sample, - * sampling rate, and loop count, will take effect immediately. Those options which don't - * take effect immediately will take effect the next time you load a mod. */ -void ModPlug_GetSettings(ModPlug_Settings* settings); -void ModPlug_SetSettings(const ModPlug_Settings* settings); - -/* New ModPlug API Functions */ -/* NOTE: Master Volume (1-512) */ -unsigned int ModPlug_GetMasterVolume(ModPlugFile* file) ; -void ModPlug_SetMasterVolume(ModPlugFile* file,unsigned int cvol) ; - -int ModPlug_GetCurrentSpeed(ModPlugFile* file); -int ModPlug_GetCurrentTempo(ModPlugFile* file); -int ModPlug_GetCurrentOrder(ModPlugFile* file); -int ModPlug_GetCurrentPattern(ModPlugFile* file); -int ModPlug_GetCurrentRow(ModPlugFile* file); -int ModPlug_GetPlayingChannels(ModPlugFile* file); - -void ModPlug_SeekOrder(ModPlugFile* file,int order); -int ModPlug_GetModuleType(ModPlugFile* file); -char* ModPlug_GetMessage(ModPlugFile* file); - - -#ifndef MODPLUG_NO_FILESAVE -/* - * EXPERIMENTAL Export Functions - */ -/*Export to a Scream Tracker 3 S3M module. EXPERIMENTAL (only works on Little-Endian platforms)*/ -char ModPlug_ExportS3M(ModPlugFile* file, const char* filepath); - -/*Export to a Extended Module (XM). EXPERIMENTAL (only works on Little-Endian platforms)*/ -char ModPlug_ExportXM(ModPlugFile* file, const char* filepath); - -/*Export to a Amiga MOD file. EXPERIMENTAL.*/ -char ModPlug_ExportMOD(ModPlugFile* file, const char* filepath); - -/*Export to a Impulse Tracker IT file. Should work OK in Little-Endian & Big-Endian platforms :-) */ -char ModPlug_ExportIT(ModPlugFile* file, const char* filepath); -#endif // MODPLUG_NO_FILESAVE - -unsigned int ModPlug_NumInstruments(ModPlugFile* file); -unsigned int ModPlug_NumSamples(ModPlugFile* file); -unsigned int ModPlug_NumPatterns(ModPlugFile* file); -unsigned int ModPlug_NumChannels(ModPlugFile* file); -unsigned int ModPlug_SampleName(ModPlugFile* file, unsigned int qual, char* buff); -unsigned int ModPlug_InstrumentName(ModPlugFile* file, unsigned int qual, char* buff); - -/* - * Retrieve pattern note-data - */ -ModPlugNote* ModPlug_GetPattern(ModPlugFile* file, int pattern, unsigned int* numrows); - -/* - * ================= - * Mixer callback - * ================= - * - * Use this callback if you want to 'modify' the mixed data of LibModPlug. - * - * void proc(int* buffer,unsigned long channels,unsigned long nsamples) ; - * - * 'buffer': A buffer of mixed samples - * 'channels': N. of channels in the buffer - * 'nsamples': N. of samples in the buffeer (without taking care of n.channels) - * - * (Samples are signed 32-bit integers) - */ -void ModPlug_InitMixerCallback(ModPlugFile* file,ModPlugMixerProc proc) ; -void ModPlug_UnloadMixerCallback(ModPlugFile* file) ; - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/jni/snd_dsp.cpp b/jni/snd_dsp.cpp deleted file mode 100644 index ab5a305..0000000 --- a/jni/snd_dsp.cpp +++ /dev/null @@ -1,485 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -#include "stdafx.h" -#include "sndfile.h" - -#ifdef MODPLUG_FASTSOUNDLIB -#define MODPLUG_NO_REVERB -#endif - - -// Delayed Surround Filters -#ifndef MODPLUG_FASTSOUNDLIB -#define nDolbyHiFltAttn 6 -#define nDolbyHiFltMask 3 -#define DOLBYATTNROUNDUP 31 -#else -#define nDolbyHiFltAttn 3 -#define nDolbyHiFltMask 3 -#define DOLBYATTNROUNDUP 3 -#endif - -// Bass Expansion -#define XBASS_DELAY 14 // 2.5 ms - -// Buffer Sizes -#define XBASSBUFFERSIZE 64 // 2 ms at 50KHz -#define FILTERBUFFERSIZE 64 // 1.25 ms -#define SURROUNDBUFFERSIZE ((MAX_SAMPLE_RATE * 50) / 1000) -#define REVERBBUFFERSIZE ((MAX_SAMPLE_RATE * 200) / 1000) -#define REVERBBUFFERSIZE2 ((REVERBBUFFERSIZE*13) / 17) -#define REVERBBUFFERSIZE3 ((REVERBBUFFERSIZE*7) / 13) -#define REVERBBUFFERSIZE4 ((REVERBBUFFERSIZE*7) / 19) - - -// DSP Effects: PUBLIC members -UINT CSoundFile::m_nXBassDepth = 6; -UINT CSoundFile::m_nXBassRange = XBASS_DELAY; -UINT CSoundFile::m_nReverbDepth = 1; -UINT CSoundFile::m_nReverbDelay = 100; -UINT CSoundFile::m_nProLogicDepth = 12; -UINT CSoundFile::m_nProLogicDelay = 20; - -//////////////////////////////////////////////////////////////////// -// DSP Effects internal state - -// Bass Expansion: low-pass filter -static LONG nXBassSum = 0; -static LONG nXBassBufferPos = 0; -static LONG nXBassDlyPos = 0; -static LONG nXBassMask = 0; - -// Noise Reduction: simple low-pass filter -static LONG nLeftNR = 0; -static LONG nRightNR = 0; - -// Surround Encoding: 1 delay line + low-pass filter + high-pass filter -static LONG nSurroundSize = 0; -static LONG nSurroundPos = 0; -static LONG nDolbyDepth = 0; -static LONG nDolbyLoDlyPos = 0; -static LONG nDolbyLoFltPos = 0; -static LONG nDolbyLoFltSum = 0; -static LONG nDolbyHiFltPos = 0; -static LONG nDolbyHiFltSum = 0; - -// Reverb: 4 delay lines + high-pass filter + low-pass filter -#ifndef MODPLUG_NO_REVERB -static LONG nReverbSize = 0; -static LONG nReverbBufferPos = 0; -static LONG nReverbSize2 = 0; -static LONG nReverbBufferPos2 = 0; -static LONG nReverbSize3 = 0; -static LONG nReverbBufferPos3 = 0; -static LONG nReverbSize4 = 0; -static LONG nReverbBufferPos4 = 0; -static LONG nReverbLoFltSum = 0; -static LONG nReverbLoFltPos = 0; -static LONG nReverbLoDlyPos = 0; -static LONG nFilterAttn = 0; -static LONG gRvbLowPass[8]; -static LONG gRvbLPPos = 0; -static LONG gRvbLPSum = 0; -static LONG ReverbLoFilterBuffer[XBASSBUFFERSIZE]; -static LONG ReverbLoFilterDelay[XBASSBUFFERSIZE]; -static LONG ReverbBuffer[REVERBBUFFERSIZE]; -static LONG ReverbBuffer2[REVERBBUFFERSIZE2]; -static LONG ReverbBuffer3[REVERBBUFFERSIZE3]; -static LONG ReverbBuffer4[REVERBBUFFERSIZE4]; -#endif -static LONG XBassBuffer[XBASSBUFFERSIZE]; -static LONG XBassDelay[XBASSBUFFERSIZE]; -static LONG DolbyLoFilterBuffer[XBASSBUFFERSIZE]; -static LONG DolbyLoFilterDelay[XBASSBUFFERSIZE]; -static LONG DolbyHiFilterBuffer[FILTERBUFFERSIZE]; -static LONG SurroundBuffer[SURROUNDBUFFERSIZE]; - -// Access the main temporary mix buffer directly: avoids an extra pointer -extern int MixSoundBuffer[MIXBUFFERSIZE*2]; -//cextern int MixReverbBuffer[MIXBUFFERSIZE*2]; -extern int MixReverbBuffer[MIXBUFFERSIZE*2]; - -static UINT GetMaskFromSize(UINT len) -//----------------------------------- -{ - UINT n = 2; - while (n <= len) n <<= 1; - return ((n >> 1) - 1); -} - - -void CSoundFile::InitializeDSP(BOOL bReset) -//----------------------------------------- -{ - if (!m_nReverbDelay) m_nReverbDelay = 100; - if (!m_nXBassRange) m_nXBassRange = XBASS_DELAY; - if (!m_nProLogicDelay) m_nProLogicDelay = 20; - if (m_nXBassDepth > 8) m_nXBassDepth = 8; - if (m_nXBassDepth < 2) m_nXBassDepth = 2; - if (bReset) - { - // Noise Reduction - nLeftNR = nRightNR = 0; - } - // Pro-Logic Surround - nSurroundPos = nSurroundSize = 0; - nDolbyLoFltPos = nDolbyLoFltSum = nDolbyLoDlyPos = 0; - nDolbyHiFltPos = nDolbyHiFltSum = 0; - if (gdwSoundSetup & SNDMIX_SURROUND) - { - memset(DolbyLoFilterBuffer, 0, sizeof(DolbyLoFilterBuffer)); - memset(DolbyHiFilterBuffer, 0, sizeof(DolbyHiFilterBuffer)); - memset(DolbyLoFilterDelay, 0, sizeof(DolbyLoFilterDelay)); - memset(SurroundBuffer, 0, sizeof(SurroundBuffer)); - nSurroundSize = (gdwMixingFreq * m_nProLogicDelay) / 1000; - if (nSurroundSize > SURROUNDBUFFERSIZE) nSurroundSize = SURROUNDBUFFERSIZE; - if (m_nProLogicDepth < 8) nDolbyDepth = (32 >> m_nProLogicDepth) + 32; - else nDolbyDepth = (m_nProLogicDepth < 16) ? (8 + (m_nProLogicDepth - 8) * 7) : 64; - nDolbyDepth >>= 2; - } - // Reverb Setup -#ifndef MODPLUG_NO_REVERB - if (gdwSoundSetup & SNDMIX_REVERB) - { - UINT nrs = (gdwMixingFreq * m_nReverbDelay) / 1000; - UINT nfa = m_nReverbDepth+1; - if (nrs > REVERBBUFFERSIZE) nrs = REVERBBUFFERSIZE; - if ((bReset) || (nrs != (UINT)nReverbSize) || (nfa != (UINT)nFilterAttn)) - { - nFilterAttn = nfa; - nReverbSize = nrs; - nReverbBufferPos = nReverbBufferPos2 = nReverbBufferPos3 = nReverbBufferPos4 = 0; - nReverbLoFltSum = nReverbLoFltPos = nReverbLoDlyPos = 0; - gRvbLPSum = gRvbLPPos = 0; - nReverbSize2 = (nReverbSize * 13) / 17; - if (nReverbSize2 > REVERBBUFFERSIZE2) nReverbSize2 = REVERBBUFFERSIZE2; - nReverbSize3 = (nReverbSize * 7) / 13; - if (nReverbSize3 > REVERBBUFFERSIZE3) nReverbSize3 = REVERBBUFFERSIZE3; - nReverbSize4 = (nReverbSize * 7) / 19; - if (nReverbSize4 > REVERBBUFFERSIZE4) nReverbSize4 = REVERBBUFFERSIZE4; - memset(ReverbLoFilterBuffer, 0, sizeof(ReverbLoFilterBuffer)); - memset(ReverbLoFilterDelay, 0, sizeof(ReverbLoFilterDelay)); - memset(ReverbBuffer, 0, sizeof(ReverbBuffer)); - memset(ReverbBuffer2, 0, sizeof(ReverbBuffer2)); - memset(ReverbBuffer3, 0, sizeof(ReverbBuffer3)); - memset(ReverbBuffer4, 0, sizeof(ReverbBuffer4)); - memset(gRvbLowPass, 0, sizeof(gRvbLowPass)); - } - } else nReverbSize = 0; -#endif - BOOL bResetBass = FALSE; - // Bass Expansion Reset - if (gdwSoundSetup & SNDMIX_MEGABASS) - { - UINT nXBassSamples = (gdwMixingFreq * m_nXBassRange) / 10000; - if (nXBassSamples > XBASSBUFFERSIZE) nXBassSamples = XBASSBUFFERSIZE; - UINT mask = GetMaskFromSize(nXBassSamples); - if ((bReset) || (mask != (UINT)nXBassMask)) - { - nXBassMask = mask; - bResetBass = TRUE; - } - } else - { - nXBassMask = 0; - bResetBass = TRUE; - } - if (bResetBass) - { - nXBassSum = nXBassBufferPos = nXBassDlyPos = 0; - memset(XBassBuffer, 0, sizeof(XBassBuffer)); - memset(XBassDelay, 0, sizeof(XBassDelay)); - } -} - - -void CSoundFile::ProcessStereoDSP(int count) -//------------------------------------------ -{ -#ifndef MODPLUG_NO_REVERB - // Reverb - if (gdwSoundSetup & SNDMIX_REVERB) - { - int *pr = MixSoundBuffer, *pin = MixReverbBuffer, rvbcount = count; - do - { - int echo = ReverbBuffer[nReverbBufferPos] + ReverbBuffer2[nReverbBufferPos2] - + ReverbBuffer3[nReverbBufferPos3] + ReverbBuffer4[nReverbBufferPos4]; // echo = reverb signal - // Delay line and remove Low Frequencies // v = original signal - int echodly = ReverbLoFilterDelay[nReverbLoDlyPos]; // echodly = delayed signal - ReverbLoFilterDelay[nReverbLoDlyPos] = echo >> 1; - nReverbLoDlyPos++; - nReverbLoDlyPos &= 0x1F; - int n = nReverbLoFltPos; - nReverbLoFltSum -= ReverbLoFilterBuffer[n]; - int tmp = echo / 128; - ReverbLoFilterBuffer[n] = tmp; - nReverbLoFltSum += tmp; - echodly -= nReverbLoFltSum; - nReverbLoFltPos = (n + 1) & 0x3F; - // Reverb - int v = (pin[0]+pin[1]) >> nFilterAttn; - pr[0] += pin[0] + echodly; - pr[1] += pin[1] + echodly; - v += echodly >> 2; - ReverbBuffer3[nReverbBufferPos3] = v; - ReverbBuffer4[nReverbBufferPos4] = v; - v += echodly >> 4; - v >>= 1; - gRvbLPSum -= gRvbLowPass[gRvbLPPos]; - gRvbLPSum += v; - gRvbLowPass[gRvbLPPos] = v; - gRvbLPPos++; - gRvbLPPos &= 7; - int vlp = gRvbLPSum >> 2; - ReverbBuffer[nReverbBufferPos] = vlp; - ReverbBuffer2[nReverbBufferPos2] = vlp; - if (++nReverbBufferPos >= nReverbSize) nReverbBufferPos = 0; - if (++nReverbBufferPos2 >= nReverbSize2) nReverbBufferPos2 = 0; - if (++nReverbBufferPos3 >= nReverbSize3) nReverbBufferPos3 = 0; - if (++nReverbBufferPos4 >= nReverbSize4) nReverbBufferPos4 = 0; - pr += 2; - pin += 2; - } while (--rvbcount); - } -#endif - // Dolby Pro-Logic Surround - if (gdwSoundSetup & SNDMIX_SURROUND) - { - int *pr = MixSoundBuffer, n = nDolbyLoFltPos; - for (int r=count; r; r--) - { - int v = (pr[0]+pr[1]+DOLBYATTNROUNDUP) >> (nDolbyHiFltAttn+1); -#ifndef MODPLUG_FASTSOUNDLIB - v *= (int)nDolbyDepth; -#endif - // Low-Pass Filter - nDolbyHiFltSum -= DolbyHiFilterBuffer[nDolbyHiFltPos]; - DolbyHiFilterBuffer[nDolbyHiFltPos] = v; - nDolbyHiFltSum += v; - v = nDolbyHiFltSum; - nDolbyHiFltPos++; - nDolbyHiFltPos &= nDolbyHiFltMask; - // Surround - int secho = SurroundBuffer[nSurroundPos]; - SurroundBuffer[nSurroundPos] = v; - // Delay line and remove low frequencies - v = DolbyLoFilterDelay[nDolbyLoDlyPos]; // v = delayed signal - DolbyLoFilterDelay[nDolbyLoDlyPos] = secho; // secho = signal - nDolbyLoDlyPos++; - nDolbyLoDlyPos &= 0x1F; - nDolbyLoFltSum -= DolbyLoFilterBuffer[n]; - int tmp = secho / 64; - DolbyLoFilterBuffer[n] = tmp; - nDolbyLoFltSum += tmp; - v -= nDolbyLoFltSum; - n++; - n &= 0x3F; - // Add echo - pr[0] += v; - pr[1] -= v; - if (++nSurroundPos >= nSurroundSize) nSurroundPos = 0; - pr += 2; - } - nDolbyLoFltPos = n; - } - // Bass Expansion - if (gdwSoundSetup & SNDMIX_MEGABASS) - { - int *px = MixSoundBuffer; - int xba = m_nXBassDepth+1, xbamask = (1 << xba) - 1; - int n = nXBassBufferPos; - for (int x=count; x; x--) - { - nXBassSum -= XBassBuffer[n]; - int tmp0 = px[0] + px[1]; - int tmp = (tmp0 + ((tmp0 >> 31) & xbamask)) >> xba; - XBassBuffer[n] = tmp; - nXBassSum += tmp; - int v = XBassDelay[nXBassDlyPos]; - XBassDelay[nXBassDlyPos] = px[0]; - px[0] = v + nXBassSum; - v = XBassDelay[nXBassDlyPos+1]; - XBassDelay[nXBassDlyPos+1] = px[1]; - px[1] = v + nXBassSum; - nXBassDlyPos = (nXBassDlyPos + 2) & nXBassMask; - px += 2; - n++; - n &= nXBassMask; - } - nXBassBufferPos = n; - } - // Noise Reduction - if (gdwSoundSetup & SNDMIX_NOISEREDUCTION) - { - int n1 = nLeftNR, n2 = nRightNR; - int *pnr = MixSoundBuffer; - for (int nr=count; nr; nr--) - { - int vnr = pnr[0] >> 1; - pnr[0] = vnr + n1; - n1 = vnr; - vnr = pnr[1] >> 1; - pnr[1] = vnr + n2; - n2 = vnr; - pnr += 2; - } - nLeftNR = n1; - nRightNR = n2; - } -} - - -void CSoundFile::ProcessMonoDSP(int count) -//---------------------------------------- -{ -#ifndef MODPLUG_NO_REVERB - // Reverb - if (gdwSoundSetup & SNDMIX_REVERB) - { - int *pr = MixSoundBuffer, rvbcount = count, *pin = MixReverbBuffer; - do - { - int echo = ReverbBuffer[nReverbBufferPos] + ReverbBuffer2[nReverbBufferPos2] - + ReverbBuffer3[nReverbBufferPos3] + ReverbBuffer4[nReverbBufferPos4]; // echo = reverb signal - // Delay line and remove Low Frequencies // v = original signal - int echodly = ReverbLoFilterDelay[nReverbLoDlyPos]; // echodly = delayed signal - ReverbLoFilterDelay[nReverbLoDlyPos] = echo >> 1; - nReverbLoDlyPos++; - nReverbLoDlyPos &= 0x1F; - int n = nReverbLoFltPos; - nReverbLoFltSum -= ReverbLoFilterBuffer[n]; - int tmp = echo / 128; - ReverbLoFilterBuffer[n] = tmp; - nReverbLoFltSum += tmp; - echodly -= nReverbLoFltSum; - nReverbLoFltPos = (n + 1) & 0x3F; - // Reverb - int v = pin[0] >> (nFilterAttn-1); - *pr++ += pin[0] + echodly; - pin++; - v += echodly >> 2; - ReverbBuffer3[nReverbBufferPos3] = v; - ReverbBuffer4[nReverbBufferPos4] = v; - v += echodly >> 4; - v >>= 1; - gRvbLPSum -= gRvbLowPass[gRvbLPPos]; - gRvbLPSum += v; - gRvbLowPass[gRvbLPPos] = v; - gRvbLPPos++; - gRvbLPPos &= 7; - int vlp = gRvbLPSum >> 2; - ReverbBuffer[nReverbBufferPos] = vlp; - ReverbBuffer2[nReverbBufferPos2] = vlp; - if (++nReverbBufferPos >= nReverbSize) nReverbBufferPos = 0; - if (++nReverbBufferPos2 >= nReverbSize2) nReverbBufferPos2 = 0; - if (++nReverbBufferPos3 >= nReverbSize3) nReverbBufferPos3 = 0; - if (++nReverbBufferPos4 >= nReverbSize4) nReverbBufferPos4 = 0; - } while (--rvbcount); - } -#endif - // Bass Expansion - if (gdwSoundSetup & SNDMIX_MEGABASS) - { - int *px = MixSoundBuffer; - int xba = m_nXBassDepth, xbamask = (1 << xba)-1; - int n = nXBassBufferPos; - for (int x=count; x; x--) - { - nXBassSum -= XBassBuffer[n]; - int tmp0 = *px; - int tmp = (tmp0 + ((tmp0 >> 31) & xbamask)) >> xba; - XBassBuffer[n] = tmp; - nXBassSum += tmp; - int v = XBassDelay[nXBassDlyPos]; - XBassDelay[nXBassDlyPos] = *px; - *px++ = v + nXBassSum; - nXBassDlyPos = (nXBassDlyPos + 2) & nXBassMask; - n++; - n &= nXBassMask; - } - nXBassBufferPos = n; - } - // Noise Reduction - if (gdwSoundSetup & SNDMIX_NOISEREDUCTION) - { - int n = nLeftNR; - int *pnr = MixSoundBuffer; - for (int nr=count; nr; pnr++, nr--) - { - int vnr = *pnr >> 1; - *pnr = vnr + n; - n = vnr; - } - nLeftNR = n; - } -} - - -///////////////////////////////////////////////////////////////// -// Clean DSP Effects interface - -// [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms] -BOOL CSoundFile::SetReverbParameters(UINT nDepth, UINT nDelay) -//------------------------------------------------------------ -{ - if (nDepth > 100) nDepth = 100; - UINT gain = nDepth / 20; - if (gain > 4) gain = 4; - m_nReverbDepth = 4 - gain; - if (nDelay < 40) nDelay = 40; - if (nDelay > 250) nDelay = 250; - m_nReverbDelay = nDelay; - return TRUE; -} - - -// [XBass level 0(quiet)-100(loud)], [cutoff in Hz 20-100] -BOOL CSoundFile::SetXBassParameters(UINT nDepth, UINT nRange) -//----------------------------------------------------------- -{ - if (nDepth > 100) nDepth = 100; - UINT gain = nDepth / 20; - if (gain > 4) gain = 4; - m_nXBassDepth = 8 - gain; // filter attenuation 1/256 .. 1/16 - UINT range = nRange / 5; - if (range > 5) range -= 5; else range = 0; - if (nRange > 16) nRange = 16; - m_nXBassRange = 21 - range; // filter average on 0.5-1.6ms - return TRUE; -} - - -// [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-50ms] -BOOL CSoundFile::SetSurroundParameters(UINT nDepth, UINT nDelay) -//-------------------------------------------------------------- -{ - UINT gain = (nDepth * 16) / 100; - if (gain > 16) gain = 16; - if (gain < 1) gain = 1; - m_nProLogicDepth = gain; - if (nDelay < 4) nDelay = 4; - if (nDelay > 50) nDelay = 50; - m_nProLogicDelay = nDelay; - return TRUE; -} - -BOOL CSoundFile::SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ) -//---------------------------------------------------------------------------------------------------------------------------- -{ - DWORD d = gdwSoundSetup & ~(SNDMIX_SURROUND | SNDMIX_NORESAMPLING | SNDMIX_REVERB | SNDMIX_HQRESAMPLER | SNDMIX_MEGABASS | SNDMIX_NOISEREDUCTION | SNDMIX_EQ); - if (bSurround) d |= SNDMIX_SURROUND; - if (bNoOverSampling) d |= SNDMIX_NORESAMPLING; - if (bReverb) d |= SNDMIX_REVERB; - if (hqido) d |= SNDMIX_HQRESAMPLER; - if (bMegaBass) d |= SNDMIX_MEGABASS; - if (bNR) d |= SNDMIX_NOISEREDUCTION; - if (bEQ) d |= SNDMIX_EQ; - gdwSoundSetup = d; - InitPlayer(FALSE); - return TRUE; -} diff --git a/jni/snd_flt.cpp b/jni/snd_flt.cpp deleted file mode 100644 index f8a573c..0000000 --- a/jni/snd_flt.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -#include "stdafx.h" -#include "sndfile.h" - -// AWE32: cutoff = reg[0-255] * 31.25 + 100 -> [100Hz-8060Hz] -// EMU10K1 docs: cutoff = reg[0-127]*62+100 -#define FILTER_PRECISION 8192 - -#ifndef NO_FILTER - -#ifdef MSC_VER -#define _ASM_MATH -#endif - -#ifdef _ASM_MATH - -// pow(a,b) returns a^^b -> 2^^(b.log2(a)) -static float pow(float a, float b) -{ - long tmpint; - float result; - _asm { - fld b // Load b - fld a // Load a - fyl2x // ST(0) = b.log2(a) - fist tmpint // Store integer exponent - fisub tmpint // ST(0) = -1 <= (b*log2(a)) <= 1 - f2xm1 // ST(0) = 2^(x)-1 - fild tmpint // load integer exponent - fld1 // Load 1 - fscale // ST(0) = 2^ST(1) - fstp ST(1) // Remove the integer from the stack - fmul ST(1), ST(0) // multiply with fractional part - faddp ST(1), ST(0) // add integer_part - fstp result // Store the result - } - return result; -} - - -#else - -#include - -#endif // _ASM_MATH - - -DWORD CSoundFile::CutOffToFrequency(UINT nCutOff, int flt_modifier) const -//----------------------------------------------------------------------- -{ - float Fc; - - if (m_dwSongFlags & SONG_EXFILTERRANGE) - Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(21.0f*512.0f)); - else - Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(24.0f*512.0f)); - LONG freq = (LONG)Fc; - if (freq < 120) return 120; - if (freq > 10000) return 10000; - if (freq*2 > (LONG)gdwMixingFreq) freq = gdwMixingFreq>>1; - return (DWORD)freq; -} - - -// Simple 2-poles resonant filter -void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier) const -//---------------------------------------------------------------------------------------- -{ - float fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier); - float fs = (float)gdwMixingFreq; - float fg, fb0, fb1; - - fc *= (float)(2.0*3.14159265358/fs); - float dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)pChn->nResonance) / 20.0f); - float d = (1.0f-2.0f*dmpfac)* fc; - if (d>2.0) d = 2.0; - d = (2.0f*dmpfac - d)/fc; - float e = pow(1.0f/fc,2.0f); - - fg=1/(1+d+e); - fb0=(d+e+e)/(1+d+e); - fb1=-e/(1+d+e); - - pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION); - pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION); - pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION); - - if (bReset) - { - pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0; - pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0; - } - pChn->dwFlags |= CHN_FILTER; -} - -#endif // NO_FILTER diff --git a/jni/snd_fx.cpp b/jni/snd_fx.cpp deleted file mode 100644 index af52455..0000000 --- a/jni/snd_fx.cpp +++ /dev/null @@ -1,2379 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque -*/ - -#include "stdafx.h" -#include -#include "sndfile.h" -#include "tables.h" - -#ifdef MSC_VER -#pragma warning(disable:4244) -#endif - -//////////////////////////////////////////////////////////// -// Length - -DWORD CSoundFile::GetLength(BOOL bAdjust, BOOL bTotal) -//---------------------------------------------------- -{ - UINT dwElapsedTime=0, nRow=0, nCurrentPattern=0, nNextPattern=0, nPattern=Order[0]; - UINT nMusicSpeed=m_nDefaultSpeed, nMusicTempo=m_nDefaultTempo, nNextRow=0; - UINT nMaxRow = 0, nMaxPattern = 0; - LONG nGlbVol = m_nDefaultGlobalVolume, nOldGlbVolSlide = 0; - BYTE samples[MAX_CHANNELS]; - BYTE instr[MAX_CHANNELS]; - BYTE notes[MAX_CHANNELS]; - BYTE vols[MAX_CHANNELS]; - BYTE oldparam[MAX_CHANNELS]; - BYTE chnvols[MAX_CHANNELS]; - DWORD patloop[MAX_CHANNELS]; - - memset(instr, 0, sizeof(instr)); - memset(notes, 0, sizeof(notes)); - memset(vols, 0xFF, sizeof(vols)); - memset(patloop, 0, sizeof(patloop)); - memset(oldparam, 0, sizeof(oldparam)); - memset(chnvols, 64, sizeof(chnvols)); - memset(samples, 0, sizeof(samples)); - for (UINT icv=0; icv= MAX_PATTERNS) - { - // End of song ? - if ((nPattern == 0xFF) || (nCurrentPattern >= MAX_ORDERS)) - { - goto EndMod; - } else - { - nCurrentPattern++; - nPattern = (nCurrentPattern < MAX_ORDERS) ? Order[nCurrentPattern] : 0xFF; - } - nNextPattern = nCurrentPattern; - } - // Weird stuff? - if ((nPattern >= MAX_PATTERNS) || (!Patterns[nPattern])) break; - // Should never happen - if (nRow >= PatternSize[nPattern]) nRow = 0; - // Update next position - nNextRow = nRow + 1; - if (nNextRow >= PatternSize[nPattern]) - { - nNextPattern = nCurrentPattern + 1; - nNextRow = 0; - } - if (!nRow) - { - for (UINT ipck=0; ipck nMaxPattern) || ((nCurrentPattern == nMaxPattern) && (nRow >= nMaxRow))) - { - if (bAdjust) - { - m_nMusicSpeed = nMusicSpeed; - m_nMusicTempo = nMusicTempo; - } - break; - } - } - MODCHANNEL *pChn = Chn; - MODCOMMAND *p = Patterns[nPattern] + nRow * m_nChannels; - for (UINT nChn=0; nChncommand; - UINT param = p->param; - UINT note = p->note; - if (p->instr) { instr[nChn] = p->instr; notes[nChn] = 0; vols[nChn] = 0xFF; } - if ((note) && (note <= NOTE_MAX)) notes[nChn] = note; - if (p->volcmd == VOLCMD_VOLUME) { vols[nChn] = p->vol; } - if (command) switch (command) - { - // Position Jump - case CMD_POSITIONJUMP: - if (param <= nCurrentPattern) goto EndMod; - nNextPattern = param; - nNextRow = 0; - if (bAdjust) - { - pChn->nPatternLoopCount = 0; - pChn->nPatternLoop = 0; - } - break; - // Pattern Break - case CMD_PATTERNBREAK: - nNextRow = param; - nNextPattern = nCurrentPattern + 1; - if (bAdjust) - { - pChn->nPatternLoopCount = 0; - pChn->nPatternLoop = 0; - } - break; - // Set Speed - case CMD_SPEED: - if (!param) break; - if ((param <= 0x20) || (m_nType != MOD_TYPE_MOD)) - { - if (param < 128) nMusicSpeed = param; - } - break; - // Set Tempo - case CMD_TEMPO: - if ((bAdjust) && (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) - { - if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo; - } - if (param >= 0x20) nMusicTempo = param; else - // Tempo Slide - if ((param & 0xF0) == 0x10) - { - nMusicTempo += param & 0x0F; - if (nMusicTempo > 255) nMusicTempo = 255; - } else - { - nMusicTempo -= param & 0x0F; - if (nMusicTempo < 32) nMusicTempo = 32; - } - break; - // Pattern Delay - case CMD_S3MCMDEX: - if ((param & 0xF0) == 0x60) { nSpeedCount = param & 0x0F; break; } else - if ((param & 0xF0) == 0xB0) { param &= 0x0F; param |= 0x60; } - case CMD_MODCMDEX: - if ((param & 0xF0) == 0xE0) nSpeedCount = (param & 0x0F) * nMusicSpeed; else - if ((param & 0xF0) == 0x60) - { - if (param & 0x0F) dwElapsedTime += (dwElapsedTime - patloop[nChn]) * (param & 0x0F); - else patloop[nChn] = dwElapsedTime; - } - break; - } - if (!bAdjust) continue; - switch(command) - { - // Portamento Up/Down - case CMD_PORTAMENTOUP: - case CMD_PORTAMENTODOWN: - if (param) pChn->nOldPortaUpDown = param; - break; - // Tone-Portamento - case CMD_TONEPORTAMENTO: - if (param) pChn->nPortamentoSlide = param << 2; - break; - // Offset - case CMD_OFFSET: - if (param) pChn->nOldOffset = param; - break; - // Volume Slide - case CMD_VOLUMESLIDE: - case CMD_TONEPORTAVOL: - case CMD_VIBRATOVOL: - if (param) pChn->nOldVolumeSlide = param; - break; - // Set Volume - case CMD_VOLUME: - vols[nChn] = param; - break; - // Global Volume - case CMD_GLOBALVOLUME: - if (!(m_nType & (MOD_TYPE_IT))) param <<= 1; - if (param > 128) param = 128; - nGlbVol = param << 1; - break; - // Global Volume Slide - case CMD_GLOBALVOLSLIDE: - if (param) nOldGlbVolSlide = param; else param = nOldGlbVolSlide; - if (((param & 0x0F) == 0x0F) && (param & 0xF0)) - { - param >>= 4; - if (m_nType != MOD_TYPE_IT) param <<= 1; - nGlbVol += param << 1; - } else - if (((param & 0xF0) == 0xF0) && (param & 0x0F)) - { - param = (param & 0x0F) << 1; - if (m_nType != MOD_TYPE_IT) param <<= 1; - nGlbVol -= param; - } else - if (param & 0xF0) - { - param >>= 4; - param <<= 1; - if (m_nType != MOD_TYPE_IT) param <<= 1; - nGlbVol += param * nMusicSpeed; - } else - { - param = (param & 0x0F) << 1; - if (m_nType != MOD_TYPE_IT) param <<= 1; - nGlbVol -= param * nMusicSpeed; - } - if (nGlbVol < 0) nGlbVol = 0; - if (nGlbVol > 256) nGlbVol = 256; - break; - case CMD_CHANNELVOLUME: - if (param <= 64) chnvols[nChn] = param; - break; - case CMD_CHANNELVOLSLIDE: - if (param) oldparam[nChn] = param; else param = oldparam[nChn]; - pChn->nOldChnVolSlide = param; - if (((param & 0x0F) == 0x0F) && (param & 0xF0)) - { - param = (param >> 4) + chnvols[nChn]; - } else - if (((param & 0xF0) == 0xF0) && (param & 0x0F)) - { - if (chnvols[nChn] > (int)(param & 0x0F)) param = chnvols[nChn] - (param & 0x0F); - else param = 0; - } else - if (param & 0x0F) - { - param = (param & 0x0F) * nMusicSpeed; - param = (chnvols[nChn] > param) ? chnvols[nChn] - param : 0; - } else param = ((param & 0xF0) >> 4) * nMusicSpeed + chnvols[nChn]; - if (param > 64) param = 64; - chnvols[nChn] = param; - break; - } - } - nSpeedCount += nMusicSpeed; - dwElapsedTime += (2500 * nSpeedCount) / nMusicTempo; - } -EndMod: - if ((bAdjust) && (!bTotal)) - { - m_nGlobalVolume = nGlbVol; - m_nOldGlbVolSlide = nOldGlbVolSlide; - for (UINT n=0; n 64) vols[n] = 64; - Chn[n].nVolume = vols[n] << 2; - } - } - } - return (dwElapsedTime+500) / 1000; -} - - -////////////////////////////////////////////////////////////////////////////////////////////////// -// Effects - -void CSoundFile::InstrumentChange(MODCHANNEL *pChn, UINT instr, BOOL bPorta, BOOL bUpdVol, BOOL bResetEnv) -//-------------------------------------------------------------------------------------------------------- -{ - BOOL bInstrumentChanged = FALSE; - - if (instr >= MAX_INSTRUMENTS) return; - INSTRUMENTHEADER *penv = Headers[instr]; - MODINSTRUMENT *psmp = &Ins[instr]; - UINT note = pChn->nNewNote; - if ((penv) && (note) && (note <= 128)) - { - if (penv->NoteMap[note-1] >= 0xFE) return; - UINT n = penv->Keyboard[note-1]; - psmp = ((n) && (n < MAX_SAMPLES)) ? &Ins[n] : NULL; - } else - if (m_nInstruments) - { - if (note >= 0xFE) return; - psmp = NULL; - } - // Update Volume - if (bUpdVol) pChn->nVolume = (psmp) ? psmp->nVolume : 0; - // bInstrumentChanged is used for IT carry-on env option - if (penv != pChn->pHeader) - { - bInstrumentChanged = TRUE; - pChn->pHeader = penv; - } else - { - // Special XM hack - if ((bPorta) && (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) && (penv) - && (pChn->pInstrument) && (psmp != pChn->pInstrument)) - { - // FT2 doesn't change the sample in this case, - // but still uses the sample info from the old one (bug?) - return; - } - } - // Instrument adjust - pChn->nNewIns = 0; - if (psmp) - { - if (penv) - { - pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 6; - if (penv->dwFlags & ENV_SETPANNING) pChn->nPan = penv->nPan; - pChn->nNNA = penv->nNNA; - } else - { - pChn->nInsVol = psmp->nGlobalVol; - } - if (psmp->uFlags & CHN_PANNING) pChn->nPan = psmp->nPan; - } - // Reset envelopes - if (bResetEnv) - { - if ((!bPorta) || (!(m_nType & MOD_TYPE_IT)) || (m_dwSongFlags & SONG_ITCOMPATMODE) - || (!pChn->nLength) || ((pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol))) - { - pChn->dwFlags |= CHN_FASTVOLRAMP; - if ((m_nType & MOD_TYPE_IT) && (!bInstrumentChanged) && (penv) && (!(pChn->dwFlags & (CHN_KEYOFF|CHN_NOTEFADE)))) - { - if (!(penv->dwFlags & ENV_VOLCARRY)) pChn->nVolEnvPosition = 0; - if (!(penv->dwFlags & ENV_PANCARRY)) pChn->nPanEnvPosition = 0; - if (!(penv->dwFlags & ENV_PITCHCARRY)) pChn->nPitchEnvPosition = 0; - } else - { - pChn->nVolEnvPosition = 0; - pChn->nPanEnvPosition = 0; - pChn->nPitchEnvPosition = 0; - } - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - } else - if ((penv) && (!(penv->dwFlags & ENV_VOLUME))) - { - pChn->nVolEnvPosition = 0; - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - } - } - // Invalid sample ? - if (!psmp) - { - pChn->pInstrument = NULL; - pChn->nInsVol = 0; - return; - } - // Tone-Portamento doesn't reset the pingpong direction flag - if ((bPorta) && (psmp == pChn->pInstrument)) - { - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) return; - pChn->dwFlags &= ~(CHN_KEYOFF|CHN_NOTEFADE); - pChn->dwFlags = (pChn->dwFlags & (0xFFFFFF00 | CHN_PINGPONGFLAG)) | (psmp->uFlags); - } else - { - pChn->dwFlags &= ~(CHN_KEYOFF|CHN_NOTEFADE|CHN_VOLENV|CHN_PANENV|CHN_PITCHENV); - pChn->dwFlags = (pChn->dwFlags & 0xFFFFFF00) | (psmp->uFlags); - if (penv) - { - if (penv->dwFlags & ENV_VOLUME) pChn->dwFlags |= CHN_VOLENV; - if (penv->dwFlags & ENV_PANNING) pChn->dwFlags |= CHN_PANENV; - if (penv->dwFlags & ENV_PITCH) pChn->dwFlags |= CHN_PITCHENV; - if ((penv->dwFlags & ENV_PITCH) && (penv->dwFlags & ENV_FILTER)) - { - if (!pChn->nCutOff) pChn->nCutOff = 0x7F; - } - if (penv->nIFC & 0x80) pChn->nCutOff = penv->nIFC & 0x7F; - if (penv->nIFR & 0x80) pChn->nResonance = penv->nIFR & 0x7F; - } - pChn->nVolSwing = pChn->nPanSwing = 0; - } - pChn->pInstrument = psmp; - pChn->nLength = psmp->nLength; - pChn->nLoopStart = psmp->nLoopStart; - pChn->nLoopEnd = psmp->nLoopEnd; - pChn->nC4Speed = psmp->nC4Speed; - pChn->pSample = psmp->pSample; - pChn->nTranspose = psmp->RelativeTone; - pChn->nFineTune = psmp->nFineTune; - if (pChn->dwFlags & CHN_SUSTAINLOOP) - { - pChn->nLoopStart = psmp->nSustainStart; - pChn->nLoopEnd = psmp->nSustainEnd; - pChn->dwFlags |= CHN_LOOP; - if (pChn->dwFlags & CHN_PINGPONGSUSTAIN) pChn->dwFlags |= CHN_PINGPONGLOOP; - } - if ((pChn->dwFlags & CHN_LOOP) && (pChn->nLoopEnd < pChn->nLength)) pChn->nLength = pChn->nLoopEnd; -} - - -void CSoundFile::NoteChange(UINT nChn, int note, BOOL bPorta, BOOL bResetEnv) -//--------------------------------------------------------------------------- -{ - if (note < 1) return; - MODCHANNEL * const pChn = &Chn[nChn]; - MODINSTRUMENT *pins = pChn->pInstrument; - INSTRUMENTHEADER *penv = pChn->pHeader; - if ((penv) && (note <= 0x80)) - { - UINT n = penv->Keyboard[note - 1]; - if ((n) && (n < MAX_SAMPLES)) pins = &Ins[n]; - note = penv->NoteMap[note-1]; - } - // Key Off - if (note >= 0x80) // 0xFE or invalid note => key off - { - // Key Off - KeyOff(nChn); - // Note Cut - if (note == 0xFE) - { - pChn->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP); - if ((!(m_nType & MOD_TYPE_IT)) || (m_nInstruments)) pChn->nVolume = 0; - pChn->nFadeOutVol = 0; - } - return; - } - if (!pins) return; - if ((!bPorta) && (m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MT2))) - { - pChn->nTranspose = pins->RelativeTone; - pChn->nFineTune = pins->nFineTune; - } - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2|MOD_TYPE_MED)) note += pChn->nTranspose; - if (note < 1) note = 1; - if (note > 132) note = 132; - pChn->nNote = note; - if ((!bPorta) || (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) pChn->nNewIns = 0; - UINT period = GetPeriodFromNote(note, pChn->nFineTune, pChn->nC4Speed); - if (period) - { - if ((!bPorta) || (!pChn->nPeriod)) pChn->nPeriod = period; - pChn->nPortamentoDest = period; - if ((!bPorta) || ((!pChn->nLength) && (!(m_nType & MOD_TYPE_S3M)))) - { - pChn->pInstrument = pins; - pChn->pSample = pins->pSample; - pChn->nLength = pins->nLength; - pChn->nLoopEnd = pins->nLength; - pChn->nLoopStart = 0; - pChn->dwFlags = (pChn->dwFlags & 0xFFFFFF00) | (pins->uFlags); - if (pChn->dwFlags & CHN_SUSTAINLOOP) - { - pChn->nLoopStart = pins->nSustainStart; - pChn->nLoopEnd = pins->nSustainEnd; - pChn->dwFlags &= ~CHN_PINGPONGLOOP; - pChn->dwFlags |= CHN_LOOP; - if (pChn->dwFlags & CHN_PINGPONGSUSTAIN) pChn->dwFlags |= CHN_PINGPONGLOOP; - if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd; - } else - if (pChn->dwFlags & CHN_LOOP) - { - pChn->nLoopStart = pins->nLoopStart; - pChn->nLoopEnd = pins->nLoopEnd; - if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd; - } - pChn->nPos = 0; - pChn->nPosLo = 0; - if (pChn->nVibratoType < 4) pChn->nVibratoPos = ((m_nType & MOD_TYPE_IT) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))) ? 0x10 : 0; - if (pChn->nTremoloType < 4) pChn->nTremoloPos = 0; - } - if (pChn->nPos >= pChn->nLength) pChn->nPos = pChn->nLoopStart; - } else bPorta = FALSE; - if ((!bPorta) || (!(m_nType & MOD_TYPE_IT)) - || ((pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol)) - || ((m_dwSongFlags & SONG_ITCOMPATMODE) && (pChn->nRowInstr))) - { - if ((m_nType & MOD_TYPE_IT) && (pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol)) - { - pChn->nVolEnvPosition = 0; - pChn->nPanEnvPosition = 0; - pChn->nPitchEnvPosition = 0; - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - pChn->dwFlags &= ~CHN_NOTEFADE; - pChn->nFadeOutVol = 65536; - } - if ((!bPorta) || (!(m_dwSongFlags & SONG_ITCOMPATMODE)) || (pChn->nRowInstr)) - { - if ((!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) || (pChn->nRowInstr)) - { - pChn->dwFlags &= ~CHN_NOTEFADE; - pChn->nFadeOutVol = 65536; - } - } - } - pChn->dwFlags &= ~(CHN_EXTRALOUD|CHN_KEYOFF); - // Enable Ramping - if (!bPorta) - { - pChn->nVUMeter = 0x100; - pChn->nLeftVU = pChn->nRightVU = 0xFF; - pChn->dwFlags &= ~CHN_FILTER; - pChn->dwFlags |= CHN_FASTVOLRAMP; - pChn->nRetrigCount = 0; - pChn->nTremorCount = 0; - if (bResetEnv) - { - pChn->nVolSwing = pChn->nPanSwing = 0; - if (penv) - { - if (!(penv->dwFlags & ENV_VOLCARRY)) pChn->nVolEnvPosition = 0; - if (!(penv->dwFlags & ENV_PANCARRY)) pChn->nPanEnvPosition = 0; - if (!(penv->dwFlags & ENV_PITCHCARRY)) pChn->nPitchEnvPosition = 0; - if (m_nType & MOD_TYPE_IT) - { - // Volume Swing - if (penv->nVolSwing) - { - int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128; - pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/128); - } - // Pan Swing - if (penv->nPanSwing) - { - int d = ((LONG)penv->nPanSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128; - pChn->nPanSwing = (signed short)d; - } - } - } - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - } - pChn->nLeftVol = pChn->nRightVol = 0; - BOOL bFlt = (m_dwSongFlags & SONG_MPTFILTERMODE) ? FALSE : TRUE; - // Setup Initial Filter for this note - if (penv) - { - if (penv->nIFR & 0x80) { pChn->nResonance = penv->nIFR & 0x7F; bFlt = TRUE; } - if (penv->nIFC & 0x80) { pChn->nCutOff = penv->nIFC & 0x7F; bFlt = TRUE; } - } else - { - pChn->nVolSwing = pChn->nPanSwing = 0; - } -#ifndef NO_FILTER - if ((pChn->nCutOff < 0x7F) && (bFlt)) SetupChannelFilter(pChn, TRUE); -#endif // NO_FILTER - } -} - - -UINT CSoundFile::GetNNAChannel(UINT nChn) const -//--------------------------------------------- -{ - const MODCHANNEL *pChn = &Chn[nChn]; - // Check for empty channel - const MODCHANNEL *pi = &Chn[m_nChannels]; - for (UINT i=m_nChannels; inLength) return i; - if (!pChn->nFadeOutVol) return 0; - // All channels are used: check for lowest volume - UINT result = 0; - DWORD vol = 64*65536; // 25% - DWORD envpos = 0xFFFFFF; - const MODCHANNEL *pj = &Chn[m_nChannels]; - for (UINT j=m_nChannels; jnFadeOutVol) return j; - DWORD v = pj->nVolume; - if (pj->dwFlags & CHN_NOTEFADE) - v = v * pj->nFadeOutVol; - else - v <<= 16; - if (pj->dwFlags & CHN_LOOP) v >>= 1; - if ((v < vol) || ((v == vol) && (pj->nVolEnvPosition > envpos))) - { - envpos = pj->nVolEnvPosition; - vol = v; - result = j; - } - } - return result; -} - - -void CSoundFile::CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut) -//------------------------------------------------------------------------ -{ - MODCHANNEL *pChn = &Chn[nChn]; - INSTRUMENTHEADER *penv = pChn->pHeader, *pHeader = 0; - signed char *pSample; - if (note > 0x80) note = 0; - if (note < 1) return; - // Always NNA cut - using - if ((!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MT2))) || (!m_nInstruments) || (bForceCut)) - { - if ((m_dwSongFlags & SONG_CPUVERYHIGH) - || (!pChn->nLength) || (pChn->dwFlags & CHN_MUTE) - || ((!pChn->nLeftVol) && (!pChn->nRightVol))) return; - UINT n = GetNNAChannel(nChn); - if (!n) return; - MODCHANNEL *p = &Chn[n]; - // Copy Channel - *p = *pChn; - p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO); - p->nMasterChn = nChn+1; - p->nCommand = 0; - // Cut the note - p->nFadeOutVol = 0; - p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP); - // Stop this channel - pChn->nLength = pChn->nPos = pChn->nPosLo = 0; - pChn->nROfs = pChn->nLOfs = 0; - pChn->nLeftVol = pChn->nRightVol = 0; - return; - } - if (instr >= MAX_INSTRUMENTS) instr = 0; - pSample = pChn->pSample; - pHeader = pChn->pHeader; - if ((instr) && (note)) - { - pHeader = Headers[instr]; - if (pHeader) - { - UINT n = 0; - if (note <= 0x80) - { - n = pHeader->Keyboard[note-1]; - note = pHeader->NoteMap[note-1]; - if ((n) && (n < MAX_SAMPLES)) pSample = Ins[n].pSample; - } - } else pSample = NULL; - } - if (!penv) return; - MODCHANNEL *p = pChn; - for (UINT i=nChn; i= m_nChannels) || (p == pChn)) - { - if (((p->nMasterChn == nChn+1) || (p == pChn)) && (p->pHeader)) - { - BOOL bOk = FALSE; - // Duplicate Check Type - switch(p->pHeader->nDCT) - { - // Note - case DCT_NOTE: - if ((note) && (p->nNote == note) && (pHeader == p->pHeader)) bOk = TRUE; - break; - // Sample - case DCT_SAMPLE: - if ((pSample) && (pSample == p->pSample)) bOk = TRUE; - break; - // Instrument - case DCT_INSTRUMENT: - if (pHeader == p->pHeader) bOk = TRUE; - break; - } - // Duplicate Note Action - if (bOk) - { - switch(p->pHeader->nDNA) - { - // Cut - case DNA_NOTECUT: - KeyOff(i); - p->nVolume = 0; - break; - // Note Off - case DNA_NOTEOFF: - KeyOff(i); - break; - // Note Fade - case DNA_NOTEFADE: - p->dwFlags |= CHN_NOTEFADE; - break; - } - if (!p->nVolume) - { - p->nFadeOutVol = 0; - p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP); - } - } - } - } - if (pChn->dwFlags & CHN_MUTE) return; - // New Note Action - if ((pChn->nVolume) && (pChn->nLength)) - { - UINT n = GetNNAChannel(nChn); - if (n) - { - MODCHANNEL *p = &Chn[n]; - // Copy Channel - *p = *pChn; - p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO); - p->nMasterChn = nChn+1; - p->nCommand = 0; - // Key Off the note - switch(pChn->nNNA) - { - case NNA_NOTEOFF: KeyOff(n); break; - case NNA_NOTECUT: - p->nFadeOutVol = 0; - case NNA_NOTEFADE: p->dwFlags |= CHN_NOTEFADE; break; - } - if (!p->nVolume) - { - p->nFadeOutVol = 0; - p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP); - } - // Stop this channel - pChn->nLength = pChn->nPos = pChn->nPosLo = 0; - pChn->nROfs = pChn->nLOfs = 0; - } - } -} - - -BOOL CSoundFile::ProcessEffects() -//------------------------------- -{ - MODCHANNEL *pChn = Chn; - int nBreakRow = -1, nPosJump = -1, nPatLoopRow = -1; - - for (UINT nChn=0; nChnnRowInstr; - UINT volcmd = pChn->nRowVolCmd; - UINT vol = pChn->nRowVolume; - UINT cmd = pChn->nRowCommand; - UINT param = pChn->nRowParam; - bool bPorta = ((cmd != CMD_TONEPORTAMENTO) && (cmd != CMD_TONEPORTAVOL) && (volcmd != VOLCMD_TONEPORTAMENTO)) ? FALSE : TRUE; - UINT nStartTick = 0; - - pChn->dwFlags &= ~CHN_FASTVOLRAMP; - // Process special effects (note delay, pattern delay, pattern loop) - if ((cmd == CMD_MODCMDEX) || (cmd == CMD_S3MCMDEX)) - { - if ((!param) && (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) param = pChn->nOldCmdEx; else pChn->nOldCmdEx = param; - // Note Delay ? - if ((param & 0xF0) == 0xD0) - { - nStartTick = param & 0x0F; - } else - if (!m_nTickCount) - { - // Pattern Loop ? - if ((((param & 0xF0) == 0x60) && (cmd == CMD_MODCMDEX)) - || (((param & 0xF0) == 0xB0) && (cmd == CMD_S3MCMDEX))) - { - int nloop = PatternLoop(pChn, param & 0x0F); - if (nloop >= 0) nPatLoopRow = nloop; - } else - // Pattern Delay - if ((param & 0xF0) == 0xE0) - { - m_nPatternDelay = param & 0x0F; - } - } - } - - // Handles note/instrument/volume changes - if (m_nTickCount == nStartTick) // can be delayed by a note delay effect - { - UINT note = pChn->nRowNote; - if (instr) pChn->nNewIns = instr; - // XM: Key-Off + Sample == Note Cut - if (m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if ((note == 0xFF) && ((!pChn->pHeader) || (!(pChn->pHeader->dwFlags & ENV_VOLUME)))) - { - pChn->dwFlags |= CHN_FASTVOLRAMP; - pChn->nVolume = 0; - note = instr = 0; - } - } - if ((!note) && (instr)) - { - if (m_nInstruments) - { - if (pChn->pInstrument) pChn->nVolume = pChn->pInstrument->nVolume; - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - pChn->dwFlags |= CHN_FASTVOLRAMP; - pChn->nVolEnvPosition = 0; - pChn->nPanEnvPosition = 0; - pChn->nPitchEnvPosition = 0; - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - pChn->dwFlags &= ~CHN_NOTEFADE; - pChn->nFadeOutVol = 65536; - } - } else - { - if (instr < MAX_SAMPLES) pChn->nVolume = Ins[instr].nVolume; - } - if (!(m_nType & MOD_TYPE_IT)) instr = 0; - } - // Invalid Instrument ? - if (instr >= MAX_INSTRUMENTS) instr = 0; - // Note Cut/Off => ignore instrument - if (note >= 0xFE) instr = 0; - if ((note) && (note <= 128)) pChn->nNewNote = note; - // New Note Action ? - if ((note) && (note <= 128) && (!bPorta)) - { - CheckNNA(nChn, instr, note, FALSE); - } - // Instrument Change ? - if (instr) - { - MODINSTRUMENT *psmp = pChn->pInstrument; - InstrumentChange(pChn, instr, bPorta, TRUE); - pChn->nNewIns = 0; - // Special IT case: portamento+note causes sample change -> ignore portamento - if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) - && (psmp != pChn->pInstrument) && (note) && (note < 0x80)) - { - bPorta = FALSE; - } - } - // New Note ? - if (note) - { - if ((!instr) && (pChn->nNewIns) && (note < 0x80)) - { - InstrumentChange(pChn, pChn->nNewIns, bPorta, FALSE, (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE); - pChn->nNewIns = 0; - } - NoteChange(nChn, note, bPorta, (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE); - if ((bPorta) && (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) && (instr)) - { - pChn->dwFlags |= CHN_FASTVOLRAMP; - pChn->nVolEnvPosition = 0; - pChn->nPanEnvPosition = 0; - pChn->nPitchEnvPosition = 0; - pChn->nAutoVibDepth = 0; - pChn->nAutoVibPos = 0; - } - } - // Tick-0 only volume commands - if (volcmd == VOLCMD_VOLUME) - { - if (vol > 64) vol = 64; - pChn->nVolume = vol << 2; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } else - if (volcmd == VOLCMD_PANNING) - { - if (vol > 64) vol = 64; - pChn->nPan = vol << 2; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } - } - - // Volume Column Effect (except volume & panning) - if ((volcmd > VOLCMD_PANNING) && (m_nTickCount >= nStartTick)) - { - if (volcmd == VOLCMD_TONEPORTAMENTO) - { - if (m_nType & MOD_TYPE_IT) - TonePortamento(pChn, ImpulseTrackerPortaVolCmd[vol & 0x0F]); - else - TonePortamento(pChn, vol * 16); - } else - { - if (vol) pChn->nOldVolParam = vol; else vol = pChn->nOldVolParam; - switch(volcmd) - { - case VOLCMD_VOLSLIDEUP: - VolumeSlide(pChn, vol << 4); - break; - - case VOLCMD_VOLSLIDEDOWN: - VolumeSlide(pChn, vol); - break; - - case VOLCMD_FINEVOLUP: - if (m_nType & MOD_TYPE_IT) - { - if (m_nTickCount == nStartTick) VolumeSlide(pChn, (vol << 4) | 0x0F); - } else - FineVolumeUp(pChn, vol); - break; - - case VOLCMD_FINEVOLDOWN: - if (m_nType & MOD_TYPE_IT) - { - if (m_nTickCount == nStartTick) VolumeSlide(pChn, 0xF0 | vol); - } else - FineVolumeDown(pChn, vol); - break; - - case VOLCMD_VIBRATOSPEED: - Vibrato(pChn, vol << 4); - break; - - case VOLCMD_VIBRATO: - Vibrato(pChn, vol); - break; - - case VOLCMD_PANSLIDELEFT: - PanningSlide(pChn, vol); - break; - - case VOLCMD_PANSLIDERIGHT: - PanningSlide(pChn, vol << 4); - break; - - case VOLCMD_PORTAUP: - PortamentoUp(pChn, vol << 2); - break; - - case VOLCMD_PORTADOWN: - PortamentoDown(pChn, vol << 2); - break; - } - } - } - - // Effects - if (cmd) switch (cmd) - { - // Set Volume - case CMD_VOLUME: - if (!m_nTickCount) - { - pChn->nVolume = (param < 64) ? param*4 : 256; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } - break; - - // Portamento Up - case CMD_PORTAMENTOUP: - if ((!param) && (m_nType & MOD_TYPE_MOD)) break; - PortamentoUp(pChn, param); - break; - - // Portamento Down - case CMD_PORTAMENTODOWN: - if ((!param) && (m_nType & MOD_TYPE_MOD)) break; - PortamentoDown(pChn, param); - break; - - // Volume Slide - case CMD_VOLUMESLIDE: - if ((param) || (m_nType != MOD_TYPE_MOD)) VolumeSlide(pChn, param); - break; - - // Tone-Portamento - case CMD_TONEPORTAMENTO: - TonePortamento(pChn, param); - break; - - // Tone-Portamento + Volume Slide - case CMD_TONEPORTAVOL: - if ((param) || (m_nType != MOD_TYPE_MOD)) VolumeSlide(pChn, param); - TonePortamento(pChn, 0); - break; - - // Vibrato - case CMD_VIBRATO: - Vibrato(pChn, param); - break; - - // Vibrato + Volume Slide - case CMD_VIBRATOVOL: - if ((param) || (m_nType != MOD_TYPE_MOD)) VolumeSlide(pChn, param); - Vibrato(pChn, 0); - break; - - // Set Speed - case CMD_SPEED: - if (!m_nTickCount) SetSpeed(param); - break; - - // Set Tempo - case CMD_TEMPO: - if (!m_nTickCount) - { - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) - { - if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo; - } - SetTempo(param); - } - break; - - // Set Offset - case CMD_OFFSET: - if (m_nTickCount) break; - if (param) pChn->nOldOffset = param; else param = pChn->nOldOffset; - param <<= 8; - param |= (UINT)(pChn->nOldHiOffset) << 16; - if ((pChn->nRowNote) && (pChn->nRowNote < 0x80)) - { - if (bPorta) - pChn->nPos = param; - else - pChn->nPos += param; - if (pChn->nPos >= pChn->nLength) - { - if (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) - { - pChn->nPos = pChn->nLoopStart; - if ((m_dwSongFlags & SONG_ITOLDEFFECTS) && (pChn->nLength > 4)) - { - pChn->nPos = pChn->nLength - 2; - } - } - } - } else - if ((param < pChn->nLength) && (m_nType & (MOD_TYPE_MTM|MOD_TYPE_DMF))) - { - pChn->nPos = param; - } - break; - - // Arpeggio - case CMD_ARPEGGIO: - if ((m_nTickCount) || (!pChn->nPeriod) || (!pChn->nNote)) break; - if ((!param) && (!(m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))) break; - pChn->nCommand = CMD_ARPEGGIO; - if (param) pChn->nArpeggio = param; - break; - - // Retrig - case CMD_RETRIG: - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (!(param & 0xF0)) param |= pChn->nRetrigParam & 0xF0; - if (!(param & 0x0F)) param |= pChn->nRetrigParam & 0x0F; - param |= 0x100; // increment retrig count on first row - } - if (param) pChn->nRetrigParam = (BYTE)(param & 0xFF); else param = pChn->nRetrigParam; - RetrigNote(nChn, param); - break; - - // Tremor - case CMD_TREMOR: - if (m_nTickCount) break; - pChn->nCommand = CMD_TREMOR; - if (param) pChn->nTremorParam = param; - break; - - // Set Global Volume - case CMD_GLOBALVOLUME: - if (m_nTickCount) break; - if (m_nType != MOD_TYPE_IT) param <<= 1; - if (param > 128) param = 128; - m_nGlobalVolume = param << 1; - break; - - // Global Volume Slide - case CMD_GLOBALVOLSLIDE: - GlobalVolSlide(param); - break; - - // Set 8-bit Panning - case CMD_PANNING8: - if (m_nTickCount) break; - if (!(m_dwSongFlags & SONG_SURROUNDPAN)) pChn->dwFlags &= ~CHN_SURROUND; - if (m_nType & (MOD_TYPE_IT|MOD_TYPE_XM|MOD_TYPE_MT2)) - { - pChn->nPan = param; - } else - if (param <= 0x80) - { - pChn->nPan = param << 1; - } else - if (param == 0xA4) - { - pChn->dwFlags |= CHN_SURROUND; - pChn->nPan = 0x80; - } - pChn->dwFlags |= CHN_FASTVOLRAMP; - break; - - // Panning Slide - case CMD_PANNINGSLIDE: - PanningSlide(pChn, param); - break; - - // Tremolo - case CMD_TREMOLO: - Tremolo(pChn, param); - break; - - // Fine Vibrato - case CMD_FINEVIBRATO: - FineVibrato(pChn, param); - break; - - // MOD/XM Exx Extended Commands - case CMD_MODCMDEX: - ExtendedMODCommands(nChn, param); - break; - - // S3M/IT Sxx Extended Commands - case CMD_S3MCMDEX: - ExtendedS3MCommands(nChn, param); - break; - - // Key Off - case CMD_KEYOFF: - if (!m_nTickCount) KeyOff(nChn); - break; - - // Extra-fine porta up/down - case CMD_XFINEPORTAUPDOWN: - switch(param & 0xF0) - { - case 0x10: ExtraFinePortamentoUp(pChn, param & 0x0F); break; - case 0x20: ExtraFinePortamentoDown(pChn, param & 0x0F); break; - // Modplug XM Extensions - case 0x50: - case 0x60: - case 0x70: - case 0x90: - case 0xA0: ExtendedS3MCommands(nChn, param); break; - } - break; - - // Set Channel Global Volume - case CMD_CHANNELVOLUME: - if (m_nTickCount) break; - if (param <= 64) - { - pChn->nGlobalVol = param; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } - break; - - // Channel volume slide - case CMD_CHANNELVOLSLIDE: - ChannelVolSlide(pChn, param); - break; - - // Panbrello (IT) - case CMD_PANBRELLO: - Panbrello(pChn, param); - break; - - // Set Envelope Position - case CMD_SETENVPOSITION: - if (!m_nTickCount) - { - pChn->nVolEnvPosition = param; - pChn->nPanEnvPosition = param; - pChn->nPitchEnvPosition = param; - if (pChn->pHeader) - { - INSTRUMENTHEADER *penv = pChn->pHeader; - if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv) && (param > penv->PanPoints[penv->nPanEnv-1])) - { - pChn->dwFlags &= ~CHN_PANENV; - } - } - } - break; - - // Position Jump - case CMD_POSITIONJUMP: - nPosJump = param; - break; - - // Pattern Break - case CMD_PATTERNBREAK: - nBreakRow = param; - break; - - // Midi Controller - case CMD_MIDI: - if (m_nTickCount) break; - if (param < 0x80){ - ProcessMidiMacro(nChn, &m_MidiCfg.szMidiSFXExt[pChn->nActiveMacro << 5], param); - } else { - ProcessMidiMacro(nChn, &m_MidiCfg.szMidiZXXExt[(param & 0x7F) << 5], 0); - } - break; - } - } - - // Navigation Effects - if (!m_nTickCount) - { - // Pattern Loop - if (nPatLoopRow >= 0) - { - m_nNextPattern = m_nCurrentPattern; - m_nNextRow = nPatLoopRow; - if (m_nPatternDelay) m_nNextRow++; - } else - // Pattern Break / Position Jump only if no loop running - if ((nBreakRow >= 0) || (nPosJump >= 0)) - { - BOOL bNoLoop = FALSE; - if (nPosJump < 0) nPosJump = m_nCurrentPattern+1; - if (nBreakRow < 0) nBreakRow = 0; - // Modplug Tracker & ModPlugin allow backward jumps - #ifndef MODPLUG_FASTSOUNDLIB - if ((nPosJump < (int)m_nCurrentPattern) - || ((nPosJump == (int)m_nCurrentPattern) && (nBreakRow <= (int)m_nRow))) - { - if (!IsValidBackwardJump(m_nCurrentPattern, m_nRow, nPosJump, nBreakRow)) - { - if (m_nRepeatCount) - { - if (m_nRepeatCount > 0) m_nRepeatCount--; - } else - { - #ifdef MODPLUG_TRACKER - if (gdwSoundSetup & SNDMIX_NOBACKWARDJUMPS) - #endif - // Backward jump disabled - bNoLoop = TRUE; - //reset repeat count incase there are multiple loops. - //(i.e. Unreal tracks) - m_nRepeatCount = m_nInitialRepeatCount; - } - } - } - #endif // MODPLUG_FASTSOUNDLIB - if (((!bNoLoop) && (nPosJump < MAX_ORDERS)) - && ((nPosJump != (int)m_nCurrentPattern) || (nBreakRow != (int)m_nRow))) - { - if (nPosJump != (int)m_nCurrentPattern) - { - for (UINT i=0; inOldPortaUpDown = param; else param = pChn->nOldPortaUpDown; - if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0)) - { - if (param & 0x0F) - { - if ((param & 0xF0) == 0xF0) - { - FinePortamentoUp(pChn, param & 0x0F); - } else - if ((param & 0xF0) == 0xE0) - { - ExtraFinePortamentoUp(pChn, param & 0x0F); - } - } - return; - } - // Regular Slide - if (!(m_dwSongFlags & SONG_FIRSTTICK) || (m_nMusicSpeed == 1)) //rewbs.PortaA01fix - { - DoFreqSlide(pChn, -(int)(param * 4)); - } -} - - -void CSoundFile::PortamentoDown(MODCHANNEL *pChn, UINT param) -//----------------------------------------------------------- -{ - if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown; - if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0)) - { - if (param & 0x0F) - { - if ((param & 0xF0) == 0xF0) - { - FinePortamentoDown(pChn, param & 0x0F); - } else - if ((param & 0xF0) == 0xE0) - { - ExtraFinePortamentoDown(pChn, param & 0x0F); - } - } - return; - } - if (!(m_dwSongFlags & SONG_FIRSTTICK) || (m_nMusicSpeed == 1)) { //rewbs.PortaA01fix - DoFreqSlide(pChn, (int)(param << 2)); - } -} - - -void CSoundFile::FinePortamentoUp(MODCHANNEL *pChn, UINT param) -//------------------------------------------------------------- -{ - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown; - } - if (m_dwSongFlags & SONG_FIRSTTICK) - { - if ((pChn->nPeriod) && (param)) - { - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideDownTable[param & 0x0F], 65536); - } else - { - pChn->nPeriod -= (int)(param * 4); - } - if (pChn->nPeriod < 1) pChn->nPeriod = 1; - } - } -} - - -void CSoundFile::FinePortamentoDown(MODCHANNEL *pChn, UINT param) -//--------------------------------------------------------------- -{ - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown; - } - if (m_dwSongFlags & SONG_FIRSTTICK) - { - if ((pChn->nPeriod) && (param)) - { - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideUpTable[param & 0x0F], 65536); - } else - { - pChn->nPeriod += (int)(param * 4); - } - if (pChn->nPeriod > 0xFFFF) pChn->nPeriod = 0xFFFF; - } - } -} - - -void CSoundFile::ExtraFinePortamentoUp(MODCHANNEL *pChn, UINT param) -//------------------------------------------------------------------ -{ - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown; - } - if (m_dwSongFlags & SONG_FIRSTTICK) - { - if ((pChn->nPeriod) && (param)) - { - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - pChn->nPeriod = _muldivr(pChn->nPeriod, FineLinearSlideDownTable[param & 0x0F], 65536); - } else - { - pChn->nPeriod -= (int)(param); - } - if (pChn->nPeriod < 1) pChn->nPeriod = 1; - } - } -} - - -void CSoundFile::ExtraFinePortamentoDown(MODCHANNEL *pChn, UINT param) -//-------------------------------------------------------------------- -{ - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown; - } - if (m_dwSongFlags & SONG_FIRSTTICK) - { - if ((pChn->nPeriod) && (param)) - { - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - pChn->nPeriod = _muldivr(pChn->nPeriod, FineLinearSlideUpTable[param & 0x0F], 65536); - } else - { - pChn->nPeriod += (int)(param); - } - if (pChn->nPeriod > 0xFFFF) pChn->nPeriod = 0xFFFF; - } - } -} - - -// Portamento Slide -void CSoundFile::TonePortamento(MODCHANNEL *pChn, UINT param) -//----------------------------------------------------------- -{ - if (param) pChn->nPortamentoSlide = param * 4; - pChn->dwFlags |= CHN_PORTAMENTO; - if ((pChn->nPeriod) && (pChn->nPortamentoDest) && (!(m_dwSongFlags & SONG_FIRSTTICK))) - { - if (pChn->nPeriod < pChn->nPortamentoDest) - { - LONG delta = (int)pChn->nPortamentoSlide; - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - UINT n = pChn->nPortamentoSlide >> 2; - if (n > 255) n = 255; - delta = _muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536) - pChn->nPeriod; - if (delta < 1) delta = 1; - } - pChn->nPeriod += delta; - if (pChn->nPeriod > pChn->nPortamentoDest) pChn->nPeriod = pChn->nPortamentoDest; - } else - if (pChn->nPeriod > pChn->nPortamentoDest) - { - LONG delta = - (int)pChn->nPortamentoSlide; - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - UINT n = pChn->nPortamentoSlide >> 2; - if (n > 255) n = 255; - delta = _muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536) - pChn->nPeriod; - if (delta > -1) delta = -1; - } - pChn->nPeriod += delta; - if (pChn->nPeriod < pChn->nPortamentoDest) pChn->nPeriod = pChn->nPortamentoDest; - } - } -} - - -void CSoundFile::Vibrato(MODCHANNEL *p, UINT param) -//------------------------------------------------- -{ - if (param & 0x0F) p->nVibratoDepth = (param & 0x0F) * 4; - if (param & 0xF0) p->nVibratoSpeed = (param >> 4) & 0x0F; - p->dwFlags |= CHN_VIBRATO; -} - - -void CSoundFile::FineVibrato(MODCHANNEL *p, UINT param) -//----------------------------------------------------- -{ - if (param & 0x0F) p->nVibratoDepth = param & 0x0F; - if (param & 0xF0) p->nVibratoSpeed = (param >> 4) & 0x0F; - p->dwFlags |= CHN_VIBRATO; -} - - -void CSoundFile::Panbrello(MODCHANNEL *p, UINT param) -//--------------------------------------------------- -{ - if (param & 0x0F) p->nPanbrelloDepth = param & 0x0F; - if (param & 0xF0) p->nPanbrelloSpeed = (param >> 4) & 0x0F; - p->dwFlags |= CHN_PANBRELLO; -} - - -void CSoundFile::VolumeSlide(MODCHANNEL *pChn, UINT param) -//-------------------------------------------------------- -{ - if (param) pChn->nOldVolumeSlide = param; else param = pChn->nOldVolumeSlide; - LONG newvolume = pChn->nVolume; - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM|MOD_TYPE_AMF)) - { - if ((param & 0x0F) == 0x0F) - { - if (param & 0xF0) - { - FineVolumeUp(pChn, (param >> 4)); - return; - } else - { - if ((m_dwSongFlags & SONG_FIRSTTICK) && (!(m_dwSongFlags & SONG_FASTVOLSLIDES))) - { - newvolume -= 0x0F * 4; - } - } - } else - if ((param & 0xF0) == 0xF0) - { - if (param & 0x0F) - { - FineVolumeDown(pChn, (param & 0x0F)); - return; - } else - { - if ((m_dwSongFlags & SONG_FIRSTTICK) && (!(m_dwSongFlags & SONG_FASTVOLSLIDES))) - { - newvolume += 0x0F * 4; - } - } - } - } - if ((!(m_dwSongFlags & SONG_FIRSTTICK)) || (m_dwSongFlags & SONG_FASTVOLSLIDES)) - { - if (param & 0x0F) newvolume -= (int)((param & 0x0F) * 4); - else newvolume += (int)((param & 0xF0) >> 2); - if (m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP; - } - if (newvolume < 0) newvolume = 0; - if (newvolume > 256) newvolume = 256; - pChn->nVolume = newvolume; -} - - -void CSoundFile::PanningSlide(MODCHANNEL *pChn, UINT param) -//--------------------------------------------------------- -{ - LONG nPanSlide = 0; - if (param) pChn->nOldPanSlide = param; else param = pChn->nOldPanSlide; - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) - { - if (((param & 0x0F) == 0x0F) && (param & 0xF0)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) - { - param = (param & 0xF0) >> 2; - nPanSlide = - (int)param; - } - } else - if (((param & 0xF0) == 0xF0) && (param & 0x0F)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) - { - nPanSlide = (param & 0x0F) << 2; - } - } else - { - if (!(m_dwSongFlags & SONG_FIRSTTICK)) - { - if (param & 0x0F) nPanSlide = (int)((param & 0x0F) << 2); - else nPanSlide = -(int)((param & 0xF0) >> 2); - } - } - } else - { - if (!(m_dwSongFlags & SONG_FIRSTTICK)) - { - if (param & 0x0F) nPanSlide = -(int)((param & 0x0F) << 2); - else nPanSlide = (int)((param & 0xF0) >> 2); - } - } - if (nPanSlide) - { - nPanSlide += pChn->nPan; - if (nPanSlide < 0) nPanSlide = 0; - if (nPanSlide > 256) nPanSlide = 256; - pChn->nPan = nPanSlide; - } -} - - -void CSoundFile::FineVolumeUp(MODCHANNEL *pChn, UINT param) -//--------------------------------------------------------- -{ - if (param) pChn->nOldFineVolUpDown = param; else param = pChn->nOldFineVolUpDown; - if (m_dwSongFlags & SONG_FIRSTTICK) - { - pChn->nVolume += param * 4; - if (pChn->nVolume > 256) pChn->nVolume = 256; - if (m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP; - } -} - - -void CSoundFile::FineVolumeDown(MODCHANNEL *pChn, UINT param) -//----------------------------------------------------------- -{ - if (param) pChn->nOldFineVolUpDown = param; else param = pChn->nOldFineVolUpDown; - if (m_dwSongFlags & SONG_FIRSTTICK) - { - pChn->nVolume -= param * 4; - if (pChn->nVolume < 0) pChn->nVolume = 0; - if (m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP; - } -} - - -void CSoundFile::Tremolo(MODCHANNEL *p, UINT param) -//------------------------------------------------- -{ - if (param & 0x0F) p->nTremoloDepth = (param & 0x0F) << 2; - if (param & 0xF0) p->nTremoloSpeed = (param >> 4) & 0x0F; - p->dwFlags |= CHN_TREMOLO; -} - - -void CSoundFile::ChannelVolSlide(MODCHANNEL *pChn, UINT param) -//------------------------------------------------------------ -{ - LONG nChnSlide = 0; - if (param) pChn->nOldChnVolSlide = param; else param = pChn->nOldChnVolSlide; - if (((param & 0x0F) == 0x0F) && (param & 0xF0)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) nChnSlide = param >> 4; - } else - if (((param & 0xF0) == 0xF0) && (param & 0x0F)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) nChnSlide = - (int)(param & 0x0F); - } else - { - if (!(m_dwSongFlags & SONG_FIRSTTICK)) - { - if (param & 0x0F) nChnSlide = -(int)(param & 0x0F); - else nChnSlide = (int)((param & 0xF0) >> 4); - } - } - if (nChnSlide) - { - nChnSlide += pChn->nGlobalVol; - if (nChnSlide < 0) nChnSlide = 0; - if (nChnSlide > 64) nChnSlide = 64; - pChn->nGlobalVol = nChnSlide; - } -} - - -void CSoundFile::ExtendedMODCommands(UINT nChn, UINT param) -//--------------------------------------------------------- -{ - MODCHANNEL *pChn = &Chn[nChn]; - UINT command = param & 0xF0; - param &= 0x0F; - switch(command) - { - // E0x: Set Filter - // E1x: Fine Portamento Up - case 0x10: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FinePortamentoUp(pChn, param); break; - // E2x: Fine Portamento Down - case 0x20: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FinePortamentoDown(pChn, param); break; - // E3x: Set Glissando Control - case 0x30: pChn->dwFlags &= ~CHN_GLISSANDO; if (param) pChn->dwFlags |= CHN_GLISSANDO; break; - // E4x: Set Vibrato WaveForm - case 0x40: pChn->nVibratoType = param & 0x07; break; - // E5x: Set FineTune - case 0x50: if (m_nTickCount) break; - pChn->nC4Speed = S3MFineTuneTable[param]; - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - pChn->nFineTune = param*2; - else - pChn->nFineTune = MOD2XMFineTune(param); - if (pChn->nPeriod) pChn->nPeriod = GetPeriodFromNote(pChn->nNote, pChn->nFineTune, pChn->nC4Speed); - break; - // E6x: Pattern Loop - // E7x: Set Tremolo WaveForm - case 0x70: pChn->nTremoloType = param & 0x07; break; - // E8x: Set 4-bit Panning - case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break; - // E9x: Retrig - case 0x90: RetrigNote(nChn, param); break; - // EAx: Fine Volume Up - case 0xA0: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FineVolumeUp(pChn, param); break; - // EBx: Fine Volume Down - case 0xB0: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FineVolumeDown(pChn, param); break; - // ECx: Note Cut - case 0xC0: NoteCut(nChn, param); break; - // EDx: Note Delay - // EEx: Pattern Delay - // EFx: MOD: Invert Loop, XM: Set Active Midi Macro - case 0xF0: pChn->nActiveMacro = param; break; - } -} - - -void CSoundFile::ExtendedS3MCommands(UINT nChn, UINT param) -//--------------------------------------------------------- -{ - MODCHANNEL *pChn = &Chn[nChn]; - UINT command = param & 0xF0; - param &= 0x0F; - switch(command) - { - // S0x: Set Filter - // S1x: Set Glissando Control - case 0x10: pChn->dwFlags &= ~CHN_GLISSANDO; if (param) pChn->dwFlags |= CHN_GLISSANDO; break; - // S2x: Set FineTune - case 0x20: if (m_nTickCount) break; - pChn->nC4Speed = S3MFineTuneTable[param & 0x0F]; - pChn->nFineTune = MOD2XMFineTune(param); - if (pChn->nPeriod) pChn->nPeriod = GetPeriodFromNote(pChn->nNote, pChn->nFineTune, pChn->nC4Speed); - break; - // S3x: Set Vibrato WaveForm - case 0x30: pChn->nVibratoType = param & 0x07; break; - // S4x: Set Tremolo WaveForm - case 0x40: pChn->nTremoloType = param & 0x07; break; - // S5x: Set Panbrello WaveForm - case 0x50: pChn->nPanbrelloType = param & 0x07; break; - // S6x: Pattern Delay for x frames - case 0x60: m_nFrameDelay = param; break; - // S7x: Envelope Control - case 0x70: if (m_nTickCount) break; - switch(param) - { - case 0: - case 1: - case 2: - { - MODCHANNEL *bkp = &Chn[m_nChannels]; - for (UINT i=m_nChannels; inMasterChn == nChn+1) - { - if (param == 1) KeyOff(i); else - if (param == 2) bkp->dwFlags |= CHN_NOTEFADE; else - { bkp->dwFlags |= CHN_NOTEFADE; bkp->nFadeOutVol = 0; } - } - } - } - break; - case 3: pChn->nNNA = NNA_NOTECUT; break; - case 4: pChn->nNNA = NNA_CONTINUE; break; - case 5: pChn->nNNA = NNA_NOTEOFF; break; - case 6: pChn->nNNA = NNA_NOTEFADE; break; - case 7: pChn->dwFlags &= ~CHN_VOLENV; break; - case 8: pChn->dwFlags |= CHN_VOLENV; break; - case 9: pChn->dwFlags &= ~CHN_PANENV; break; - case 10: pChn->dwFlags |= CHN_PANENV; break; - case 11: pChn->dwFlags &= ~CHN_PITCHENV; break; - case 12: pChn->dwFlags |= CHN_PITCHENV; break; - } - break; - // S8x: Set 4-bit Panning - case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break; - // S9x: Set Surround - case 0x90: ExtendedChannelEffect(pChn, param & 0x0F); break; - // SAx: Set 64k Offset - case 0xA0: if (!m_nTickCount) - { - pChn->nOldHiOffset = param; - if ((pChn->nRowNote) && (pChn->nRowNote < 0x80)) - { - DWORD pos = param << 16; - if (pos < pChn->nLength) pChn->nPos = pos; - } - } - break; - // SBx: Pattern Loop - // SCx: Note Cut - case 0xC0: NoteCut(nChn, param); break; - // SDx: Note Delay - // case 0xD0: break; - // SEx: Pattern Delay for x rows - // SFx: S3M: Funk Repeat, IT: Set Active Midi Macro - case 0xF0: pChn->nActiveMacro = param; break; - } -} - - -void CSoundFile::ExtendedChannelEffect(MODCHANNEL *pChn, UINT param) -//------------------------------------------------------------------ -{ - // S9x and X9x commands (S3M/XM/IT only) - if (m_nTickCount) return; - switch(param & 0x0F) - { - // S90: Surround Off - case 0x00: pChn->dwFlags &= ~CHN_SURROUND; break; - // S91: Surround On - case 0x01: pChn->dwFlags |= CHN_SURROUND; pChn->nPan = 128; break; - //////////////////////////////////////////////////////////// - // Modplug Extensions - // S98: Reverb Off - case 0x08: - pChn->dwFlags &= ~CHN_REVERB; - pChn->dwFlags |= CHN_NOREVERB; - break; - // S99: Reverb On - case 0x09: - pChn->dwFlags &= ~CHN_NOREVERB; - pChn->dwFlags |= CHN_REVERB; - break; - // S9A: 2-Channels surround mode - case 0x0A: - m_dwSongFlags &= ~SONG_SURROUNDPAN; - break; - // S9B: 4-Channels surround mode - case 0x0B: - m_dwSongFlags |= SONG_SURROUNDPAN; - break; - // S9C: IT Filter Mode - case 0x0C: - m_dwSongFlags &= ~SONG_MPTFILTERMODE; - break; - // S9D: MPT Filter Mode - case 0x0D: - m_dwSongFlags |= SONG_MPTFILTERMODE; - break; - // S9E: Go forward - case 0x0E: - pChn->dwFlags &= ~(CHN_PINGPONGFLAG); - break; - // S9F: Go backward (set position at the end for non-looping samples) - case 0x0F: - if ((!(pChn->dwFlags & CHN_LOOP)) && (!pChn->nPos) && (pChn->nLength)) - { - pChn->nPos = pChn->nLength - 1; - pChn->nPosLo = 0xFFFF; - } - pChn->dwFlags |= CHN_PINGPONGFLAG; - break; - } -} - - -void CSoundFile::ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param) -//--------------------------------------------------------------------------- -{ - MODCHANNEL *pChn = &Chn[nChn]; - DWORD dwMacro = (*((LPDWORD)pszMidiMacro)) & 0x7F5F7F5F; - // Not Internal Device ? - if (dwMacro != 0x30463046 && dwMacro != 0x31463046) - { - UINT pos = 0, nNib = 0, nBytes = 0; - DWORD dwMidiCode = 0, dwByteCode = 0; - while (pos+6 <= 32) - { - CHAR cData = pszMidiMacro[pos++]; - if (!cData) break; - if ((cData >= '0') && (cData <= '9')) { dwByteCode = (dwByteCode<<4) | (cData-'0'); nNib++; } else - if ((cData >= 'A') && (cData <= 'F')) { dwByteCode = (dwByteCode<<4) | (cData-'A'+10); nNib++; } else - if ((cData >= 'a') && (cData <= 'f')) { dwByteCode = (dwByteCode<<4) | (cData-'a'+10); nNib++; } else - if ((cData == 'z') || (cData == 'Z')) { dwByteCode = param & 0x7f; nNib = 2; } else - if ((cData == 'x') || (cData == 'X')) { dwByteCode = param & 0x70; nNib = 2; } else - if ((cData == 'y') || (cData == 'Y')) { dwByteCode = (param & 0x0f)<<3; nNib = 2; } else - if (nNib >= 2) - { - nNib = 0; - dwMidiCode |= dwByteCode << (nBytes*8); - dwByteCode = 0; - nBytes++; - if (nBytes >= 3) - { - UINT nMasterCh = (nChn < m_nChannels) ? nChn+1 : pChn->nMasterChn; - if ((nMasterCh) && (nMasterCh <= m_nChannels)) - { - UINT nPlug = ChnSettings[nMasterCh-1].nMixPlugin; - if ((nPlug) && (nPlug <= MAX_MIXPLUGINS)) - { - IMixPlugin *pPlugin = m_MixPlugins[nPlug-1].pMixPlugin; - if ((pPlugin) && (m_MixPlugins[nPlug-1].pMixState)) - { - pPlugin->MidiSend(dwMidiCode); - } - } - } - nBytes = 0; - dwMidiCode = 0; - } - } - - } - return; - } - // Internal device - pszMidiMacro += 4; - // Filter ? - if (pszMidiMacro[0] == '0') - { - CHAR cData1 = pszMidiMacro[2]; - DWORD dwParam = 0; - if ((cData1 == 'z') || (cData1 == 'Z')) - { - dwParam = param; - } else - { - CHAR cData2 = pszMidiMacro[3]; - if ((cData1 >= '0') && (cData1 <= '9')) dwParam += (cData1 - '0') << 4; else - if ((cData1 >= 'A') && (cData1 <= 'F')) dwParam += (cData1 - 'A' + 0x0A) << 4; - if ((cData2 >= '0') && (cData2 <= '9')) dwParam += (cData2 - '0'); else - if ((cData2 >= 'A') && (cData2 <= 'F')) dwParam += (cData2 - 'A' + 0x0A); - } - switch(pszMidiMacro[1]) - { - // F0.F0.00.xx: Set CutOff - case '0': - { - int oldcutoff = pChn->nCutOff; - if (dwParam < 0x80) pChn->nCutOff = (BYTE)dwParam; -#ifndef NO_FILTER - oldcutoff -= pChn->nCutOff; - - if (oldcutoff < 0) oldcutoff = -oldcutoff; - if ((pChn->nVolume > 0) || (oldcutoff < 0x10) - || (!(pChn->dwFlags & CHN_FILTER)) || (!(pChn->nLeftVol|pChn->nRightVol))) - SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE); -#endif // NO_FILTER - } - break; - - // F0.F0.01.xx: Set Resonance - case '1': - if (dwParam < 0x80) pChn->nResonance = (BYTE)dwParam; -#ifndef NO_FILTER - SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE); -#endif // NO_FILTER - - break; - } - - } -} - - -void CSoundFile::RetrigNote(UINT nChn, UINT param) -//------------------------------------------------ -{ - // Retrig: bit 8 is set if it's the new XM retrig - MODCHANNEL *pChn = &Chn[nChn]; - UINT nRetrigSpeed = param & 0x0F; - UINT nRetrigCount = pChn->nRetrigCount; - BOOL bDoRetrig = FALSE; - - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) - { - if (!nRetrigSpeed) nRetrigSpeed = 1; - if ((nRetrigCount) && (!(nRetrigCount % nRetrigSpeed))) bDoRetrig = TRUE; - nRetrigCount++; - } else - { - UINT realspeed = nRetrigSpeed; - if ((param & 0x100) && (pChn->nRowVolCmd == VOLCMD_VOLUME) && (pChn->nRowParam & 0xF0)) realspeed++; - if ((m_nTickCount) || (param & 0x100)) - { - if (!realspeed) realspeed = 1; - if ((!(param & 0x100)) && (m_nMusicSpeed) && (!(m_nTickCount % realspeed))) bDoRetrig = TRUE; - nRetrigCount++; - } else if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) nRetrigCount = 0; - if (nRetrigCount >= realspeed) - { - if ((m_nTickCount) || ((param & 0x100) && (!pChn->nRowNote))) bDoRetrig = TRUE; - } - } - if (bDoRetrig) - { - UINT dv = (param >> 4) & 0x0F; - if (dv) - { - int vol = pChn->nVolume; - if (retrigTable1[dv]) - vol = (vol * retrigTable1[dv]) >> 4; - else - vol += ((int)retrigTable2[dv]) << 2; - if (vol < 0) vol = 0; - if (vol > 256) vol = 256; - pChn->nVolume = vol; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } - UINT nNote = pChn->nNewNote; - LONG nOldPeriod = pChn->nPeriod; - if ((nNote) && (nNote <= NOTE_MAX) && (pChn->nLength)) CheckNNA(nChn, 0, nNote, TRUE); - BOOL bResetEnv = FALSE; - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if ((pChn->nRowInstr) && (param < 0x100)) { InstrumentChange(pChn, pChn->nRowInstr, FALSE, FALSE); bResetEnv = TRUE; } - if (param < 0x100) bResetEnv = TRUE; - } - NoteChange(nChn, nNote, FALSE, bResetEnv); - if ((m_nType & MOD_TYPE_IT) && (!pChn->nRowNote) && (nOldPeriod)) pChn->nPeriod = nOldPeriod; - if (!(m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) nRetrigCount = 0; - } - pChn->nRetrigCount = (BYTE)nRetrigCount; -} - - -void CSoundFile::DoFreqSlide(MODCHANNEL *pChn, LONG nFreqSlide) -//------------------------------------------------------------- -{ - // IT Linear slides - if (!pChn->nPeriod) return; - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))) - { - if (nFreqSlide < 0) - { - UINT n = (- nFreqSlide) >> 2; - if (n > 255) n = 255; - pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536); - } else - { - UINT n = (nFreqSlide) >> 2; - - if (n > 255) n = 255; - pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536); - } - } else - { - pChn->nPeriod += nFreqSlide; - } - if (pChn->nPeriod < 1) - { - pChn->nPeriod = 1; - if (m_nType & MOD_TYPE_IT) - { - pChn->dwFlags |= CHN_NOTEFADE; - pChn->nFadeOutVol = 0; - } - } -} - - -void CSoundFile::NoteCut(UINT nChn, UINT nTick) -//--------------------------------------------- -{ - if (m_nTickCount == nTick) - { - MODCHANNEL *pChn = &Chn[nChn]; - // if (m_nInstruments) KeyOff(pChn); ? - pChn->nVolume = 0; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } -} - - -void CSoundFile::KeyOff(UINT nChn) -//-------------------------------- -{ - MODCHANNEL *pChn = &Chn[nChn]; - BOOL bKeyOn = (pChn->dwFlags & CHN_KEYOFF) ? FALSE : TRUE; - pChn->dwFlags |= CHN_KEYOFF; - //if ((!pChn->pHeader) || (!(pChn->dwFlags & CHN_VOLENV))) - if ((pChn->pHeader) && (!(pChn->dwFlags & CHN_VOLENV))) - { - pChn->dwFlags |= CHN_NOTEFADE; - } - if (!pChn->nLength) return; - if ((pChn->dwFlags & CHN_SUSTAINLOOP) && (pChn->pInstrument) && (bKeyOn)) - { - MODINSTRUMENT *psmp = pChn->pInstrument; - if (psmp->uFlags & CHN_LOOP) - { - if (psmp->uFlags & CHN_PINGPONGLOOP) - pChn->dwFlags |= CHN_PINGPONGLOOP; - else - pChn->dwFlags &= ~(CHN_PINGPONGLOOP|CHN_PINGPONGFLAG); - pChn->dwFlags |= CHN_LOOP; - pChn->nLength = psmp->nLength; - pChn->nLoopStart = psmp->nLoopStart; - pChn->nLoopEnd = psmp->nLoopEnd; - if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd; - } else - { - pChn->dwFlags &= ~(CHN_LOOP|CHN_PINGPONGLOOP|CHN_PINGPONGFLAG); - pChn->nLength = psmp->nLength; - } - } - if (pChn->pHeader) - { - INSTRUMENTHEADER *penv = pChn->pHeader; - if (((penv->dwFlags & ENV_VOLLOOP) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) && (penv->nFadeOut)) - pChn->dwFlags |= CHN_NOTEFADE; - } -} - - -////////////////////////////////////////////////////////// -// CSoundFile: Global Effects - - -void CSoundFile::SetSpeed(UINT param) -//----------------------------------- -{ - UINT max = (m_nType == MOD_TYPE_IT) ? 256 : 128; - // Modplug Tracker and Mod-Plugin don't do this check -#ifndef MODPLUG_TRACKER -#ifndef MODPLUG_FASTSOUNDLIB - // Big Hack!!! - if ((!param) || (param >= 0x80) || ((m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2)) && (param >= 0x1E))) - { - if (IsSongFinished(m_nCurrentPattern, m_nRow+1)) - { - GlobalFadeSong(1000); - } - } -#endif // MODPLUG_FASTSOUNDLIB -#endif // MODPLUG_TRACKER - if ((m_nType & MOD_TYPE_S3M) && (param > 0x80)) param -= 0x80; - if ((param) && (param <= max)) m_nMusicSpeed = param; -} - - -void CSoundFile::SetTempo(UINT param) -//----------------------------------- -{ - if (param < 0x20) - { - // Tempo Slide - if ((param & 0xF0) == 0x10) - { - m_nMusicTempo += (param & 0x0F) * 2; - if (m_nMusicTempo > 255) m_nMusicTempo = 255; - } else - { - m_nMusicTempo -= (param & 0x0F) * 2; - if ((LONG)m_nMusicTempo < 32) m_nMusicTempo = 32; - } - } else - { - m_nMusicTempo = param; - } -} - - -int CSoundFile::PatternLoop(MODCHANNEL *pChn, UINT param) -//------------------------------------------------------- -{ - if (param) - { - if (pChn->nPatternLoopCount) - { - pChn->nPatternLoopCount--; - if (!pChn->nPatternLoopCount) return -1; - } else - { - MODCHANNEL *p = Chn; - for (UINT i=0; inPatternLoopCount) return -1; - } - pChn->nPatternLoopCount = param; - } - return pChn->nPatternLoop; - } else - { - pChn->nPatternLoop = m_nRow; - } - return -1; -} - - -void CSoundFile::GlobalVolSlide(UINT param) -//----------------------------------------- -{ - LONG nGlbSlide = 0; - if (param) m_nOldGlbVolSlide = param; else param = m_nOldGlbVolSlide; - if (((param & 0x0F) == 0x0F) && (param & 0xF0)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) nGlbSlide = (param >> 4) * 2; - } else - if (((param & 0xF0) == 0xF0) && (param & 0x0F)) - { - if (m_dwSongFlags & SONG_FIRSTTICK) nGlbSlide = - (int)((param & 0x0F) * 2); - } else - { - if (!(m_dwSongFlags & SONG_FIRSTTICK)) - { - if (param & 0xF0) nGlbSlide = (int)((param & 0xF0) >> 4) * 2; - else nGlbSlide = -(int)((param & 0x0F) * 2); - } - } - if (nGlbSlide) - { - if (m_nType != MOD_TYPE_IT) nGlbSlide *= 2; - nGlbSlide += m_nGlobalVolume; - if (nGlbSlide < 0) nGlbSlide = 0; - if (nGlbSlide > 256) nGlbSlide = 256; - m_nGlobalVolume = nGlbSlide; - } -} - - -DWORD CSoundFile::IsSongFinished(UINT nStartOrder, UINT nStartRow) const -//---------------------------------------------------------------------- -{ - UINT nOrd; - - for (nOrd=nStartOrder; nOrd= MAX_PATTERNS) break; - p = Patterns[nPat]; - if (p) - { - UINT len = PatternSize[nPat] * m_nChannels; - UINT pos = (nOrd == nStartOrder) ? nStartRow : 0; - pos *= m_nChannels; - while (pos < len) - { - UINT cmd; - if ((p[pos].note) || (p[pos].volcmd)) return 0; - cmd = p[pos].command; - if (cmd == CMD_MODCMDEX) - { - UINT cmdex = p[pos].param & 0xF0; - if ((!cmdex) || (cmdex == 0x60) || (cmdex == 0xE0) || (cmdex == 0xF0)) cmd = 0; - } - if ((cmd) && (cmd != CMD_SPEED) && (cmd != CMD_TEMPO)) return 0; - pos++; - } - } - } - } - return (nOrd < MAX_ORDERS) ? nOrd : MAX_ORDERS-1; -} - - -BOOL CSoundFile::IsValidBackwardJump(UINT nStartOrder, UINT nStartRow, UINT nJumpOrder, UINT nJumpRow) const -//---------------------------------------------------------------------------------------------------------- -{ - while ((nJumpOrder < MAX_PATTERNS) && (Order[nJumpOrder] == 0xFE)) nJumpOrder++; - if ((nStartOrder >= MAX_PATTERNS) || (nJumpOrder >= MAX_PATTERNS)) return FALSE; - // Treat only case with jumps in the same pattern - if (nJumpOrder > nStartOrder) return TRUE; - if ((nJumpOrder < nStartOrder) || (nJumpRow >= PatternSize[nStartOrder]) - || (!Patterns[nStartOrder]) || (nStartRow >= 256) || (nJumpRow >= 256)) return FALSE; - // See if the pattern is being played backward - BYTE row_hist[256]; - memset(row_hist, 0, sizeof(row_hist)); - UINT nRows = PatternSize[nStartOrder], row = nJumpRow; - if (nRows > 256) nRows = 256; - row_hist[nStartRow] = TRUE; - while ((row < 256) && (!row_hist[row])) - { - if (row >= nRows) return TRUE; - row_hist[row] = TRUE; - MODCOMMAND *p = Patterns[nStartOrder] + row * m_nChannels; - row++; - int breakrow = -1, posjump = 0; - for (UINT i=0; icommand == CMD_POSITIONJUMP) - { - if (p->param < nStartOrder) return FALSE; - if (p->param > nStartOrder) return TRUE; - posjump = TRUE; - } else - if (p->command == CMD_PATTERNBREAK) - { - breakrow = p->param; - } - } - if (breakrow >= 0) - { - if (!posjump) return TRUE; - row = breakrow; - } - if (row >= nRows) return TRUE; - } - return FALSE; -} - - -////////////////////////////////////////////////////// -// Note/Period/Frequency functions - -UINT CSoundFile::GetNoteFromPeriod(UINT period) const -//--------------------------------------------------- -{ - if (!period) return 0; - if (m_nType & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_OKT|MOD_TYPE_AMF0)) - { - period >>= 2; - for (UINT i=0; i<6*12; i++) - { - if (period >= ProTrackerPeriodTable[i]) - { - if ((period != ProTrackerPeriodTable[i]) && (i)) - { - UINT p1 = ProTrackerPeriodTable[i-1]; - UINT p2 = ProTrackerPeriodTable[i]; - if (p1 - period < (period - p2)) return i+36; - } - return i+1+36; - } - } - return 6*12+36; - } else - { - for (UINT i=1; i 0) && (n <= (LONG)period)) return i; - } - return NOTE_MAX; - } -} - - - -UINT CSoundFile::GetPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const -//------------------------------------------------------------------------------- -{ - if ((!note) || (note > 0xF0)) return 0; - if (m_nType & (MOD_TYPE_IT|MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_MDL|MOD_TYPE_ULT|MOD_TYPE_WAV - |MOD_TYPE_FAR|MOD_TYPE_DMF|MOD_TYPE_PTM|MOD_TYPE_AMS|MOD_TYPE_DBM|MOD_TYPE_AMF|MOD_TYPE_PSM)) - { - note--; - if (m_dwSongFlags & SONG_LINEARSLIDES) - { - return (FreqS3MTable[note % 12] << 5) >> (note / 12); - } else - { - if (!nC4Speed) nC4Speed = 8363; - return _muldiv(8363, (FreqS3MTable[note % 12] << 5), nC4Speed << (note / 12)); - } - } else - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (note < 13) note = 13; - note -= 13; - if (m_dwSongFlags & SONG_LINEARSLIDES) - { - LONG l = ((NOTE_MAX - note) << 6) - (nFineTune / 2); - if (l < 1) l = 1; - return (UINT)l; - } else - { - int finetune = nFineTune; - UINT rnote = (note % 12) << 3; - UINT roct = note / 12; - int rfine = finetune / 16; - int i = rnote + rfine + 8; - if (i < 0) i = 0; - if (i >= 104) i = 103; - UINT per1 = XMPeriodTable[i]; - if ( finetune < 0 ) - { - rfine--; - finetune = -finetune; - } else rfine++; - i = rnote+rfine+8; - if (i < 0) i = 0; - if (i >= 104) i = 103; - UINT per2 = XMPeriodTable[i]; - rfine = finetune & 0x0F; - per1 *= 16-rfine; - per2 *= rfine; - return ((per1 + per2) << 1) >> roct; - } - } else - { - note--; - nFineTune = XM2MODFineTune(nFineTune); - if ((nFineTune) || (note < 36) || (note >= 36+6*12)) - return (ProTrackerTunedPeriods[nFineTune*12 + note % 12] << 5) >> (note / 12); - else - return (ProTrackerPeriodTable[note-36] << 2); - } -} - - -UINT CSoundFile::GetFreqFromPeriod(UINT period, UINT nC4Speed, int nPeriodFrac) const -//----------------------------------------------------------------------------------- -{ - if (!period) return 0; - if (m_nType & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_OKT|MOD_TYPE_AMF0)) - { - return (3546895L*4) / period; - } else - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (m_dwSongFlags & SONG_LINEARSLIDES) - return XMLinearTable[period % 768] >> (period / 768); - else - return 8363 * 1712L / period; - } else - { - if (m_dwSongFlags & SONG_LINEARSLIDES) - { - if (!nC4Speed) nC4Speed = 8363; - return _muldiv(nC4Speed, 1712L << 8, (period << 8)+nPeriodFrac); - } else - { - return _muldiv(8363, 1712L << 8, (period << 8)+nPeriodFrac); - } - } -} - - diff --git a/jni/sndfile.cpp b/jni/sndfile.cpp deleted file mode 100644 index 953801c..0000000 --- a/jni/sndfile.cpp +++ /dev/null @@ -1,1899 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque , - * Adam Goode (endian and char fixes for PPC) -*/ - -#include //for GCCFIX -#include -#include - -#define MMCMP_SUPPORT - -#ifdef MMCMP_SUPPORT -extern BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength); -#endif - -// External decompressors -extern void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter); -extern WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n); -extern int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen); -extern void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215); -extern void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215); - - -#define MAX_PACK_TABLES 3 - - -// Compression table -static const signed char UnpackTable[MAX_PACK_TABLES][16] = -//-------------------------------------------- -{ - // CPU-generated dynamic table - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - // u-Law table - {0, 1, 2, 4, 8, 16, 32, 64, - -1, -2, -4, -8, -16, -32, -48, -64}, - // Linear table - {0, 1, 2, 3, 5, 7, 12, 19, - -1, -2, -3, -5, -7, -12, -19, -31} -}; - - -////////////////////////////////////////////////////////// -// CSoundFile - -CSoundFile::CSoundFile() -//---------------------- -{ - m_nType = MOD_TYPE_NONE; - m_dwSongFlags = 0; - m_nChannels = 0; - m_nMixChannels = 0; - m_nSamples = 0; - m_nInstruments = 0; - m_nPatternNames = 0; - m_lpszPatternNames = NULL; - m_lpszSongComments = NULL; - m_nFreqFactor = m_nTempoFactor = 128; - m_nMasterVolume = 128; - m_nMinPeriod = 0x20; - m_nMaxPeriod = 0x7FFF; - m_nRepeatCount = 0; - memset(Chn, 0, sizeof(Chn)); - memset(ChnMix, 0, sizeof(ChnMix)); - memset(Ins, 0, sizeof(Ins)); - memset(ChnSettings, 0, sizeof(ChnSettings)); - memset(Headers, 0, sizeof(Headers)); - memset(Order, 0xFF, sizeof(Order)); - memset(Patterns, 0, sizeof(Patterns)); - memset(m_szNames, 0, sizeof(m_szNames)); - memset(m_MixPlugins, 0, sizeof(m_MixPlugins)); -} - - -CSoundFile::~CSoundFile() -//----------------------- -{ - Destroy(); -} - - -BOOL CSoundFile::Create(LPCBYTE lpStream, DWORD dwMemLength) -//---------------------------------------------------------- -{ - int i; - - m_nType = MOD_TYPE_NONE; - m_dwSongFlags = 0; - m_nChannels = 0; - m_nMixChannels = 0; - m_nSamples = 0; - m_nInstruments = 0; - m_nFreqFactor = m_nTempoFactor = 128; - m_nMasterVolume = 128; - m_nDefaultGlobalVolume = 256; - m_nGlobalVolume = 256; - m_nOldGlbVolSlide = 0; - m_nDefaultSpeed = 6; - m_nDefaultTempo = 125; - m_nPatternDelay = 0; - m_nFrameDelay = 0; - m_nNextRow = 0; - m_nRow = 0; - m_nPattern = 0; - m_nCurrentPattern = 0; - m_nNextPattern = 0; - m_nRestartPos = 0; - m_nMinPeriod = 16; - m_nMaxPeriod = 32767; - m_nSongPreAmp = 0x30; - m_nPatternNames = 0; - m_nMaxOrderPosition = 0; - m_lpszPatternNames = NULL; - m_lpszSongComments = NULL; - memset(Ins, 0, sizeof(Ins)); - memset(ChnMix, 0, sizeof(ChnMix)); - memset(Chn, 0, sizeof(Chn)); - memset(Headers, 0, sizeof(Headers)); - memset(Order, 0xFF, sizeof(Order)); - memset(Patterns, 0, sizeof(Patterns)); - memset(m_szNames, 0, sizeof(m_szNames)); - memset(m_MixPlugins, 0, sizeof(m_MixPlugins)); - ResetMidiCfg(); - for (UINT npt=0; npt=0) && (p[j]<=' ')) p[j--] = 0; - while (j>=0) - { - if (((BYTE)p[j]) < ' ') p[j] = ' '; - j--; - } - } - // Adjust channels - for (i=0; i 64) ChnSettings[i].nVolume = 64; - if (ChnSettings[i].nPan > 256) ChnSettings[i].nPan = 128; - Chn[i].nPan = ChnSettings[i].nPan; - Chn[i].nGlobalVol = ChnSettings[i].nVolume; - Chn[i].dwFlags = ChnSettings[i].dwFlags; - Chn[i].nVolume = 256; - Chn[i].nCutOff = 0x7F; - } - // Checking instruments - MODINSTRUMENT *pins = Ins; - - for (i=0; ipSample) - { - if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength; - if (pins->nLoopStart + 3 >= pins->nLoopEnd) - { - pins->nLoopStart = 0; - pins->nLoopEnd = 0; - } - if (pins->nSustainEnd > pins->nLength) pins->nSustainEnd = pins->nLength; - if (pins->nSustainStart + 3 >= pins->nSustainEnd) - { - pins->nSustainStart = 0; - pins->nSustainEnd = 0; - } - } else - { - pins->nLength = 0; - pins->nLoopStart = 0; - pins->nLoopEnd = 0; - pins->nSustainStart = 0; - pins->nSustainEnd = 0; - } - if (!pins->nLoopEnd) pins->uFlags &= ~CHN_LOOP; - if (!pins->nSustainEnd) pins->uFlags &= ~CHN_SUSTAINLOOP; - if (pins->nGlobalVol > 64) pins->nGlobalVol = 64; - } - // Check invalid instruments - while ((m_nInstruments > 0) && (!Headers[m_nInstruments])) - m_nInstruments--; - // Set default values - if (m_nSongPreAmp < 0x20) m_nSongPreAmp = 0x20; - if (m_nDefaultTempo < 32) m_nDefaultTempo = 125; - if (!m_nDefaultSpeed) m_nDefaultSpeed = 6; - m_nMusicSpeed = m_nDefaultSpeed; - m_nMusicTempo = m_nDefaultTempo; - m_nGlobalVolume = m_nDefaultGlobalVolume; - m_nNextPattern = 0; - m_nCurrentPattern = 0; - m_nPattern = 0; - m_nBufferCount = 0; - m_nTickCount = m_nMusicSpeed; - m_nNextRow = 0; - m_nRow = 0; - if ((m_nRestartPos >= MAX_ORDERS) || (Order[m_nRestartPos] >= MAX_PATTERNS)) m_nRestartPos = 0; - // Load plugins - if (gpMixPluginCreateProc) - { - for (UINT iPlug=0; iPlugRestoreAllParameters(); - } - } - } - } - if (m_nType) - { - UINT maxpreamp = 0x10+(m_nChannels*8); - if (maxpreamp > 100) maxpreamp = 100; - if (m_nSongPreAmp > maxpreamp) m_nSongPreAmp = maxpreamp; - return TRUE; - } - return FALSE; -} - - -BOOL CSoundFile::Destroy() - -//------------------------ -{ - int i; - for (i=0; ipSample) - { - FreeSample(pins->pSample); - pins->pSample = NULL; - } - } - for (i=0; iRelease(); - m_MixPlugins[i].pMixPlugin = NULL; - } - } - m_nType = MOD_TYPE_NONE; - m_nChannels = m_nSamples = m_nInstruments = 0; - return TRUE; -} - - -////////////////////////////////////////////////////////////////////////// -// Memory Allocation - -MODCOMMAND *CSoundFile::AllocatePattern(UINT rows, UINT nchns) -//------------------------------------------------------------ -{ - MODCOMMAND *p = new MODCOMMAND[rows*nchns]; - if (p) memset(p, 0, rows*nchns*sizeof(MODCOMMAND)); - return p; -} - - -void CSoundFile::FreePattern(LPVOID pat) -//-------------------------------------- -{ - if (pat) delete [] (signed char*)pat; -} - - -signed char* CSoundFile::AllocateSample(UINT nbytes) -//------------------------------------------- -{ - signed char * p = (signed char *)GlobalAllocPtr(GHND, (nbytes+39) & ~7); - if (p) p += 16; - return p; -} - - -void CSoundFile::FreeSample(LPVOID p) -//----------------------------------- -{ - if (p) - { - GlobalFreePtr(((LPSTR)p)-16); - } -} - - -////////////////////////////////////////////////////////////////////////// -// Misc functions - -void CSoundFile::ResetMidiCfg() -//----------------------------- -{ - memset(&m_MidiCfg, 0, sizeof(m_MidiCfg)); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_START*32], "FF"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_STOP*32], "FC"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON*32], "9c n v"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF*32], "9c n 0"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM*32], "Cc p"); - lstrcpy(&m_MidiCfg.szMidiSFXExt[0], "F0F000z"); - for (int iz=0; iz<16; iz++) wsprintf(&m_MidiCfg.szMidiZXXExt[iz*32], "F0F001%02X", iz*8); -} - - -UINT CSoundFile::GetNumChannels() const -//------------------------------------- -{ - UINT n = 0; - for (UINT i=0; i 1) && (s)) s[1] = '\x0A'; - while ((*p) && (i+2 < len)) - { - BYTE c = (BYTE)*p++; - if ((c == 0x0D) || ((c == ' ') && (ln >= linesize))) - { if (s) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else i+= 2; ln=0; } - else - if (c >= 0x20) { if (s) s[i++] = c; else i++; ln++; } - } - if (s) s[i] = 0; - return i; -} - - -UINT CSoundFile::GetRawSongComments(LPSTR s, UINT len, UINT linesize) -//------------------------------------------------------------------- -{ - LPCSTR p = m_lpszSongComments; - if (!p) return 0; - UINT i = 0, ln=0; - while ((*p) && (i < len-1)) - { - BYTE c = (BYTE)*p++; - if ((c == 0x0D) || (c == 0x0A)) - { - if (ln) - { - while (ln < linesize) { if (s) s[i] = ' '; i++; ln++; } - ln = 0; - } - } else - if ((c == ' ') && (!ln)) - { - UINT k=0; - while ((p[k]) && (p[k] >= ' ')) k++; - if (k <= linesize) - { - if (s) s[i] = ' '; - i++; - ln++; - } - } else - { - if (s) s[i] = c; - i++; - ln++; - if (ln == linesize) ln = 0; - } - } - if (ln) - { - while ((ln < linesize) && (i < len)) - { - if (s) s[i] = ' '; - i++; - ln++; - } - } - if (s) s[i] = 0; - return i; -} - - -BOOL CSoundFile::SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX) -//---------------------------------------------------------------------------- -{ - BOOL bReset = FALSE; - DWORD d = gdwSoundSetup & ~SNDMIX_ENABLEMMX; - if (bMMX) d |= SNDMIX_ENABLEMMX; - if ((gdwMixingFreq != nRate) || (gnBitsPerSample != nBits) || (gnChannels != nChannels) || (d != gdwSoundSetup)) bReset = TRUE; - gnChannels = nChannels; - gdwSoundSetup = d; - gdwMixingFreq = nRate; - gnBitsPerSample = nBits; - InitPlayer(bReset); - return TRUE; -} - -BOOL CSoundFile::SetMixConfig(UINT nStereoSeparation, UINT nMaxMixChannels) -//------------------------------------------------------------------------- -{ - if (nMaxMixChannels < 2) return FALSE; - - m_nMaxMixChannels = nMaxMixChannels; - m_nStereoSeparation = nStereoSeparation; - return TRUE; -} - - -BOOL CSoundFile::SetResamplingMode(UINT nMode) -//-------------------------------------------- -{ - DWORD d = gdwSoundSetup & ~(SNDMIX_NORESAMPLING|SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE); - switch(nMode) - { - case SRCMODE_NEAREST: d |= SNDMIX_NORESAMPLING; break; - case SRCMODE_LINEAR: break; - case SRCMODE_SPLINE: d |= SNDMIX_HQRESAMPLER; break; - case SRCMODE_POLYPHASE: d |= (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE); break; - default: - return FALSE; - } - gdwSoundSetup = d; - return TRUE; -} - - -BOOL CSoundFile::SetMasterVolume(UINT nVol, BOOL bAdjustAGC) -//---------------------------------------------------------- -{ - if (nVol < 1) nVol = 1; - if (nVol > 0x200) nVol = 0x200; // x4 maximum - if ((nVol < m_nMasterVolume) && (nVol) && (gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC)) - { - gnAGC = gnAGC * m_nMasterVolume / nVol; - if (gnAGC > AGC_UNITY) gnAGC = AGC_UNITY; - } - m_nMasterVolume = nVol; - return TRUE; -} - - -void CSoundFile::SetAGC(BOOL b) -//----------------------------- -{ - if (b) - { - if (!(gdwSoundSetup & SNDMIX_AGC)) - { - gdwSoundSetup |= SNDMIX_AGC; - gnAGC = AGC_UNITY; - } - } else gdwSoundSetup &= ~SNDMIX_AGC; -} - - -UINT CSoundFile::GetNumPatterns() const -//------------------------------------- -{ - UINT i = 0; - while ((i < MAX_ORDERS) && (Order[i] < 0xFF)) i++; - return i; -} - - -UINT CSoundFile::GetNumInstruments() const -//---------------------------------------- -{ - UINT n=0; - for (UINT i=0; i= MAX_ORDERS) - || (Order[nPattern] >= MAX_PATTERNS) - || (nPos >= PatternSize[Order[nPattern]])) - { - nPos = 0; - nPattern = 0; - } - UINT nRow = nPos; - if ((nRow) && (Order[nPattern] < MAX_PATTERNS)) - { - MODCOMMAND *p = Patterns[Order[nPattern]]; - if ((p) && (nRow < PatternSize[Order[nPattern]])) - { - BOOL bOk = FALSE; - while ((!bOk) && (nRow > 0)) - { - UINT n = nRow * m_nChannels; - for (UINT k=0; k= MAX_ORDERS) || (Order[nPos] >= MAX_PATTERNS)) return; - for (UINT j=0; j= MAX_PATTERNS) || (!Patterns[nPat])) - { - m_dwSongFlags &= ~SONG_PATTERNLOOP; - } else - { - if ((nRow < 0) || (nRow >= PatternSize[nPat])) nRow = 0; - m_nPattern = nPat; - m_nRow = m_nNextRow = nRow; - m_nTickCount = m_nMusicSpeed; - m_nPatternDelay = 0; - m_nFrameDelay = 0; - m_nBufferCount = 0; - m_dwSongFlags |= SONG_PATTERNLOOP; - } -} - - -UINT CSoundFile::GetBestSaveFormat() const -//---------------------------------------- -{ - if ((!m_nSamples) || (!m_nChannels)) return MOD_TYPE_NONE; - if (!m_nType) return MOD_TYPE_NONE; - if (m_nType & (MOD_TYPE_MOD|MOD_TYPE_OKT)) - return MOD_TYPE_MOD; - if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_ULT|MOD_TYPE_FAR|MOD_TYPE_PTM)) - return MOD_TYPE_S3M; - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MTM|MOD_TYPE_MT2)) - return MOD_TYPE_XM; - return MOD_TYPE_IT; -} - - -UINT CSoundFile::GetSaveFormats() const -//------------------------------------- -{ - UINT n = 0; - if ((!m_nSamples) || (!m_nChannels) || (m_nType == MOD_TYPE_NONE)) return 0; - switch(m_nType) - { - case MOD_TYPE_MOD: n = MOD_TYPE_MOD; break; - case MOD_TYPE_S3M: n = MOD_TYPE_S3M; break; - } - n |= MOD_TYPE_XM | MOD_TYPE_IT; - if (!m_nInstruments) - { - if (m_nSamples < 32) n |= MOD_TYPE_MOD; - n |= MOD_TYPE_S3M; - } - return n; -} - - -UINT CSoundFile::GetSampleName(UINT nSample,LPSTR s) const -//-------------------------------------------------------- -{ - char sztmp[40] = ""; // changed from CHAR - memcpy(sztmp, m_szNames[nSample],32); - sztmp[31] = 0; - if (s) strcpy(s, sztmp); - return strlen(sztmp); -} - - -UINT CSoundFile::GetInstrumentName(UINT nInstr,LPSTR s) const -//----------------------------------------------------------- -{ - char sztmp[40] = ""; // changed from CHAR - if ((nInstr >= MAX_INSTRUMENTS) || (!Headers[nInstr])) - { - if (s) *s = 0; - return 0; - } - INSTRUMENTHEADER *penv = Headers[nInstr]; - memcpy(sztmp, penv->name, 32); - sztmp[31] = 0; - if (s) strcpy(s, sztmp); - return strlen(sztmp); -} - - -#ifndef NO_PACKING -UINT CSoundFile::PackSample(int &sample, int next) -//------------------------------------------------ -{ - UINT i = 0; - int delta = next - sample; - if (delta >= 0) - { - for (i=0; i<7; i++) if (delta <= (int)CompressionTable[i+1]) break; - } else - { - for (i=8; i<15; i++) if (delta >= (int)CompressionTable[i+1]) break; - } - sample += (int)CompressionTable[i]; - return i; -} - - -BOOL CSoundFile::CanPackSample(LPSTR pSample, UINT nLen, UINT nPacking, BYTE *result) -//----------------------------------------------------------------------------------- -{ - int pos, old, oldpos, besttable = 0; - DWORD dwErr, dwTotal, dwResult; - int i,j; - - if (result) *result = 0; - if ((!pSample) || (nLen < 1024)) return FALSE; - // Try packing with different tables - dwResult = 0; - for (j=1; j= dwResult) - { - dwResult = dwErr; - besttable = j; - } - } - memcpy(CompressionTable, UnpackTable[besttable], 16); - if (result) - { - if (dwResult > 100) *result = 100; else *result = (BYTE)dwResult; - } - return (dwResult >= nPacking) ? TRUE : FALSE; -} -#endif // NO_PACKING - -#ifndef MODPLUG_NO_FILESAVE - -UINT CSoundFile::WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen) -//----------------------------------------------------------------------------------- -{ - UINT len = 0, bufcount; - signed char buffer[4096]; - signed char *pSample = (signed char *)pins->pSample; - UINT nLen = pins->nLength; - - if ((nMaxLen) && (nLen > nMaxLen)) nLen = nMaxLen; - if ((!pSample) || (f == NULL) || (!nLen)) return 0; - switch(nFlags) - { -#ifndef NO_PACKING - // 3: 4-bit ADPCM data - case RS_ADPCM4: - { - int pos; - len = (nLen + 1) / 2; - fwrite(CompressionTable, 16, 1, f); - bufcount = 0; - pos = 0; - for (UINT j=0; j= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - len += 16; - } - break; -#endif // NO_PACKING - - // 16-bit samples - case RS_PCM16U: - case RS_PCM16D: - case RS_PCM16S: - { - int16_t *p = (int16_t *)pSample; - int s_old = 0, s_ofs; - len = nLen * 2; - bufcount = 0; - s_ofs = (nFlags == RS_PCM16U) ? 0x8000 : 0; - for (UINT j=0; juFlags & CHN_STEREO) - { - s_new = (s_new + (*p) + 1) >> 1; - p++; - } - if (nFlags == RS_PCM16D) - { - int16_t temp = bswapLE16((int16_t)(s_new - s_old)); - *((int16_t*)(&buffer[bufcount])) = temp; - s_old = s_new; - } else - { - int16_t temp = bswapLE16((int16_t)(s_new + s_ofs)); - *((int16_t *)(&buffer[bufcount])) = temp; - } - bufcount += 2; - if (bufcount >= sizeof(buffer) - 1) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - break; - - - // 8-bit Stereo samples (not interleaved) - case RS_STPCM8S: - case RS_STPCM8U: - case RS_STPCM8D: - { - int s_ofs = (nFlags == RS_STPCM8U) ? 0x80 : 0; - for (UINT iCh=0; iCh<2; iCh++) - { - signed char *p = pSample + iCh; - int s_old = 0; - - bufcount = 0; - for (UINT j=0; j= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - } - len = nLen * 2; - break; - - // 16-bit Stereo samples (not interleaved) - case RS_STPCM16S: - case RS_STPCM16U: - case RS_STPCM16D: - { - int s_ofs = (nFlags == RS_STPCM16U) ? 0x8000 : 0; - for (UINT iCh=0; iCh<2; iCh++) - { - int16_t *p = ((int16_t *)pSample) + iCh; - int s_old = 0; - - bufcount = 0; - for (UINT j=0; j= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - } - len = nLen*4; - break; - - // Stereo signed interleaved - case RS_STIPCM8S: - case RS_STIPCM16S: - len = nLen * 2; - if (nFlags == RS_STIPCM16S) len *= 2; - fwrite(pSample, 1, len, f); - break; - - // Default: assume 8-bit PCM data - default: - len = nLen; - bufcount = 0; - { - signed char *p = pSample; - int sinc = (pins->uFlags & CHN_16BIT) ? 2 : 1; - int s_old = 0, s_ofs = (nFlags == RS_PCM8U) ? 0x80 : 0; - if (pins->uFlags & CHN_16BIT) p++; - for (UINT j=0; juFlags & CHN_STEREO) - { - s_new = (s_new + ((int)*p) + 1) >> 1; - p += sinc; - } - if (nFlags == RS_PCM8D) - { - buffer[bufcount++] = (signed char)(s_new - s_old); - s_old = s_new; - } else - { - buffer[bufcount++] = (signed char)(s_new + s_ofs); - } - if (bufcount >= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - } - return len; -} - -#endif // MODPLUG_NO_FILESAVE - - -// Flags: -// 0 = signed 8-bit PCM data (default) -// 1 = unsigned 8-bit PCM data -// 2 = 8-bit ADPCM data with linear table -// 3 = 4-bit ADPCM data -// 4 = 16-bit ADPCM data with linear table -// 5 = signed 16-bit PCM data -// 6 = unsigned 16-bit PCM data - - -UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength) -//------------------------------------------------------------------------------ -{ - UINT len = 0, mem = pIns->nLength+6; - - // Disable >2Gb samples,(preventing buffer overflow in AllocateSample) - if ((!pIns) || ((int)pIns->nLength < 4) || (!lpMemFile)) return 0; - if (pIns->nLength > MAX_SAMPLE_LENGTH) pIns->nLength = MAX_SAMPLE_LENGTH; - pIns->uFlags &= ~(CHN_16BIT|CHN_STEREO); - if (nFlags & RSF_16BIT) - { - mem *= 2; - pIns->uFlags |= CHN_16BIT; - } - if (nFlags & RSF_STEREO) - { - mem *= 2; - pIns->uFlags |= CHN_STEREO; - } - if ((pIns->pSample = AllocateSample(mem)) == NULL) - { - pIns->nLength = 0; - return 0; - } - switch(nFlags) - { - // 1: 8-bit unsigned PCM data - case RS_PCM8U: - { - len = pIns->nLength; - if (len > dwMemLength) len = pIns->nLength = dwMemLength; - signed char *pSample = pIns->pSample; - for (UINT j=0; jnLength; - if (len > dwMemLength) break; - signed char *pSample = pIns->pSample; - const signed char *p = (const signed char *)lpMemFile; - int delta = 0; - - for (UINT j=0; jnLength + 1) / 2; - if (len > dwMemLength - 16) break; - memcpy(CompressionTable, lpMemFile, 16); - lpMemFile += 16; - signed char *pSample = pIns->pSample; - signed char delta = 0; - for (UINT j=0; j> 4); - delta = (signed char)GetDeltaValue((int)delta, b0); - pSample[0] = delta; - delta = (signed char)GetDeltaValue((int)delta, b1); - pSample[1] = delta; - pSample += 2; - } - len += 16; - } - break; - - // 4: 16-bit ADPCM data with linear table - case RS_PCM16D: - { - len = pIns->nLength * 2; - if (len > dwMemLength) break; - int16_t *pSample = (int16_t *)pIns->pSample; - int16_t *p = (int16_t *)lpMemFile; - int delta16 = 0; - for (UINT j=0; jnLength * 2; - if (len <= dwMemLength) memcpy(pIns->pSample, lpMemFile, len); - int16_t *pSample = (int16_t *)pIns->pSample; - for (UINT j=0; jnLength * 2; - if (len > dwMemLength) len = dwMemLength & ~1; - if (len > 1) - { - signed char *pSample = (signed char *)pIns->pSample; - signed char *pSrc = (signed char *)lpMemFile; - for (UINT j=0; jnLength * 2; - if (len > dwMemLength) break; - int16_t *pSample = (int16_t *)pIns->pSample; - int16_t *pSrc = (int16_t *)lpMemFile; - for (UINT j=0; jnLength * 2; - if (len*2 <= dwMemLength) - { - signed char *pSample = (signed char *)pIns->pSample; - signed char *pSrc = (signed char *)lpMemFile; - for (UINT j=0; jnLength; - signed char *psrc = (signed char *)lpMemFile; - signed char *pSample = (signed char *)pIns->pSample; - if (len*2 > dwMemLength) break; - for (UINT j=0; jnLength; - int16_t *psrc = (int16_t *)lpMemFile; - int16_t *pSample = (int16_t *)pIns->pSample; - if (len*4 > dwMemLength) break; - for (UINT j=0; jpSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT2158)); - else - ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT21516)); - break; - -#ifndef MODPLUG_BASIC_SUPPORT -#ifndef MODPLUG_FASTSOUNDLIB - // 8-bit interleaved stereo samples - case RS_STIPCM8S: - case RS_STIPCM8U: - { - int iadd = 0; - if (nFlags == RS_STIPCM8U) { iadd = -0x80; } - len = pIns->nLength; - if (len*2 > dwMemLength) len = dwMemLength >> 1; - LPBYTE psrc = (LPBYTE)lpMemFile; - LPBYTE pSample = (LPBYTE)pIns->pSample; - for (UINT j=0; jnLength; - if (len*4 > dwMemLength) len = dwMemLength >> 2; - int16_t *psrc = (int16_t *)lpMemFile; - int16_t *pSample = (int16_t *)pIns->pSample; - for (UINT j=0; j 9) - { - const char *psrc = lpMemFile; - char packcharacter = lpMemFile[8], *pdest = (char *)pIns->pSample; - len += bswapLE32(*((LPDWORD)(lpMemFile+4))); - if (len > dwMemLength) len = dwMemLength; - UINT dmax = pIns->nLength; - if (pIns->uFlags & CHN_16BIT) dmax <<= 1; - AMSUnpack(psrc+9, len-9, pdest, dmax, packcharacter); - } - break; - - // PTM 8bit delta to 16-bit sample - case RS_PTM8DTO16: - { - len = pIns->nLength * 2; - if (len > dwMemLength) break; - int8_t *pSample = (int8_t *)pIns->pSample; - int8_t delta8 = 0; - for (UINT j=0; jpSample; - for (UINT j=0; j= 4) - { - LPBYTE pSample = (LPBYTE)pIns->pSample; - LPBYTE ibuf = (LPBYTE)lpMemFile; - DWORD bitbuf = bswapLE32(*((DWORD *)ibuf)); - UINT bitnum = 32; - BYTE dlt = 0, lowbyte = 0; - ibuf += 4; - for (UINT j=0; jnLength; j++) - { - BYTE hibyte; - BYTE sign; - if (nFlags == RS_MDL16) lowbyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 8); - sign = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 1); - if (MDLReadBits(bitbuf, bitnum, ibuf, 1)) - { - hibyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 3); - } else - { - hibyte = 8; - while (!MDLReadBits(bitbuf, bitnum, ibuf, 1)) hibyte += 0x10; - hibyte += MDLReadBits(bitbuf, bitnum, ibuf, 4); - } - if (sign) hibyte = ~hibyte; - dlt += hibyte; - if (nFlags != RS_MDL16) - pSample[j] = dlt; - else - { - pSample[j<<1] = lowbyte; - pSample[(j<<1)+1] = dlt; - } - } - } - break; - - case RS_DMF8: - case RS_DMF16: - len = dwMemLength; - if (len >= 4) - { - UINT maxlen = pIns->nLength; - if (pIns->uFlags & CHN_16BIT) maxlen <<= 1; - LPBYTE ibuf = (LPBYTE)lpMemFile, ibufmax = (LPBYTE)(lpMemFile+dwMemLength); - len = DMFUnpack((LPBYTE)pIns->pSample, ibuf, ibufmax, maxlen); - } - break; - -#ifdef MODPLUG_TRACKER - // PCM 24-bit signed -> load sample, and normalize it to 16-bit - case RS_PCM24S: - case RS_PCM32S: - len = pIns->nLength * 3; - if (nFlags == RS_PCM32S) len += pIns->nLength; - if (len > dwMemLength) break; - if (len > 4*8) - { - UINT slsize = (nFlags == RS_PCM32S) ? 4 : 3; - LPBYTE pSrc = (LPBYTE)lpMemFile; - LONG max = 255; - if (nFlags == RS_PCM32S) pSrc++; - for (UINT j=0; j max) max = l; - if (-l > max) max = -l; - } - max = (max / 128) + 1; - int16_t *pDest = (int16_t *)pIns->pSample; - for (UINT k=0; k load sample, and normalize it to 16-bit - case RS_STIPCM24S: - case RS_STIPCM32S: - len = pIns->nLength * 6; - if (nFlags == RS_STIPCM32S) len += pIns->nLength * 2; - if (len > dwMemLength) break; - if (len > 8*8) - { - UINT slsize = (nFlags == RS_STIPCM32S) ? 4 : 3; - LPBYTE pSrc = (LPBYTE)lpMemFile; - LONG max = 255; - if (nFlags == RS_STIPCM32S) pSrc++; - for (UINT j=0; j max) max = l; - if (-l > max) max = -l; - } - max = (max / 128) + 1; - int16_t *pDest = (int16_t *)pIns->pSample; - for (UINT k=0; knLength; - if (len*4 > dwMemLength) len = dwMemLength >> 2; - LPCBYTE psrc = (LPCBYTE)lpMemFile; - int16_t *pSample = (int16_t *)pIns->pSample; - for (UINT j=0; jnLength; - if (len > dwMemLength) len = pIns->nLength = dwMemLength; - memcpy(pIns->pSample, lpMemFile, len); - break; - } - if (len > dwMemLength) - { - if (pIns->pSample) - { - pIns->nLength = 0; - FreeSample(pIns->pSample); - pIns->pSample = NULL; - } - return 0; - } - AdjustSampleLoop(pIns); - return len; -} - - -void CSoundFile::AdjustSampleLoop(MODINSTRUMENT *pIns) -//---------------------------------------------------- -{ - if (!pIns->pSample) return; - if (pIns->nLength > MAX_SAMPLE_LENGTH) pIns->nLength = MAX_SAMPLE_LENGTH; - if (pIns->nLoopEnd > pIns->nLength) pIns->nLoopEnd = pIns->nLength; - if (pIns->nLoopStart > pIns->nLength+2) pIns->nLoopStart = pIns->nLength+2; - if (pIns->nLoopStart+2 >= pIns->nLoopEnd) - { - pIns->nLoopStart = pIns->nLoopEnd = 0; - pIns->uFlags &= ~CHN_LOOP; - } - UINT len = pIns->nLength; - if (pIns->uFlags & CHN_16BIT) - { - int16_t *pSample = (int16_t *)pIns->pSample; - // Adjust end of sample - if (pIns->uFlags & CHN_STEREO) - { - pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = 0; - pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = 0; - } else - { - pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = 0; - } - if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) - { - // Fix bad loops - if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & MOD_TYPE_S3M)) - { - pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart]; - pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1]; - pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2]; - pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3]; - pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4]; - } - } - } else - { - signed char *pSample = pIns->pSample; -#ifndef MODPLUG_FASTSOUNDLIB - // Crappy samples (except chiptunes) ? - if ((pIns->nLength > 0x100) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M)) - && (!(pIns->uFlags & CHN_STEREO))) - { - int smpend = pSample[pIns->nLength-1], smpfix = 0, kscan; - for (kscan=pIns->nLength-1; kscan>0; kscan--) - { - smpfix = pSample[kscan-1]; - if (smpfix != smpend) break; - } - int delta = smpfix - smpend; - if (((!(pIns->uFlags & CHN_LOOP)) || (kscan > (int)pIns->nLoopEnd)) - && ((delta < -8) || (delta > 8))) - { - while (kscan<(int)pIns->nLength) - { - if (!(kscan & 7)) - { - if (smpfix > 0) smpfix--; - if (smpfix < 0) smpfix++; - } - pSample[kscan] = (signed char)smpfix; - kscan++; - } - } - } -#endif - // Adjust end of sample - if (pIns->uFlags & CHN_STEREO) - { - pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = 0; - pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = 0; - - } else - { - pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = 0; - } - if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) - { - if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M))) - { - pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart]; - pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1]; - pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2]; - pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3]; - pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4]; - } - } - } -} - - -///////////////////////////////////////////////////////////// -// Transpose <-> Frequency conversions - -// returns 8363*2^((transp*128+ftune)/(12*128)) -DWORD CSoundFile::TransposeToFrequency(int transp, int ftune) -//----------------------------------------------------------- -{ - -#ifdef MSC_VER - const float _fbase = 8363; - const float _factor = 1.0f/(12.0f*128.0f); - int result; - DWORD freq; - - transp = (transp << 7) + ftune; - _asm { - fild transp - fld _factor - fmulp st(1), st(0) - fist result - fisub result - f2xm1 - fild result - fld _fbase - fscale - fstp st(1) - fmul st(1), st(0) - faddp st(1), st(0) - fistp freq - } - UINT derr = freq % 11025; - if (derr <= 8) freq -= derr; - if (derr >= 11015) freq += 11025-derr; - derr = freq % 1000; - if (derr <= 5) freq -= derr; - if (derr >= 995) freq += 1000-derr; - return freq; -#else - //---GCCFIX: Removed assembly. - return (DWORD)(8363*pow(2, (double)(transp*128+ftune)/(1536))); -#endif -} - - -// returns 12*128*log2(freq/8363) -int CSoundFile::FrequencyToTranspose(DWORD freq) -//---------------------------------------------- -{ - -#ifdef MSC_VER - const float _f1_8363 = 1.0f / 8363.0f; - const float _factor = 128 * 12; - LONG result; - - if (!freq) return 0; - _asm { - fld _factor - fild freq - fld _f1_8363 - fmulp st(1), st(0) - fyl2x - fistp result - } - return result; -#else - //---GCCFIX: Removed assembly. - return int(1536*(log(freq/8363.0)/log(2.0))); -#endif -} - - -void CSoundFile::FrequencyToTranspose(MODINSTRUMENT *psmp) -//-------------------------------------------------------- -{ - int f2t = FrequencyToTranspose(psmp->nC4Speed); - int transp = f2t >> 7; - int ftune = f2t & 0x7F; - if (ftune > 80) - { - transp++; - ftune -= 128; - } - if (transp > 127) transp = 127; - if (transp < -127) transp = -127; - psmp->RelativeTone = transp; - psmp->nFineTune = ftune; -} - - -void CSoundFile::CheckCPUUsage(UINT nCPU) -//--------------------------------------- -{ - if (nCPU > 100) nCPU = 100; - gnCPUUsage = nCPU; - if (nCPU < 90) - { - m_dwSongFlags &= ~SONG_CPUVERYHIGH; - } else - if ((m_dwSongFlags & SONG_CPUVERYHIGH) && (nCPU >= 94)) - { - UINT i=MAX_CHANNELS; - while (i >= 8) - { - i--; - if (Chn[i].nLength) - { - Chn[i].nLength = Chn[i].nPos = 0; - nCPU -= 2; - if (nCPU < 94) break; - } - } - } else - if (nCPU > 90) - { - m_dwSongFlags |= SONG_CPUVERYHIGH; - } -} - - -BOOL CSoundFile::SetPatternName(UINT nPat, LPCSTR lpszName) -//--------------------------------------------------------- -{ - char szName[MAX_PATTERNNAME] = ""; // changed from CHAR - if (nPat >= MAX_PATTERNS) return FALSE; - if (lpszName) lstrcpyn(szName, lpszName, MAX_PATTERNNAME); - szName[MAX_PATTERNNAME-1] = 0; - if (!m_lpszPatternNames) m_nPatternNames = 0; - if (nPat >= m_nPatternNames) - { - if (!lpszName[0]) return TRUE; - UINT len = (nPat+1)*MAX_PATTERNNAME; - char *p = new char[len]; // changed from CHAR - if (!p) return FALSE; - memset(p, 0, len); - if (m_lpszPatternNames) - { - memcpy(p, m_lpszPatternNames, m_nPatternNames * MAX_PATTERNNAME); - delete [] m_lpszPatternNames; - m_lpszPatternNames = NULL; - } - m_lpszPatternNames = p; - m_nPatternNames = nPat + 1; - } - memcpy(m_lpszPatternNames + nPat * MAX_PATTERNNAME, szName, MAX_PATTERNNAME); - return TRUE; -} - - -BOOL CSoundFile::GetPatternName(UINT nPat, LPSTR lpszName, UINT cbSize) const -//--------------------------------------------------------------------------- -{ - if ((!lpszName) || (!cbSize)) return FALSE; - lpszName[0] = 0; - if (cbSize > MAX_PATTERNNAME) cbSize = MAX_PATTERNNAME; - if ((m_lpszPatternNames) && (nPat < m_nPatternNames)) - { - memcpy(lpszName, m_lpszPatternNames + nPat * MAX_PATTERNNAME, cbSize); - lpszName[cbSize-1] = 0; - return TRUE; - } - return FALSE; -} - - -#ifndef MODPLUG_FASTSOUNDLIB - -UINT CSoundFile::DetectUnusedSamples(BOOL *pbIns) -//----------------------------------------------- -{ - UINT nExt = 0; - - if (!pbIns) return 0; - if (m_nInstruments) - { - memset(pbIns, 0, MAX_SAMPLES * sizeof(BOOL)); - for (UINT ipat=0; ipatnote) && (p->note <= NOTE_MAX)) - { - if ((p->instr) && (p->instr < MAX_INSTRUMENTS)) - { - INSTRUMENTHEADER *penv = Headers[p->instr]; - if (penv) - { - UINT n = penv->Keyboard[p->note-1]; - if (n < MAX_SAMPLES) pbIns[n] = TRUE; - } - } else - { - for (UINT k=1; k<=m_nInstruments; k++) - { - INSTRUMENTHEADER *penv = Headers[k]; - if (penv) - { - UINT n = penv->Keyboard[p->note-1]; - if (n < MAX_SAMPLES) pbIns[n] = TRUE; - } - } - } - } - } - } - } - for (UINT ichk=1; ichk<=m_nSamples; ichk++) - { - if ((!pbIns[ichk]) && (Ins[ichk].pSample)) nExt++; - } - } - return nExt; -} - - -BOOL CSoundFile::RemoveSelectedSamples(BOOL *pbIns) -//------------------------------------------------- -{ - if (!pbIns) return FALSE; - for (UINT j=1; j 1)) m_nSamples--; - } - } - return TRUE; -} - - -BOOL CSoundFile::DestroySample(UINT nSample) -//------------------------------------------ -{ - if ((!nSample) || (nSample >= MAX_SAMPLES)) return FALSE; - if (!Ins[nSample].pSample) return TRUE; - MODINSTRUMENT *pins = &Ins[nSample]; - signed char *pSample = pins->pSample; - pins->pSample = NULL; - pins->nLength = 0; - pins->uFlags &= ~(CHN_16BIT); - for (UINT i=0; i -*/ - -#include -#include -#include "tables.h" - -#ifdef MODPLUG_TRACKER -#define ENABLE_STEREOVU -#endif - -// Volume ramp length, in 1/10 ms -#define VOLUMERAMPLEN 146 // 1.46ms = 64 samples at 44.1kHz - -// VU-Meter -#define VUMETER_DECAY 4 - -// SNDMIX: These are global flags for playback control (first two configurable via SetMixConfig) -UINT CSoundFile::m_nStereoSeparation = 128; -UINT CSoundFile::m_nMaxMixChannels = 32; -LONG CSoundFile::m_nStreamVolume = 0x8000; -// Mixing Configuration (SetWaveConfig) -DWORD CSoundFile::gdwSysInfo = 0; -DWORD CSoundFile::gnChannels = 1; -DWORD CSoundFile::gdwSoundSetup = 0; -DWORD CSoundFile::gdwMixingFreq = 44100; -DWORD CSoundFile::gnBitsPerSample = 16; -// Mixing data initialized in -UINT CSoundFile::gnAGC = AGC_UNITY; -UINT CSoundFile::gnVolumeRampSamples = 64; -UINT CSoundFile::gnVUMeter = 0; -UINT CSoundFile::gnCPUUsage = 0; -LPSNDMIXHOOKPROC CSoundFile::gpSndMixHook = NULL; -PMIXPLUGINCREATEPROC CSoundFile::gpMixPluginCreateProc = NULL; -LONG gnDryROfsVol = 0; -LONG gnDryLOfsVol = 0; -LONG gnRvbROfsVol = 0; -LONG gnRvbLOfsVol = 0; -int gbInitPlugins = 0; - -typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG); - -extern DWORD MPPASMCALL X86_Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); -extern DWORD MPPASMCALL X86_Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); -extern DWORD MPPASMCALL X86_Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); -extern DWORD MPPASMCALL X86_Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); -extern UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC); -extern VOID MPPASMCALL X86_Dither(int *pBuffer, UINT nSamples, UINT nBits); -extern VOID MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples); -extern VOID MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); -extern VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples); - -extern int MixSoundBuffer[MIXBUFFERSIZE*4]; -extern int MixRearBuffer[MIXBUFFERSIZE*2]; -UINT gnReverbSend; - - -// Log tables for pre-amp -// We don't want the tracker to get too loud -const UINT PreAmpTable[16] = -{ - 0x60, 0x60, 0x60, 0x70, // 0-7 - 0x80, 0x88, 0x90, 0x98, // 8-15 - 0xA0, 0xA4, 0xA8, 0xB0, // 16-23 - 0xB4, 0xB8, 0xBC, 0xC0, // 24-31 -}; - -const UINT PreAmpAGCTable[16] = -{ - 0x60, 0x60, 0x60, 0x60, - 0x68, 0x70, 0x78, 0x80, - 0x84, 0x88, 0x8C, 0x90, - 0x94, 0x98, 0x9C, 0xA0, -}; - - -// Return (a*b)/c - no divide error -int _muldiv(long a, long b, long c) -{ -#ifdef MSC_VER - int sign, result; - _asm { - mov eax, a - mov ebx, b - or eax, eax - mov edx, eax - jge aneg - neg eax -aneg: - xor edx, ebx - or ebx, ebx - mov ecx, c - jge bneg - neg ebx -bneg: - xor edx, ecx - or ecx, ecx - mov sign, edx - jge cneg - neg ecx -cneg: - mul ebx - cmp edx, ecx - jae diverr - div ecx - jmp ok -diverr: - mov eax, 0x7fffffff -ok: - mov edx, sign - or edx, edx - jge rneg - neg eax -rneg: - mov result, eax - } - return result; -#else - return ((uint64_t) a * (uint64_t) b ) / c; -#endif -} - - -// Return (a*b+c/2)/c - no divide error -int _muldivr(long a, long b, long c) -{ -#ifdef MSC_VER - int sign, result; - _asm { - mov eax, a - mov ebx, b - or eax, eax - mov edx, eax - jge aneg - neg eax -aneg: - xor edx, ebx - or ebx, ebx - mov ecx, c - jge bneg - neg ebx -bneg: - xor edx, ecx - or ecx, ecx - mov sign, edx - jge cneg - neg ecx -cneg: - mul ebx - mov ebx, ecx - shr ebx, 1 - add eax, ebx - adc edx, 0 - cmp edx, ecx - jae diverr - div ecx - jmp ok -diverr: - mov eax, 0x7fffffff -ok: - mov edx, sign - or edx, edx - jge rneg - neg eax -rneg: - mov result, eax - } - return result; -#else - return ((uint64_t) a * (uint64_t) b + (c >> 1)) / c; -#endif -} - - -BOOL CSoundFile::InitPlayer(BOOL bReset) -//-------------------------------------- -{ - if (m_nMaxMixChannels > MAX_CHANNELS) m_nMaxMixChannels = MAX_CHANNELS; - if (gdwMixingFreq < 4000) gdwMixingFreq = 4000; - if (gdwMixingFreq > MAX_SAMPLE_RATE) gdwMixingFreq = MAX_SAMPLE_RATE; - gnVolumeRampSamples = (gdwMixingFreq * VOLUMERAMPLEN) / 100000; - if (gnVolumeRampSamples < 8) gnVolumeRampSamples = 8; - gnDryROfsVol = gnDryLOfsVol = 0; - gnRvbROfsVol = gnRvbLOfsVol = 0; - if (bReset) - { - gnVUMeter = 0; - gnCPUUsage = 0; - } - gbInitPlugins = (bReset) ? 3 : 1; - InitializeDSP(bReset); - return TRUE; -} - - -BOOL CSoundFile::FadeSong(UINT msec) -//---------------------------------- -{ - LONG nsamples = _muldiv(msec, gdwMixingFreq, 1000); - if (nsamples <= 0) return FALSE; - if (nsamples > 0x100000) nsamples = 0x100000; - m_nBufferCount = nsamples; - LONG nRampLength = m_nBufferCount; - // Ramp everything down - for (UINT noff=0; noff < m_nMixChannels; noff++) - { - MODCHANNEL *pramp = &Chn[ChnMix[noff]]; - if (!pramp) continue; - pramp->nNewLeftVol = pramp->nNewRightVol = 0; - pramp->nRightRamp = (-pramp->nRightVol << VOLUMERAMPPRECISION) / nRampLength; - pramp->nLeftRamp = (-pramp->nLeftVol << VOLUMERAMPPRECISION) / nRampLength; - pramp->nRampRightVol = pramp->nRightVol << VOLUMERAMPPRECISION; - pramp->nRampLeftVol = pramp->nLeftVol << VOLUMERAMPPRECISION; - pramp->nRampLength = nRampLength; - pramp->dwFlags |= CHN_VOLUMERAMP; - } - m_dwSongFlags |= SONG_FADINGSONG; - return TRUE; -} - - -BOOL CSoundFile::GlobalFadeSong(UINT msec) -//---------------------------------------- -{ - if (m_dwSongFlags & SONG_GLOBALFADE) return FALSE; - m_nGlobalFadeMaxSamples = _muldiv(msec, gdwMixingFreq, 1000); - m_nGlobalFadeSamples = m_nGlobalFadeMaxSamples; - m_dwSongFlags |= SONG_GLOBALFADE; - return TRUE; -} - - -UINT CSoundFile::Read(LPVOID lpDestBuffer, UINT cbBuffer) -//------------------------------------------------------- -{ - LPBYTE lpBuffer = (LPBYTE)lpDestBuffer; - LPCONVERTPROC pCvt = X86_Convert32To8; - UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0; - LONG nVUMeterMin = 0x7FFFFFFF, nVUMeterMax = -0x7FFFFFFF; - UINT nMaxPlugins; - - { - nMaxPlugins = MAX_MIXPLUGINS; - while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--; - } - m_nMixStat = 0; - lSampleSize = gnChannels; - if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = X86_Convert32To16; } -#ifndef MODPLUG_FASTSOUNDLIB - else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = X86_Convert32To24; } - else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = X86_Convert32To32; } -#endif - lMax = cbBuffer / lSampleSize; - if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0; - lRead = lMax; - if (m_dwSongFlags & SONG_ENDREACHED) goto MixDone; - while (lRead > 0) - { - // Update Channel Data - if (!m_nBufferCount) - { -#ifndef MODPLUG_FASTSOUNDLIB - if (m_dwSongFlags & SONG_FADINGSONG) - { - m_dwSongFlags |= SONG_ENDREACHED; - m_nBufferCount = lRead; - } else -#endif - if (!ReadNote()) - { -#ifndef MODPLUG_FASTSOUNDLIB - if (!FadeSong(FADESONGDELAY)) -#endif - { - m_dwSongFlags |= SONG_ENDREACHED; - if (lRead == lMax) goto MixDone; - m_nBufferCount = lRead; - } - } - } - lCount = m_nBufferCount; - if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE; - if (lCount > lRead) lCount = lRead; - if (!lCount) break; - lSampleCount = lCount; -#ifndef MODPLUG_NO_REVERB - gnReverbSend = 0; -#endif - // Resetting sound buffer - X86_StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol); - if (gnChannels >= 2) - { - lSampleCount *= 2; - m_nMixStat += CreateStereoMix(lCount); - ProcessStereoDSP(lCount); - } else - { - m_nMixStat += CreateStereoMix(lCount); - if (nMaxPlugins) ProcessPlugins(lCount); - ProcessStereoDSP(lCount); - X86_MonoFromStereo(MixSoundBuffer, lCount); - } - nStat++; -#ifndef NO_AGC - // Automatic Gain Control - if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount); -#endif - UINT lTotalSampleCount = lSampleCount; -#ifndef MODPLUG_FASTSOUNDLIB - // Multichannel - if (gnChannels > 2) - { - X86_InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount); - lTotalSampleCount *= 2; - } - // Hook Function - if (gpSndMixHook) - { - gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels); - } -#endif - // Perform clipping + VU-Meter - lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, &nVUMeterMin, &nVUMeterMax); - // Buffer ready - lRead -= lCount; - m_nBufferCount -= lCount; - } -MixDone: - if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize); - // VU-Meter - nVUMeterMin >>= (24-MIXING_ATTENUATION); - nVUMeterMax >>= (24-MIXING_ATTENUATION); - if (nVUMeterMax < nVUMeterMin) nVUMeterMax = nVUMeterMin; - if ((gnVUMeter = (UINT)(nVUMeterMax - nVUMeterMin)) > 0xFF) gnVUMeter = 0xFF; - if (nStat) { m_nMixStat += nStat-1; m_nMixStat /= nStat; } - return lMax - lRead; -} - - - -///////////////////////////////////////////////////////////////////////////// -// Handles navigation/effects - -BOOL CSoundFile::ProcessRow() -//--------------------------- -{ - if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay) - { - m_nPatternDelay = 0; - m_nFrameDelay = 0; - m_nTickCount = 0; - m_nRow = m_nNextRow; - // Reset Pattern Loop Effect - if (m_nCurrentPattern != m_nNextPattern) m_nCurrentPattern = m_nNextPattern; - // Check if pattern is valid - if (!(m_dwSongFlags & SONG_PATTERNLOOP)) - { - m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; - if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; - while (m_nPattern >= MAX_PATTERNS) - { - // End of song ? - if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS)) - { - if (!m_nRepeatCount) - return FALSE; - if (!m_nRestartPos) - { - m_nMusicSpeed = m_nDefaultSpeed; - m_nMusicTempo = m_nDefaultTempo; - m_nGlobalVolume = m_nDefaultGlobalVolume; - for (UINT i=0; i 0) m_nRepeatCount--; - m_nCurrentPattern = m_nRestartPos; - m_nRow = 0; - if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) || (!Patterns[Order[m_nCurrentPattern]])) return FALSE; - } else - { - m_nCurrentPattern++; - } - m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; - if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; - } - m_nNextPattern = m_nCurrentPattern; - } - // Weird stuff? - if ((m_nPattern >= MAX_PATTERNS) || (!Patterns[m_nPattern])) return FALSE; - // Should never happen - if (m_nRow >= PatternSize[m_nPattern]) m_nRow = 0; - m_nNextRow = m_nRow + 1; - if (m_nNextRow >= PatternSize[m_nPattern]) - { - if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1; - m_nNextRow = 0; - } - // Reset channel values - MODCHANNEL *pChn = Chn; - MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels; - for (UINT nChn=0; nChnnRowNote = m->note; - pChn->nRowInstr = m->instr; - pChn->nRowVolCmd = m->volcmd; - pChn->nRowVolume = m->vol; - pChn->nRowCommand = m->command; - pChn->nRowParam = m->param; - - pChn->nLeftVol = pChn->nNewLeftVol; - pChn->nRightVol = pChn->nNewRightVol; - pChn->dwFlags &= ~(CHN_PORTAMENTO | CHN_VIBRATO | CHN_TREMOLO | CHN_PANBRELLO); - pChn->nCommand = 0; - } - } - // Should we process tick0 effects? - if (!m_nMusicSpeed) m_nMusicSpeed = 1; - m_dwSongFlags |= SONG_FIRSTTICK; - if (m_nTickCount) - { - m_dwSongFlags &= ~SONG_FIRSTTICK; - if ((!(m_nType & MOD_TYPE_XM)) && (m_nTickCount < m_nMusicSpeed * (1 + m_nPatternDelay))) - { - if (!(m_nTickCount % m_nMusicSpeed)) m_dwSongFlags |= SONG_FIRSTTICK; - } - - } - // Update Effects - return ProcessEffects(); -} - - -//////////////////////////////////////////////////////////////////////////////////////////// -// Handles envelopes & mixer setup - -BOOL CSoundFile::ReadNote() -//------------------------- -{ - if (!ProcessRow()) return FALSE; - //////////////////////////////////////////////////////////////////////////////////// - m_nTotalCount++; - if (!m_nMusicTempo) return FALSE; - m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8); - // Master Volume + Pre-Amplification / Attenuation setup - DWORD nMasterVol; - { - int nchn32 = (m_nChannels < 32) ? m_nChannels : 31; - if ((m_nType & MOD_TYPE_IT) && (m_nInstruments) && (nchn32 < 6)) nchn32 = 6; - int realmastervol = m_nMasterVolume; - if (realmastervol > 0x80) - { - realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16; - } - UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1]; - DWORD mastervol = (realmastervol * (m_nSongPreAmp + 0x10)) >> 6; - if (mastervol > 0x200) mastervol = 0x200; - if ((m_dwSongFlags & SONG_GLOBALFADE) && (m_nGlobalFadeMaxSamples)) - { - mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples); - } - nMasterVol = (mastervol << 7) / attenuation; - if (nMasterVol > 0x180) nMasterVol = 0x180; - } - //////////////////////////////////////////////////////////////////////////////////// - // Update channels data - m_nMixChannels = 0; - MODCHANNEL *pChn = Chn; - for (UINT nChn=0; nChndwFlags & CHN_NOTEFADE) && (!(pChn->nFadeOutVol|pChn->nRightVol|pChn->nLeftVol))) - { - pChn->nLength = 0; - pChn->nROfs = pChn->nLOfs = 0; - } - // Check for unused channel - if ((pChn->dwFlags & CHN_MUTE) || ((nChn >= m_nChannels) && (!pChn->nLength))) - { - pChn->nVUMeter = 0; -#ifdef ENABLE_STEREOVU - pChn->nLeftVU = pChn->nRightVU = 0; -#endif - continue; - } - // Reset channel data - pChn->nInc = 0; - pChn->nRealVolume = 0; - pChn->nRealPan = pChn->nPan + pChn->nPanSwing; - if (pChn->nRealPan < 0) pChn->nRealPan = 0; - if (pChn->nRealPan > 256) pChn->nRealPan = 256; - pChn->nRampLength = 0; - // Calc Frequency - if ((pChn->nPeriod) && (pChn->nLength)) - { - int vol = pChn->nVolume + pChn->nVolSwing; - - if (vol < 0) vol = 0; - if (vol > 256) vol = 256; - // Tremolo - if (pChn->dwFlags & CHN_TREMOLO) - { - UINT trempos = pChn->nTremoloPos & 0x3F; - if (vol > 0) - { - int tremattn = (m_nType & MOD_TYPE_XM) ? 5 : 6; - switch (pChn->nTremoloType & 0x03) - { - case 1: - vol += (ModRampDownTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn; - break; - case 2: - vol += (ModSquareTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn; - break; - case 3: - vol += (ModRandomTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn; - break; - default: - vol += (ModSinusTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn; - } - } - if ((m_nTickCount) || ((m_nType & (MOD_TYPE_STM|MOD_TYPE_S3M|MOD_TYPE_IT)) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS)))) - { - pChn->nTremoloPos = (trempos + pChn->nTremoloSpeed) & 0x3F; - } - } - // Tremor - if (pChn->nCommand == CMD_TREMOR) - { - UINT n = (pChn->nTremorParam >> 4) + (pChn->nTremorParam & 0x0F); - UINT ontime = pChn->nTremorParam >> 4; - if ((!(m_nType & MOD_TYPE_IT)) || (m_dwSongFlags & SONG_ITOLDEFFECTS)) { n += 2; ontime++; } - UINT tremcount = (UINT)pChn->nTremorCount; - if (tremcount >= n) tremcount = 0; - if ((m_nTickCount) || (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) - { - if (tremcount >= ontime) vol = 0; - pChn->nTremorCount = (BYTE)(tremcount + 1); - } - pChn->dwFlags |= CHN_FASTVOLRAMP; - } - // Clip volume - if (vol < 0) vol = 0; - if (vol > 0x100) vol = 0x100; - vol <<= 6; - // Process Envelopes - if (pChn->pHeader) - { - INSTRUMENTHEADER *penv = pChn->pHeader; - // Volume Envelope - if ((pChn->dwFlags & CHN_VOLENV) && (penv->nVolEnv)) - { - int envpos = pChn->nVolEnvPosition; - UINT pt = penv->nVolEnv - 1; - for (UINT i=0; i<(UINT)(penv->nVolEnv-1); i++) - { - if (envpos <= penv->VolPoints[i]) - { - pt = i; - break; - } - } - int x2 = penv->VolPoints[pt]; - int x1, envvol; - if (envpos >= x2) - { - envvol = penv->VolEnv[pt] << 2; - x1 = x2; - } else - if (pt) - { - envvol = penv->VolEnv[pt-1] << 2; - x1 = penv->VolPoints[pt-1]; - } else - { - envvol = 0; - x1 = 0; - } - if (envpos > x2) envpos = x2; - if ((x2 > x1) && (envpos > x1)) - { - envvol += ((envpos - x1) * (((int)penv->VolEnv[pt]<<2) - envvol)) / (x2 - x1); - } - if (envvol < 0) envvol = 0; - if (envvol > 256) envvol = 256; - vol = (vol * envvol) >> 8; - } - // Panning Envelope - if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv)) - { - int envpos = pChn->nPanEnvPosition; - UINT pt = penv->nPanEnv - 1; - for (UINT i=0; i<(UINT)(penv->nPanEnv-1); i++) - { - if (envpos <= penv->PanPoints[i]) - { - pt = i; - break; - } - } - int x2 = penv->PanPoints[pt], y2 = penv->PanEnv[pt]; - int x1, envpan; - if (envpos >= x2) - { - envpan = y2; - x1 = x2; - } else - if (pt) - { - envpan = penv->PanEnv[pt-1]; - x1 = penv->PanPoints[pt-1]; - } else - { - envpan = 128; - x1 = 0; - } - if ((x2 > x1) && (envpos > x1)) - { - envpan += ((envpos - x1) * (y2 - envpan)) / (x2 - x1); - } - if (envpan < 0) envpan = 0; - if (envpan > 64) envpan = 64; - int pan = pChn->nPan; - if (pan >= 128) - { - pan += ((envpan - 32) * (256 - pan)) / 32; - } else - { - pan += ((envpan - 32) * (pan)) / 32; - } - if (pan < 0) pan = 0; - if (pan > 256) pan = 256; - pChn->nRealPan = pan; - } - // FadeOut volume - if (pChn->dwFlags & CHN_NOTEFADE) - { - UINT fadeout = penv->nFadeOut; - if (fadeout) - { - pChn->nFadeOutVol -= fadeout << 1; - if (pChn->nFadeOutVol <= 0) pChn->nFadeOutVol = 0; - vol = (vol * pChn->nFadeOutVol) >> 16; - } else - if (!pChn->nFadeOutVol) - { - vol = 0; - } - } - // Pitch/Pan separation - if ((penv->nPPS) && (pChn->nRealPan) && (pChn->nNote)) - { - int pandelta = (int)pChn->nRealPan + (int)((int)(pChn->nNote - penv->nPPC - 1) * (int)penv->nPPS) / (int)8; - if (pandelta < 0) pandelta = 0; - if (pandelta > 256) pandelta = 256; - pChn->nRealPan = pandelta; - } - } else - { - // No Envelope: key off => note cut - if (pChn->dwFlags & CHN_NOTEFADE) // 1.41-: CHN_KEYOFF|CHN_NOTEFADE - { - pChn->nFadeOutVol = 0; - vol = 0; - } - } - // vol is 14-bits - if (vol) - { - // IMPORTANT: pChn->nRealVolume is 14 bits !!! - // -> _muldiv( 14+8, 6+6, 18); => RealVolume: 14-bit result (22+12-20) - pChn->nRealVolume = _muldiv(vol * m_nGlobalVolume, pChn->nGlobalVol * pChn->nInsVol, 1 << 20); - } - if (pChn->nPeriod < m_nMinPeriod) pChn->nPeriod = m_nMinPeriod; - int period = pChn->nPeriod; - if ((pChn->dwFlags & (CHN_GLISSANDO|CHN_PORTAMENTO)) == (CHN_GLISSANDO|CHN_PORTAMENTO)) - { - period = GetPeriodFromNote(GetNoteFromPeriod(period), pChn->nFineTune, pChn->nC4Speed); - } - - // Arpeggio ? - if (pChn->nCommand == CMD_ARPEGGIO) - { - switch(m_nTickCount % 3) - { - case 1: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break; - case 2: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break; - } - } - - if (m_dwSongFlags & SONG_AMIGALIMITS) - { - if (period < 113*4) period = 113*4; - if (period > 856*4) period = 856*4; - } - - // Pitch/Filter Envelope - if ((pChn->pHeader) && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->nPitchEnv)) - { - INSTRUMENTHEADER *penv = pChn->pHeader; - int envpos = pChn->nPitchEnvPosition; - UINT pt = penv->nPitchEnv - 1; - for (UINT i=0; i<(UINT)(penv->nPitchEnv-1); i++) - { - if (envpos <= penv->PitchPoints[i]) - { - pt = i; - break; - } - } - int x2 = penv->PitchPoints[pt]; - int x1, envpitch; - if (envpos >= x2) - { - envpitch = (((int)penv->PitchEnv[pt]) - 32) * 8; - x1 = x2; - } else - if (pt) - { - envpitch = (((int)penv->PitchEnv[pt-1]) - 32) * 8; - x1 = penv->PitchPoints[pt-1]; - } else - { - envpitch = 0; - x1 = 0; - } - if (envpos > x2) envpos = x2; - if ((x2 > x1) && (envpos > x1)) - { - int envpitchdest = (((int)penv->PitchEnv[pt]) - 32) * 8; - envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1); - } - if (envpitch < -256) envpitch = -256; - if (envpitch > 256) envpitch = 256; - // Filter Envelope: controls cutoff frequency - if (penv->dwFlags & ENV_FILTER) - { -#ifndef NO_FILTER - SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch); -#endif // NO_FILTER - } else - // Pitch Envelope - { - int l = envpitch; - if (l < 0) - { - l = -l; - if (l > 255) l = 255; - period = _muldiv(period, LinearSlideUpTable[l], 0x10000); - } else - { - if (l > 255) l = 255; - period = _muldiv(period, LinearSlideDownTable[l], 0x10000); - } - } - } - - // Vibrato - if (pChn->dwFlags & CHN_VIBRATO) - { - UINT vibpos = pChn->nVibratoPos; - LONG vdelta; - switch (pChn->nVibratoType & 0x03) - { - case 1: - vdelta = ModRampDownTable[vibpos]; - break; - case 2: - vdelta = ModSquareTable[vibpos]; - break; - case 3: - vdelta = ModRandomTable[vibpos]; - break; - default: - vdelta = ModSinusTable[vibpos]; - } - UINT vdepth = ((m_nType != MOD_TYPE_IT) || (m_dwSongFlags & SONG_ITOLDEFFECTS)) ? 6 : 7; - vdelta = (vdelta * (int)pChn->nVibratoDepth) >> vdepth; - if ((m_dwSongFlags & SONG_LINEARSLIDES) && (m_nType & MOD_TYPE_IT)) - { - LONG l = vdelta; - if (l < 0) - { - l = -l; - vdelta = _muldiv(period, LinearSlideDownTable[l >> 2], 0x10000) - period; - if (l & 0x03) vdelta += _muldiv(period, FineLinearSlideDownTable[l & 0x03], 0x10000) - period; - - } else - { - vdelta = _muldiv(period, LinearSlideUpTable[l >> 2], 0x10000) - period; - if (l & 0x03) vdelta += _muldiv(period, FineLinearSlideUpTable[l & 0x03], 0x10000) - period; - - } - } - period += vdelta; - if ((m_nTickCount) || ((m_nType & MOD_TYPE_IT) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS)))) - { - pChn->nVibratoPos = (vibpos + pChn->nVibratoSpeed) & 0x3F; - } - } - // Panbrello - if (pChn->dwFlags & CHN_PANBRELLO) - { - UINT panpos = ((pChn->nPanbrelloPos+0x10) >> 2) & 0x3F; - LONG pdelta; - switch (pChn->nPanbrelloType & 0x03) - { - case 1: - pdelta = ModRampDownTable[panpos]; - break; - case 2: - pdelta = ModSquareTable[panpos]; - break; - case 3: - pdelta = ModRandomTable[panpos]; - break; - default: - pdelta = ModSinusTable[panpos]; - } - pChn->nPanbrelloPos += pChn->nPanbrelloSpeed; - pdelta = ((pdelta * (int)pChn->nPanbrelloDepth) + 2) >> 3; - pdelta += pChn->nRealPan; - if (pdelta < 0) pdelta = 0; - if (pdelta > 256) pdelta = 256; - pChn->nRealPan = pdelta; - } - int nPeriodFrac = 0; - // Instrument Auto-Vibrato - if ((pChn->pInstrument) && (pChn->pInstrument->nVibDepth)) - { - MODINSTRUMENT *pins = pChn->pInstrument; - if (pins->nVibSweep == 0) - { - pChn->nAutoVibDepth = pins->nVibDepth << 8; - } else - { - if (m_nType & MOD_TYPE_IT) - { - pChn->nAutoVibDepth += pins->nVibSweep << 3; - } else - if (!(pChn->dwFlags & CHN_KEYOFF)) - { - pChn->nAutoVibDepth += (pins->nVibDepth << 8) / pins->nVibSweep; - } - if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth) - pChn->nAutoVibDepth = pins->nVibDepth << 8; - } - pChn->nAutoVibPos += pins->nVibRate; - int val; - switch(pins->nVibType) - { - case 4: // Random - val = ModRandomTable[pChn->nAutoVibPos & 0x3F]; - pChn->nAutoVibPos++; - break; - case 3: // Ramp Down - val = ((0x40 - (pChn->nAutoVibPos >> 1)) & 0x7F) - 0x40; - break; - case 2: // Ramp Up - val = ((0x40 + (pChn->nAutoVibPos >> 1)) & 0x7f) - 0x40; - break; - case 1: // Square - val = (pChn->nAutoVibPos & 128) ? +64 : -64; - break; - default: // Sine - val = ft2VibratoTable[pChn->nAutoVibPos & 255]; - } - int n = ((val * pChn->nAutoVibDepth) >> 8); - if (m_nType & MOD_TYPE_IT) - { - int df1, df2; - if (n < 0) - { - n = -n; - UINT n1 = n >> 8; - df1 = LinearSlideUpTable[n1]; - df2 = LinearSlideUpTable[n1+1]; - } else - { - UINT n1 = n >> 8; - df1 = LinearSlideDownTable[n1]; - df2 = LinearSlideDownTable[n1+1]; - } - n >>= 2; - period = _muldiv(period, df1 + ((df2-df1)*(n&0x3F)>>6), 256); - nPeriodFrac = period & 0xFF; - period >>= 8; - } else - { - period += (n >> 6); - } - } - // Final Period - if (period <= m_nMinPeriod) - { - if (m_nType & MOD_TYPE_S3M) pChn->nLength = 0; - period = m_nMinPeriod; - } - if (period > m_nMaxPeriod) - { - if ((m_nType & MOD_TYPE_IT) || (period >= 0x100000)) - { - pChn->nFadeOutVol = 0; - pChn->dwFlags |= CHN_NOTEFADE; - pChn->nRealVolume = 0; - } - period = m_nMaxPeriod; - nPeriodFrac = 0; - } - UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac); - if ((m_nType & MOD_TYPE_IT) && (freq < 256)) - { - pChn->nFadeOutVol = 0; - pChn->dwFlags |= CHN_NOTEFADE; - pChn->nRealVolume = 0; - } - UINT ninc = _muldiv(freq, 0x10000, gdwMixingFreq); - if ((ninc >= 0xFFB0) && (ninc <= 0x10090)) ninc = 0x10000; - if (m_nFreqFactor != 128) ninc = (ninc * m_nFreqFactor) >> 7; - if (ninc > 0xFF0000) ninc = 0xFF0000; - pChn->nInc = (ninc+1) & ~3; - } - - // Increment envelope position - if (pChn->pHeader) - { - INSTRUMENTHEADER *penv = pChn->pHeader; - // Volume Envelope - if (pChn->dwFlags & CHN_VOLENV) - { - // Increase position - pChn->nVolEnvPosition++; - // Volume Loop ? - if (penv->dwFlags & ENV_VOLLOOP) - { - UINT volloopend = penv->VolPoints[penv->nVolLoopEnd]; - if (m_nType != MOD_TYPE_XM) volloopend++; - if (pChn->nVolEnvPosition == volloopend) - { - pChn->nVolEnvPosition = penv->VolPoints[penv->nVolLoopStart]; - if ((penv->nVolLoopEnd == penv->nVolLoopStart) && (!penv->VolEnv[penv->nVolLoopStart]) - && ((!(m_nType & MOD_TYPE_XM)) || (penv->nVolLoopEnd+1 == penv->nVolEnv))) - { - pChn->dwFlags |= CHN_NOTEFADE; - pChn->nFadeOutVol = 0; - } - } - } - // Volume Sustain ? - if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) - { - if (pChn->nVolEnvPosition == (UINT)penv->VolPoints[penv->nVolSustainEnd]+1) - pChn->nVolEnvPosition = penv->VolPoints[penv->nVolSustainBegin]; - } else - // End of Envelope ? - if (pChn->nVolEnvPosition > penv->VolPoints[penv->nVolEnv - 1]) - { - if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE; - pChn->nVolEnvPosition = penv->VolPoints[penv->nVolEnv - 1]; - if ((!penv->VolEnv[penv->nVolEnv-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT))) - { - pChn->dwFlags |= CHN_NOTEFADE; - pChn->nFadeOutVol = 0; - - pChn->nRealVolume = 0; - } - } - } - // Panning Envelope - if (pChn->dwFlags & CHN_PANENV) - { - pChn->nPanEnvPosition++; - if (penv->dwFlags & ENV_PANLOOP) - { - UINT panloopend = penv->PanPoints[penv->nPanLoopEnd]; - if (m_nType != MOD_TYPE_XM) panloopend++; - if (pChn->nPanEnvPosition == panloopend) - pChn->nPanEnvPosition = penv->PanPoints[penv->nPanLoopStart]; - } - // Panning Sustain ? - if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (UINT)penv->PanPoints[penv->nPanSustainEnd]+1) - && (!(pChn->dwFlags & CHN_KEYOFF))) - { - // Panning sustained - pChn->nPanEnvPosition = penv->PanPoints[penv->nPanSustainBegin]; - } else - { - if (pChn->nPanEnvPosition > penv->PanPoints[penv->nPanEnv - 1]) - pChn->nPanEnvPosition = penv->PanPoints[penv->nPanEnv - 1]; - } - } - // Pitch Envelope - if (pChn->dwFlags & CHN_PITCHENV) - { - // Increase position - pChn->nPitchEnvPosition++; - // Pitch Loop ? - if (penv->dwFlags & ENV_PITCHLOOP) - { - if (pChn->nPitchEnvPosition >= penv->PitchPoints[penv->nPitchLoopEnd]) - pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchLoopStart]; - } - // Pitch Sustain ? - if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) - { - if (pChn->nPitchEnvPosition == (UINT)penv->PitchPoints[penv->nPitchSustainEnd]+1) - pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchSustainBegin]; - } else - { - if (pChn->nPitchEnvPosition > penv->PitchPoints[penv->nPitchEnv - 1]) - pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchEnv - 1]; - } - } - } -#ifdef MODPLUG_PLAYER - // Limit CPU -> > 80% -> don't ramp - if ((gnCPUUsage >= 80) && (!pChn->nRealVolume)) - { - pChn->nLeftVol = pChn->nRightVol = 0; - } -#endif // MODPLUG_PLAYER - // Volume ramping - pChn->dwFlags &= ~CHN_VOLUMERAMP; - if ((pChn->nRealVolume) || (pChn->nLeftVol) || (pChn->nRightVol)) - pChn->dwFlags |= CHN_VOLUMERAMP; -#ifdef MODPLUG_PLAYER - // Decrease VU-Meter - if (pChn->nVUMeter > VUMETER_DECAY) pChn->nVUMeter -= VUMETER_DECAY; else pChn->nVUMeter = 0; -#endif // MODPLUG_PLAYER -#ifdef ENABLE_STEREOVU - if (pChn->nLeftVU > VUMETER_DECAY) pChn->nLeftVU -= VUMETER_DECAY; else pChn->nLeftVU = 0; - if (pChn->nRightVU > VUMETER_DECAY) pChn->nRightVU -= VUMETER_DECAY; else pChn->nRightVU = 0; -#endif - // Check for too big nInc - if (((pChn->nInc >> 16) + 1) >= (LONG)(pChn->nLoopEnd - pChn->nLoopStart)) pChn->dwFlags &= ~CHN_LOOP; - pChn->nNewRightVol = pChn->nNewLeftVol = 0; - pChn->pCurrentSample = ((pChn->pSample) && (pChn->nLength) && (pChn->nInc)) ? pChn->pSample : NULL; - if (pChn->pCurrentSample) - { - // Update VU-Meter (nRealVolume is 14-bit) -#ifdef MODPLUG_PLAYER - UINT vutmp = pChn->nRealVolume >> (14 - 8); - if (vutmp > 0xFF) vutmp = 0xFF; - if (pChn->nVUMeter >= 0x100) pChn->nVUMeter = vutmp; - vutmp >>= 1; - if (pChn->nVUMeter < vutmp) pChn->nVUMeter = vutmp; -#endif // MODPLUG_PLAYER -#ifdef ENABLE_STEREOVU - UINT vul = (pChn->nRealVolume * pChn->nRealPan) >> 14; - if (vul > 127) vul = 127; - if (pChn->nLeftVU > 127) pChn->nLeftVU = (BYTE)vul; - vul >>= 1; - if (pChn->nLeftVU < vul) pChn->nLeftVU = (BYTE)vul; - UINT vur = (pChn->nRealVolume * (256-pChn->nRealPan)) >> 14; - if (vur > 127) vur = 127; - if (pChn->nRightVU > 127) pChn->nRightVU = (BYTE)vur; - vur >>= 1; - if (pChn->nRightVU < vur) pChn->nRightVU = (BYTE)vur; -#endif -#ifdef MODPLUG_TRACKER - UINT kChnMasterVol = (pChn->dwFlags & CHN_EXTRALOUD) ? 0x100 : nMasterVol; -#else -#define kChnMasterVol nMasterVol -#endif // MODPLUG_TRACKER - // Adjusting volumes - if (gnChannels >= 2) - { - int pan = ((int)pChn->nRealPan) - 128; - pan *= (int)m_nStereoSeparation; - pan /= 128; - pan += 128; - - if (pan < 0) pan = 0; - if (pan > 256) pan = 256; -#ifndef MODPLUG_FASTSOUNDLIB - if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan; -#endif - LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1); - if (gdwSoundSetup & SNDMIX_SOFTPANNING) - { - if (pan < 128) - { - pChn->nNewLeftVol = (realvol * pan) >> 8; - pChn->nNewRightVol = (realvol * 128) >> 8; - } else - { - pChn->nNewLeftVol = (realvol * 128) >> 8; - pChn->nNewRightVol = (realvol * (256 - pan)) >> 8; - } - } else - { - pChn->nNewLeftVol = (realvol * pan) >> 8; - pChn->nNewRightVol = (realvol * (256 - pan)) >> 8; - } - } else - { - pChn->nNewRightVol = (pChn->nRealVolume * kChnMasterVol) >> 8; - pChn->nNewLeftVol = pChn->nNewRightVol; - } - // Clipping volumes - if (pChn->nNewRightVol > 0xFFFF) pChn->nNewRightVol = 0xFFFF; - if (pChn->nNewLeftVol > 0xFFFF) pChn->nNewLeftVol = 0xFFFF; - // Check IDO - if (gdwSoundSetup & SNDMIX_NORESAMPLING) - { - pChn->dwFlags |= CHN_NOIDO; - } else - { - pChn->dwFlags &= ~(CHN_NOIDO|CHN_HQSRC); - if( pChn->nInc == 0x10000 ) - { pChn->dwFlags |= CHN_NOIDO; - } - else - { if( ((gdwSoundSetup & SNDMIX_HQRESAMPLER) == 0) && ((gdwSoundSetup & SNDMIX_ULTRAHQSRCMODE) == 0) ) - { if (pChn->nInc >= 0xFF00) pChn->dwFlags |= CHN_NOIDO; - } - } - } - pChn->nNewRightVol >>= MIXING_ATTENUATION; - pChn->nNewLeftVol >>= MIXING_ATTENUATION; - pChn->nRightRamp = pChn->nLeftRamp = 0; - // Dolby Pro-Logic Surround - if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2)) pChn->nNewLeftVol = - pChn->nNewLeftVol; - // Checking Ping-Pong Loops - if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc; - // Setting up volume ramp - if ((pChn->dwFlags & CHN_VOLUMERAMP) - && ((pChn->nRightVol != pChn->nNewRightVol) - || (pChn->nLeftVol != pChn->nNewLeftVol))) - { - LONG nRampLength = gnVolumeRampSamples; - LONG nRightDelta = ((pChn->nNewRightVol - pChn->nRightVol) << VOLUMERAMPPRECISION); - LONG nLeftDelta = ((pChn->nNewLeftVol - pChn->nLeftVol) << VOLUMERAMPPRECISION); -#ifndef MODPLUG_FASTSOUNDLIB - if ((gdwSoundSetup & SNDMIX_DIRECTTODISK) - || ((gdwSysInfo & (SYSMIX_ENABLEMMX|SYSMIX_FASTCPU)) - && (gdwSoundSetup & SNDMIX_HQRESAMPLER) && (gnCPUUsage <= 20))) - { - if ((pChn->nRightVol|pChn->nLeftVol) && (pChn->nNewRightVol|pChn->nNewLeftVol) && (!(pChn->dwFlags & CHN_FASTVOLRAMP))) - { - nRampLength = m_nBufferCount; - if (nRampLength > (1 << (VOLUMERAMPPRECISION-1))) nRampLength = (1 << (VOLUMERAMPPRECISION-1)); - if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples; - } - } -#endif - pChn->nRightRamp = nRightDelta / nRampLength; - pChn->nLeftRamp = nLeftDelta / nRampLength; - pChn->nRightVol = pChn->nNewRightVol - ((pChn->nRightRamp * nRampLength) >> VOLUMERAMPPRECISION); - pChn->nLeftVol = pChn->nNewLeftVol - ((pChn->nLeftRamp * nRampLength) >> VOLUMERAMPPRECISION); - if (pChn->nRightRamp|pChn->nLeftRamp) - { - pChn->nRampLength = nRampLength; - } else - { - pChn->dwFlags &= ~CHN_VOLUMERAMP; - pChn->nRightVol = pChn->nNewRightVol; - pChn->nLeftVol = pChn->nNewLeftVol; - } - } else - { - pChn->dwFlags &= ~CHN_VOLUMERAMP; - pChn->nRightVol = pChn->nNewRightVol; - pChn->nLeftVol = pChn->nNewLeftVol; - } - pChn->nRampRightVol = pChn->nRightVol << VOLUMERAMPPRECISION; - pChn->nRampLeftVol = pChn->nLeftVol << VOLUMERAMPPRECISION; - // Adding the channel in the channel list - ChnMix[m_nMixChannels++] = nChn; - if (m_nMixChannels >= MAX_CHANNELS) break; - } else - { -#ifdef ENABLE_STEREOVU - // Note change but no sample - if (pChn->nLeftVU > 128) pChn->nLeftVU = 0; - if (pChn->nRightVU > 128) pChn->nRightVU = 0; -#endif - if (pChn->nVUMeter > 0xFF) pChn->nVUMeter = 0; - pChn->nLeftVol = pChn->nRightVol = 0; - pChn->nLength = 0; - } - } - // Checking Max Mix Channels reached: ordering by volume - if ((m_nMixChannels >= m_nMaxMixChannels) && (!(gdwSoundSetup & SNDMIX_DIRECTTODISK))) - { - for (UINT i=0; i m_nBufferCount) - m_nGlobalFadeSamples -= m_nBufferCount; - else - m_nGlobalFadeSamples = 0; - } - return TRUE; -} - - diff --git a/jni/tables.h b/jni/tables.h deleted file mode 100644 index ebe5cea..0000000 --- a/jni/tables.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Olivier Lapicque - */ - -#include -#include - -#ifndef MODPLUG_FASTSOUNDLIB -//#pragma data_seg(".tables") -#endif - -static const BYTE ImpulseTrackerPortaVolCmd[16] = -{ - 0x00, 0x01, 0x04, 0x08, 0x10, 0x20, 0x40, 0x60, - 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -// Period table for Protracker octaves 0-5: -static const WORD ProTrackerPeriodTable[6*12] = -{ - 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907, - 856,808,762,720,678,640,604,570,538,508,480,453, - 428,404,381,360,339,320,302,285,269,254,240,226, - 214,202,190,180,170,160,151,143,135,127,120,113, - 107,101,95,90,85,80,75,71,67,63,60,56, - 53,50,47,45,42,40,37,35,33,31,30,28 -}; - - -static const WORD ProTrackerTunedPeriods[16*12] = -{ - 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907, - 1700,1604,1514,1430,1348,1274,1202,1134,1070,1010,954,900, - 1688,1592,1504,1418,1340,1264,1194,1126,1064,1004,948,894, - 1676,1582,1492,1408,1330,1256,1184,1118,1056,996,940,888, - 1664,1570,1482,1398,1320,1246,1176,1110,1048,990,934,882, - 1652,1558,1472,1388,1310,1238,1168,1102,1040,982,926,874, - 1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920,868, - 1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914,862, - 1814,1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960, - 1800,1700,1604,1514,1430,1350,1272,1202,1134,1070,1010,954, - 1788,1688,1592,1504,1418,1340,1264,1194,1126,1064,1004,948, - 1774,1676,1582,1492,1408,1330,1256,1184,1118,1056,996,940, - 1762,1664,1570,1482,1398,1320,1246,1176,1110,1048,988,934, - 1750,1652,1558,1472,1388,1310,1238,1168,1102,1040,982,926, - 1736,1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920, - 1724,1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914 -}; - - -// S3M C-4 periods -static const WORD FreqS3MTable[16] = -{ - 1712,1616,1524,1440,1356,1280, - 1208,1140,1076,1016,960,907, - 0,0,0,0 -}; - - -// S3M FineTune frequencies -static const WORD S3MFineTuneTable[16] = -{ - 7895,7941,7985,8046,8107,8169,8232,8280, - 8363,8413,8463,8529,8581,8651,8723,8757, // 8363*2^((i-8)/(12*8)) -}; - - -// Sinus table -static const int16_t ModSinusTable[64] = -{ - 0,12,25,37,49,60,71,81,90,98,106,112,117,122,125,126, - 127,126,125,122,117,112,106,98,90,81,71,60,49,37,25,12, - 0,-12,-25,-37,-49,-60,-71,-81,-90,-98,-106,-112,-117,-122,-125,-126, - -127,-126,-125,-122,-117,-112,-106,-98,-90,-81,-71,-60,-49,-37,-25,-12 -}; - -// Triangle wave table (ramp down) -static const int16_t ModRampDownTable[64] = -{ - 0,-4,-8,-12,-16,-20,-24,-28,-32,-36,-40,-44,-48,-52,-56,-60, - -64,-68,-72,-76,-80,-84,-88,-92,-96,-100,-104,-108,-112,-116,-120,-124, - 127,123,119,115,111,107,103,99,95,91,87,83,79,75,71,67, - 63,59,55,51,47,43,39,35,31,27,23,19,15,11,7,3 -}; - -// Square wave table -static const int16_t ModSquareTable[64] = -{ - 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, - 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, - -127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127, - -127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127 -}; - -// Random wave table -static const int16_t ModRandomTable[64] = -{ - 98,-127,-43,88,102,41,-65,-94,125,20,-71,-86,-70,-32,-16,-96, - 17,72,107,-5,116,-69,-62,-40,10,-61,65,109,-18,-38,-13,-76, - -23,88,21,-94,8,106,21,-112,6,109,20,-88,-30,9,-127,118, - 42,-34,89,-4,-51,-72,21,-29,112,123,84,-101,-92,98,-54,-95 -}; - - -// volume fade tables for Retrig Note: -static const int8_t retrigTable1[16] = -{ 0, 0, 0, 0, 0, 0, 10, 8, 0, 0, 0, 0, 0, 0, 24, 32 }; - -static const int8_t retrigTable2[16] = -{ 0, -1, -2, -4, -8, -16, 0, 0, 0, 1, 2, 4, 8, 16, 0, 0 }; - - - -static const WORD XMPeriodTable[104] = -{ - 907,900,894,887,881,875,868,862,856,850,844,838,832,826,820,814, - 808,802,796,791,785,779,774,768,762,757,752,746,741,736,730,725, - 720,715,709,704,699,694,689,684,678,675,670,665,660,655,651,646, - 640,636,632,628,623,619,614,610,604,601,597,592,588,584,580,575, - 570,567,563,559,555,551,547,543,538,535,532,528,524,520,516,513, - 508,505,502,498,494,491,487,484,480,477,474,470,467,463,460,457, - 453,450,447,443,440,437,434,431 -}; - - -static const uint32_t XMLinearTable[768] = -{ - 535232,534749,534266,533784,533303,532822,532341,531861, - 531381,530902,530423,529944,529466,528988,528511,528034, - 527558,527082,526607,526131,525657,525183,524709,524236, - 523763,523290,522818,522346,521875,521404,520934,520464, - 519994,519525,519057,518588,518121,517653,517186,516720, - 516253,515788,515322,514858,514393,513929,513465,513002, - 512539,512077,511615,511154,510692,510232,509771,509312, - 508852,508393,507934,507476,507018,506561,506104,505647, - 505191,504735,504280,503825,503371,502917,502463,502010, - 501557,501104,500652,500201,499749,499298,498848,498398, - 497948,497499,497050,496602,496154,495706,495259,494812, - 494366,493920,493474,493029,492585,492140,491696,491253, - 490809,490367,489924,489482,489041,488600,488159,487718, - 487278,486839,486400,485961,485522,485084,484647,484210, - 483773,483336,482900,482465,482029,481595,481160,480726, - 480292,479859,479426,478994,478562,478130,477699,477268, - 476837,476407,475977,475548,475119,474690,474262,473834, - 473407,472979,472553,472126,471701,471275,470850,470425, - 470001,469577,469153,468730,468307,467884,467462,467041, - 466619,466198,465778,465358,464938,464518,464099,463681, - 463262,462844,462427,462010,461593,461177,460760,460345, - 459930,459515,459100,458686,458272,457859,457446,457033, - 456621,456209,455797,455386,454975,454565,454155,453745, - 453336,452927,452518,452110,451702,451294,450887,450481, - 450074,449668,449262,448857,448452,448048,447644,447240, - 446836,446433,446030,445628,445226,444824,444423,444022, - 443622,443221,442821,442422,442023,441624,441226,440828, - 440430,440033,439636,439239,438843,438447,438051,437656, - 437261,436867,436473,436079,435686,435293,434900,434508, - 434116,433724,433333,432942,432551,432161,431771,431382, - 430992,430604,430215,429827,429439,429052,428665,428278, - 427892,427506,427120,426735,426350,425965,425581,425197, - 424813,424430,424047,423665,423283,422901,422519,422138, - 421757,421377,420997,420617,420237,419858,419479,419101, - 418723,418345,417968,417591,417214,416838,416462,416086, - 415711,415336,414961,414586,414212,413839,413465,413092, - 412720,412347,411975,411604,411232,410862,410491,410121, - 409751,409381,409012,408643,408274,407906,407538,407170, - 406803,406436,406069,405703,405337,404971,404606,404241, - 403876,403512,403148,402784,402421,402058,401695,401333, - 400970,400609,400247,399886,399525,399165,398805,398445, - 398086,397727,397368,397009,396651,396293,395936,395579, - 395222,394865,394509,394153,393798,393442,393087,392733, - 392378,392024,391671,391317,390964,390612,390259,389907, - 389556,389204,388853,388502,388152,387802,387452,387102, - 386753,386404,386056,385707,385359,385012,384664,384317, - 383971,383624,383278,382932,382587,382242,381897,381552, - 381208,380864,380521,380177,379834,379492,379149,378807, - - 378466,378124,377783,377442,377102,376762,376422,376082, - 375743,375404,375065,374727,374389,374051,373714,373377, - 373040,372703,372367,372031,371695,371360,371025,370690, - 370356,370022,369688,369355,369021,368688,368356,368023, - 367691,367360,367028,366697,366366,366036,365706,365376, - 365046,364717,364388,364059,363731,363403,363075,362747, - 362420,362093,361766,361440,361114,360788,360463,360137, - 359813,359488,359164,358840,358516,358193,357869,357547, - 357224,356902,356580,356258,355937,355616,355295,354974, - 354654,354334,354014,353695,353376,353057,352739,352420, - 352103,351785,351468,351150,350834,350517,350201,349885, - 349569,349254,348939,348624,348310,347995,347682,347368, - 347055,346741,346429,346116,345804,345492,345180,344869, - 344558,344247,343936,343626,343316,343006,342697,342388, - 342079,341770,341462,341154,340846,340539,340231,339924, - 339618,339311,339005,338700,338394,338089,337784,337479, - 337175,336870,336566,336263,335959,335656,335354,335051, - 334749,334447,334145,333844,333542,333242,332941,332641, - 332341,332041,331741,331442,331143,330844,330546,330247, - 329950,329652,329355,329057,328761,328464,328168,327872, - 327576,327280,326985,326690,326395,326101,325807,325513, - 325219,324926,324633,324340,324047,323755,323463,323171, - 322879,322588,322297,322006,321716,321426,321136,320846, - 320557,320267,319978,319690,319401,319113,318825,318538, - 318250,317963,317676,317390,317103,316817,316532,316246, - 315961,315676,315391,315106,314822,314538,314254,313971, - 313688,313405,313122,312839,312557,312275,311994,311712, - 311431,311150,310869,310589,310309,310029,309749,309470, - 309190,308911,308633,308354,308076,307798,307521,307243, - 306966,306689,306412,306136,305860,305584,305308,305033, - 304758,304483,304208,303934,303659,303385,303112,302838, - 302565,302292,302019,301747,301475,301203,300931,300660, - 300388,300117,299847,299576,299306,299036,298766,298497, - 298227,297958,297689,297421,297153,296884,296617,296349, - 296082,295815,295548,295281,295015,294749,294483,294217, - 293952,293686,293421,293157,292892,292628,292364,292100, - 291837,291574,291311,291048,290785,290523,290261,289999, - 289737,289476,289215,288954,288693,288433,288173,287913, - 287653,287393,287134,286875,286616,286358,286099,285841, - 285583,285326,285068,284811,284554,284298,284041,283785, - 283529,283273,283017,282762,282507,282252,281998,281743, - 281489,281235,280981,280728,280475,280222,279969,279716, - 279464,279212,278960,278708,278457,278206,277955,277704, - 277453,277203,276953,276703,276453,276204,275955,275706, - 275457,275209,274960,274712,274465,274217,273970,273722, - 273476,273229,272982,272736,272490,272244,271999,271753, - 271508,271263,271018,270774,270530,270286,270042,269798, - 269555,269312,269069,268826,268583,268341,268099,267857 -}; - - -static const int8_t ft2VibratoTable[256] = -{ - 0,-2,-3,-5,-6,-8,-9,-11,-12,-14,-16,-17,-19,-20,-22,-23, - -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42, - -43,-44,-45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56, - -56,-57,-58,-59,-59,-60,-60,-61,-61,-62,-62,-62,-63,-63, - -63,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-63,-63, - -63,-62,-62,-62,-61,-61,-60,-60,-59,-59,-58,-57,-56,-56, - -55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42, - -41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26,-24,-23, - -22,-20,-19,-17,-16,-14,-12,-11,-9,-8,-6,-5,-3,-2,0, - 2,3,5,6,8,9,11,12,14,16,17,19,20,22,23,24,26,27,29,30, - 32,33,34,36,37,38,39,41,42,43,44,45,46,47,48,49,50,51, - 52,53,54,55,56,56,57,58,59,59,60,60,61,61,62,62,62,63, - 63,63,64,64,64,64,64,64,64,64,64,64,64,63,63,63,62,62, - 62,61,61,60,60,59,59,58,57,56,56,55,54,53,52,51,50,49, - 48,47,46,45,44,43,42,41,39,38,37,36,34,33,32,30,29,27, - 26,24,23,22,20,19,17,16,14,12,11,9,8,6,5,3,2 -}; - - - -static const DWORD FineLinearSlideUpTable[16] = -{ - 65536, 65595, 65654, 65714, 65773, 65832, 65892, 65951, - 66011, 66071, 66130, 66190, 66250, 66309, 66369, 66429 -}; - - -static const DWORD FineLinearSlideDownTable[16] = -{ - 65535, 65477, 65418, 65359, 65300, 65241, 65182, 65123, - 65065, 65006, 64947, 64888, 64830, 64772, 64713, 64645 -}; - - -static const DWORD LinearSlideUpTable[256] = -{ - 65536, 65773, 66010, 66249, 66489, 66729, 66971, 67213, - 67456, 67700, 67945, 68190, 68437, 68685, 68933, 69182, - 69432, 69684, 69936, 70189, 70442, 70697, 70953, 71209, - 71467, 71725, 71985, 72245, 72507, 72769, 73032, 73296, - 73561, 73827, 74094, 74362, 74631, 74901, 75172, 75444, - 75717, 75991, 76265, 76541, 76818, 77096, 77375, 77655, - 77935, 78217, 78500, 78784, 79069, 79355, 79642, 79930, - 80219, 80509, 80800, 81093, 81386, 81680, 81976, 82272, - 82570, 82868, 83168, 83469, 83771, 84074, 84378, 84683, - 84989, 85297, 85605, 85915, 86225, 86537, 86850, 87164, - 87480, 87796, 88113, 88432, 88752, 89073, 89395, 89718, - 90043, 90369, 90695, 91023, 91353, 91683, 92015, 92347, - 92681, 93017, 93353, 93691, 94029, 94370, 94711, 95053, - 95397, 95742, 96088, 96436, 96785, 97135, 97486, 97839, - 98193, 98548, 98904, 99262, 99621, 99981, 100343, 100706, - 101070, 101435, 101802, 102170, 102540, 102911, 103283, 103657, - 104031, 104408, 104785, 105164, 105545, 105926, 106309, 106694, - 107080, 107467, 107856, 108246, 108637, 109030, 109425, 109820, - 110217, 110616, 111016, 111418, 111821, 112225, 112631, 113038, - 113447, 113857, 114269, 114682, 115097, 115514, 115931, 116351, - 116771, 117194, 117618, 118043, 118470, 118898, 119328, 119760, - 120193, 120628, 121064, 121502, 121941, 122382, 122825, 123269, - 123715, 124162, 124611, 125062, 125514, 125968, 126424, 126881, - 127340, 127801, 128263, 128727, 129192, 129660, 130129, 130599, - 131072, 131546, 132021, 132499, 132978, 133459, 133942, 134426, - 134912, 135400, 135890, 136381, 136875, 137370, 137866, 138365, - 138865, 139368, 139872, 140378, 140885, 141395, 141906, 142419, - 142935, 143451, 143970, 144491, 145014, 145538, 146064, 146593, - 147123, 147655, 148189, 148725, 149263, 149803, 150344, 150888, - 151434, 151982, 152531, 153083, 153637, 154192, 154750, 155310, - 155871, 156435, 157001, 157569, 158138, 158710, 159284, 159860, - 160439, 161019, 161601, 162186, 162772, 163361, 163952, 164545, -}; - - -static const DWORD LinearSlideDownTable[256] = -{ - 65536, 65299, 65064, 64830, 64596, 64363, 64131, 63900, - 63670, 63440, 63212, 62984, 62757, 62531, 62305, 62081, - 61857, 61634, 61412, 61191, 60970, 60751, 60532, 60314, - 60096, 59880, 59664, 59449, 59235, 59021, 58809, 58597, - 58385, 58175, 57965, 57757, 57548, 57341, 57134, 56928, - 56723, 56519, 56315, 56112, 55910, 55709, 55508, 55308, - 55108, 54910, 54712, 54515, 54318, 54123, 53928, 53733, - - 53540, 53347, 53154, 52963, 52772, 52582, 52392, 52204, - 52015, 51828, 51641, 51455, 51270, 51085, 50901, 50717, - 50535, 50353, 50171, 49990, 49810, 49631, 49452, 49274, - 49096, 48919, 48743, 48567, 48392, 48218, 48044, 47871, - 47698, 47526, 47355, 47185, 47014, 46845, 46676, 46508, - 46340, 46173, 46007, 45841, 45676, 45511, 45347, 45184, - 45021, 44859, 44697, 44536, 44376, 44216, 44056, 43898, - 43740, 43582, 43425, 43268, 43112, 42957, 42802, 42648, - 42494, 42341, 42189, 42037, 41885, 41734, 41584, 41434, - 41285, 41136, 40988, 40840, 40693, 40546, 40400, 40254, - 40109, 39965, 39821, 39677, 39534, 39392, 39250, 39108, - 38967, 38827, 38687, 38548, 38409, 38270, 38132, 37995, - 37858, 37722, 37586, 37450, 37315, 37181, 37047, 36913, - 36780, 36648, 36516, 36384, 36253, 36122, 35992, 35862, - 35733, 35604, 35476, 35348, 35221, 35094, 34968, 34842, - 34716, 34591, 34466, 34342, 34218, 34095, 33972, 33850, - 33728, 33606, 33485, 33364, 33244, 33124, 33005, 32886, - 32768, 32649, 32532, 32415, 32298, 32181, 32065, 31950, - 31835, 31720, 31606, 31492, 31378, 31265, 31152, 31040, - 30928, 30817, 30706, 30595, 30485, 30375, 30266, 30157, - 30048, 29940, 29832, 29724, 29617, 29510, 29404, 29298, - 29192, 29087, 28982, 28878, 28774, 28670, 28567, 28464, - 28361, 28259, 28157, 28056, 27955, 27854, 27754, 27654, - 27554, 27455, 27356, 27257, 27159, 27061, 26964, 26866, - 26770, 26673, 26577, 26481, 26386, 26291, 26196, 26102, -}; - - -static const int SpectrumSinusTable[256*2] = -{ - 0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11, - 12, 13, 14, 14, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, - 24, 25, 25, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34, 34, - 35, 36, 36, 37, 38, 38, 39, 39, 40, 41, 41, 42, 42, 43, 44, 44, - 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, - 53, 53, 53, 54, 54, 55, 55, 55, 56, 56, 57, 57, 57, 58, 58, 58, - 59, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 61, 61, 62, 62, 62, - 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 62, - 62, 62, 62, 62, 61, 61, 61, 61, 61, 60, 60, 60, 60, 59, 59, 59, - 59, 58, 58, 58, 57, 57, 57, 56, 56, 55, 55, 55, 54, 54, 53, 53, - 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, - 45, 44, 44, 43, 42, 42, 41, 41, 40, 39, 39, 38, 38, 37, 36, 36, - 35, 34, 34, 33, 32, 32, 31, 30, 30, 29, 28, 28, 27, 26, 25, 25, - 24, 23, 22, 22, 21, 20, 20, 19, 18, 17, 17, 16, 15, 14, 14, 13, - 12, 11, 10, 10, 9, 8, 7, 7, 6, 5, 4, 3, 3, 2, 1, 0, - 0, -1, -1, -2, -3, -3, -4, -5, -6, -7, -7, -8, -9, -10, -10, -11, - -12, -13, -14, -14, -15, -16, -17, -17, -18, -19, -20, -20, -21, -22, -22, -23, - -24, -25, -25, -26, -27, -28, -28, -29, -30, -30, -31, -32, -32, -33, -34, -34, - -35, -36, -36, -37, -38, -38, -39, -39, -40, -41, -41, -42, -42, -43, -44, -44, - -45, -45, -46, -46, -47, -47, -48, -48, -49, -49, -50, -50, -51, -51, -52, -52, - -53, -53, -53, -54, -54, -55, -55, -55, -56, -56, -57, -57, -57, -58, -58, -58, - -59, -59, -59, -59, -60, -60, -60, -60, -61, -61, -61, -61, -61, -62, -62, -62, - -62, -62, -62, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, - -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -62, -62, - -62, -62, -62, -62, -61, -61, -61, -61, -61, -60, -60, -60, -60, -59, -59, -59, - -59, -58, -58, -58, -57, -57, -57, -56, -56, -55, -55, -55, -54, -54, -53, -53, - -53, -52, -52, -51, -51, -50, -50, -49, -49, -48, -48, -47, -47, -46, -46, -45, - -45, -44, -44, -43, -42, -42, -41, -41, -40, -39, -39, -38, -38, -37, -36, -36, - -35, -34, -34, -33, -32, -32, -31, -30, -30, -29, -28, -28, -27, -26, -25, -25, - -24, -23, -22, -22, -21, -20, -20, -19, -18, -17, -17, -16, -15, -14, -14, -13, - -12, -11, -10, -10, -9, -8, -7, -7, -6, -5, -4, -3, -3, -2, -1, 0, -}; - diff --git a/project.properties b/project.properties deleted file mode 100644 index b7c2081..0000000 --- a/project.properties +++ /dev/null @@ -1,14 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-10 diff --git a/res/drawable-hdpi/app_frozen_bubble.png b/res/drawable-hdpi/app_frozen_bubble.png deleted file mode 100644 index c5407b9..0000000 Binary files a/res/drawable-hdpi/app_frozen_bubble.png and /dev/null differ diff --git a/res/drawable-ldpi/app_frozen_bubble.png b/res/drawable-ldpi/app_frozen_bubble.png deleted file mode 100644 index d47ebe0..0000000 Binary files a/res/drawable-ldpi/app_frozen_bubble.png and /dev/null differ diff --git a/res/drawable-mdpi/app_frozen_bubble.png b/res/drawable-mdpi/app_frozen_bubble.png deleted file mode 100644 index 9516c4d..0000000 Binary files a/res/drawable-mdpi/app_frozen_bubble.png and /dev/null differ diff --git a/res/drawable-xhdpi/app_frozen_bubble.png b/res/drawable-xhdpi/app_frozen_bubble.png deleted file mode 100644 index be8a3e1..0000000 Binary files a/res/drawable-xhdpi/app_frozen_bubble.png and /dev/null differ diff --git a/res/drawable/app_frozen_bubble.png b/res/drawable/app_frozen_bubble.png deleted file mode 100644 index 1fe69e7..0000000 Binary files a/res/drawable/app_frozen_bubble.png and /dev/null differ diff --git a/res/drawable/background.jpg b/res/drawable/background.jpg deleted file mode 100644 index efc1993..0000000 Binary files a/res/drawable/background.jpg and /dev/null differ diff --git a/res/drawable/background2.jpg b/res/drawable/background2.jpg deleted file mode 100644 index 3ba5781..0000000 Binary files a/res/drawable/background2.jpg and /dev/null differ diff --git a/res/drawable/banana.png b/res/drawable/banana.png deleted file mode 100644 index 3322337..0000000 Binary files a/res/drawable/banana.png and /dev/null differ diff --git a/res/drawable/bubble_1.png b/res/drawable/bubble_1.png deleted file mode 100644 index 27ec5d9..0000000 Binary files a/res/drawable/bubble_1.png and /dev/null differ diff --git a/res/drawable/bubble_2.png b/res/drawable/bubble_2.png deleted file mode 100644 index 4d6388e..0000000 Binary files a/res/drawable/bubble_2.png and /dev/null differ diff --git a/res/drawable/bubble_3.png b/res/drawable/bubble_3.png deleted file mode 100644 index 6b0bb97..0000000 Binary files a/res/drawable/bubble_3.png and /dev/null differ diff --git a/res/drawable/bubble_4.png b/res/drawable/bubble_4.png deleted file mode 100644 index 06d9e4a..0000000 Binary files a/res/drawable/bubble_4.png and /dev/null differ diff --git a/res/drawable/bubble_5.png b/res/drawable/bubble_5.png deleted file mode 100644 index becb5b9..0000000 Binary files a/res/drawable/bubble_5.png and /dev/null differ diff --git a/res/drawable/bubble_6.png b/res/drawable/bubble_6.png deleted file mode 100644 index 031d2e6..0000000 Binary files a/res/drawable/bubble_6.png and /dev/null differ diff --git a/res/drawable/bubble_7.png b/res/drawable/bubble_7.png deleted file mode 100644 index 622c28d..0000000 Binary files a/res/drawable/bubble_7.png and /dev/null differ diff --git a/res/drawable/bubble_8.png b/res/drawable/bubble_8.png deleted file mode 100644 index 4107187..0000000 Binary files a/res/drawable/bubble_8.png and /dev/null differ diff --git a/res/drawable/bubble_blink.png b/res/drawable/bubble_blink.png deleted file mode 100644 index 9a87ae5..0000000 Binary files a/res/drawable/bubble_blink.png and /dev/null differ diff --git a/res/drawable/bubble_colourblind_1.png b/res/drawable/bubble_colourblind_1.png deleted file mode 100644 index 336f8da..0000000 Binary files a/res/drawable/bubble_colourblind_1.png and /dev/null differ diff --git a/res/drawable/bubble_colourblind_2.png b/res/drawable/bubble_colourblind_2.png deleted file mode 100644 index 588e2cd..0000000 Binary files a/res/drawable/bubble_colourblind_2.png and /dev/null differ diff --git a/res/drawable/bubble_colourblind_3.png b/res/drawable/bubble_colourblind_3.png deleted file mode 100644 index b3ec575..0000000 Binary files a/res/drawable/bubble_colourblind_3.png and /dev/null differ diff --git a/res/drawable/bubble_colourblind_4.png b/res/drawable/bubble_colourblind_4.png deleted file mode 100644 index 08f7120..0000000 Binary files a/res/drawable/bubble_colourblind_4.png and /dev/null differ diff --git a/res/drawable/bubble_colourblind_5.png b/res/drawable/bubble_colourblind_5.png deleted file mode 100644 index eb7a93c..0000000 Binary files a/res/drawable/bubble_colourblind_5.png and /dev/null differ diff --git a/res/drawable/bubble_colourblind_6.png b/res/drawable/bubble_colourblind_6.png deleted file mode 100644 index 9b0dce0..0000000 Binary files a/res/drawable/bubble_colourblind_6.png and /dev/null differ diff --git a/res/drawable/bubble_colourblind_7.png b/res/drawable/bubble_colourblind_7.png deleted file mode 100644 index afd0d14..0000000 Binary files a/res/drawable/bubble_colourblind_7.png and /dev/null differ diff --git a/res/drawable/bubble_colourblind_8.png b/res/drawable/bubble_colourblind_8.png deleted file mode 100644 index 963db50..0000000 Binary files a/res/drawable/bubble_colourblind_8.png and /dev/null differ diff --git a/res/drawable/bubble_font.png b/res/drawable/bubble_font.png deleted file mode 100644 index 4eafe58..0000000 Binary files a/res/drawable/bubble_font.png and /dev/null differ diff --git a/res/drawable/close_eyes.png b/res/drawable/close_eyes.png deleted file mode 100644 index b69d802..0000000 Binary files a/res/drawable/close_eyes.png and /dev/null differ diff --git a/res/drawable/compressor.png b/res/drawable/compressor.png deleted file mode 100644 index 56670a2..0000000 Binary files a/res/drawable/compressor.png and /dev/null differ diff --git a/res/drawable/compressor_body.png b/res/drawable/compressor_body.png deleted file mode 100644 index 7435095..0000000 Binary files a/res/drawable/compressor_body.png and /dev/null differ diff --git a/res/drawable/fixed_1.png b/res/drawable/fixed_1.png deleted file mode 100644 index 75c03a1..0000000 Binary files a/res/drawable/fixed_1.png and /dev/null differ diff --git a/res/drawable/fixed_2.png b/res/drawable/fixed_2.png deleted file mode 100644 index 91a7406..0000000 Binary files a/res/drawable/fixed_2.png and /dev/null differ diff --git a/res/drawable/fixed_3.png b/res/drawable/fixed_3.png deleted file mode 100644 index 792b0eb..0000000 Binary files a/res/drawable/fixed_3.png and /dev/null differ diff --git a/res/drawable/fixed_4.png b/res/drawable/fixed_4.png deleted file mode 100644 index 57ccc25..0000000 Binary files a/res/drawable/fixed_4.png and /dev/null differ diff --git a/res/drawable/fixed_5.png b/res/drawable/fixed_5.png deleted file mode 100644 index b3ed1cb..0000000 Binary files a/res/drawable/fixed_5.png and /dev/null differ diff --git a/res/drawable/fixed_6.png b/res/drawable/fixed_6.png deleted file mode 100644 index 3143b9d..0000000 Binary files a/res/drawable/fixed_6.png and /dev/null differ diff --git a/res/drawable/frozen_1.png b/res/drawable/frozen_1.png deleted file mode 100644 index 473a875..0000000 Binary files a/res/drawable/frozen_1.png and /dev/null differ diff --git a/res/drawable/frozen_2.png b/res/drawable/frozen_2.png deleted file mode 100644 index 49130f8..0000000 Binary files a/res/drawable/frozen_2.png and /dev/null differ diff --git a/res/drawable/frozen_3.png b/res/drawable/frozen_3.png deleted file mode 100644 index 1cd4182..0000000 Binary files a/res/drawable/frozen_3.png and /dev/null differ diff --git a/res/drawable/frozen_4.png b/res/drawable/frozen_4.png deleted file mode 100644 index 6f54b7d..0000000 Binary files a/res/drawable/frozen_4.png and /dev/null differ diff --git a/res/drawable/frozen_5.png b/res/drawable/frozen_5.png deleted file mode 100644 index 861219d..0000000 Binary files a/res/drawable/frozen_5.png and /dev/null differ diff --git a/res/drawable/frozen_6.png b/res/drawable/frozen_6.png deleted file mode 100644 index c9a89d8..0000000 Binary files a/res/drawable/frozen_6.png and /dev/null differ diff --git a/res/drawable/frozen_7.png b/res/drawable/frozen_7.png deleted file mode 100644 index 65129d0..0000000 Binary files a/res/drawable/frozen_7.png and /dev/null differ diff --git a/res/drawable/frozen_8.png b/res/drawable/frozen_8.png deleted file mode 100644 index 0051fb4..0000000 Binary files a/res/drawable/frozen_8.png and /dev/null differ diff --git a/res/drawable/home_screen.jpg b/res/drawable/home_screen.jpg deleted file mode 100644 index 9ce2b4e..0000000 Binary files a/res/drawable/home_screen.jpg and /dev/null differ diff --git a/res/drawable/hurry.png b/res/drawable/hurry.png deleted file mode 100644 index f439295..0000000 Binary files a/res/drawable/hurry.png and /dev/null differ diff --git a/res/drawable/launcher.png b/res/drawable/launcher.png deleted file mode 100644 index 0981793..0000000 Binary files a/res/drawable/launcher.png and /dev/null differ diff --git a/res/drawable/life.png b/res/drawable/life.png deleted file mode 100644 index 9c20d0e..0000000 Binary files a/res/drawable/life.png and /dev/null differ diff --git a/res/drawable/lose_panel.jpg b/res/drawable/lose_panel.jpg deleted file mode 100644 index 9f242f5..0000000 Binary files a/res/drawable/lose_panel.jpg and /dev/null differ diff --git a/res/drawable/pause_button.png b/res/drawable/pause_button.png deleted file mode 100644 index 4ccbdb8..0000000 Binary files a/res/drawable/pause_button.png and /dev/null differ diff --git a/res/drawable/pause_panel.jpg b/res/drawable/pause_panel.jpg deleted file mode 100644 index 48e4eac..0000000 Binary files a/res/drawable/pause_panel.jpg and /dev/null differ diff --git a/res/drawable/penguins.jpg b/res/drawable/penguins.jpg deleted file mode 100644 index 4ac14f7..0000000 Binary files a/res/drawable/penguins.jpg and /dev/null differ diff --git a/res/drawable/penguins2.jpg b/res/drawable/penguins2.jpg deleted file mode 100644 index 8777f32..0000000 Binary files a/res/drawable/penguins2.jpg and /dev/null differ diff --git a/res/drawable/play_button.png b/res/drawable/play_button.png deleted file mode 100644 index 1cf15cc..0000000 Binary files a/res/drawable/play_button.png and /dev/null differ diff --git a/res/drawable/round_button.xml b/res/drawable/round_button.xml deleted file mode 100644 index 5fe7934..0000000 --- a/res/drawable/round_button.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/res/drawable/splash.jpg b/res/drawable/splash.jpg deleted file mode 100644 index cb82938..0000000 Binary files a/res/drawable/splash.jpg and /dev/null differ diff --git a/res/drawable/tomato.png b/res/drawable/tomato.png deleted file mode 100644 index fe1c7cb..0000000 Binary files a/res/drawable/tomato.png and /dev/null differ diff --git a/res/drawable/victory.jpg b/res/drawable/victory.jpg deleted file mode 100644 index b153254..0000000 Binary files a/res/drawable/victory.jpg and /dev/null differ diff --git a/res/drawable/void_panel.jpg b/res/drawable/void_panel.jpg deleted file mode 100644 index 243a2de..0000000 Binary files a/res/drawable/void_panel.jpg and /dev/null differ diff --git a/res/drawable/win_panel.jpg b/res/drawable/win_panel.jpg deleted file mode 100644 index c282460..0000000 Binary files a/res/drawable/win_panel.jpg and /dev/null differ diff --git a/res/layout/activity_frozen_bubble.xml b/res/layout/activity_frozen_bubble.xml deleted file mode 100644 index 9bcd749..0000000 --- a/res/layout/activity_frozen_bubble.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - \ No newline at end of file diff --git a/res/layout/activity_preferences_screen.xml b/res/layout/activity_preferences_screen.xml deleted file mode 100644 index 24fae84..0000000 --- a/res/layout/activity_preferences_screen.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/layout/activity_scrolling_credits.xml b/res/layout/activity_scrolling_credits.xml deleted file mode 100644 index d899ea2..0000000 --- a/res/layout/activity_scrolling_credits.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - \ No newline at end of file diff --git a/res/layout/activity_splash_screen.xml b/res/layout/activity_splash_screen.xml deleted file mode 100644 index b70c856..0000000 --- a/res/layout/activity_splash_screen.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - \ No newline at end of file diff --git a/res/layout/seek_bar_preference.xml b/res/layout/seek_bar_preference.xml deleted file mode 100644 index 13ef33e..0000000 --- a/res/layout/seek_bar_preference.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/menu/activity_frozen_bubble.xml b/res/menu/activity_frozen_bubble.xml deleted file mode 100644 index 9aafe64..0000000 --- a/res/menu/activity_frozen_bubble.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/res/raw/aftertherain.mod b/res/raw/aftertherain.mod deleted file mode 100644 index 2cbf0b9..0000000 Binary files a/res/raw/aftertherain.mod and /dev/null differ diff --git a/res/raw/ambientlight.xm b/res/raw/ambientlight.xm deleted file mode 100644 index c6f8a2a..0000000 Binary files a/res/raw/ambientlight.xm and /dev/null differ diff --git a/res/raw/ambientpower.mod b/res/raw/ambientpower.mod deleted file mode 100644 index 13fb966..0000000 Binary files a/res/raw/ambientpower.mod and /dev/null differ diff --git a/res/raw/androidrupture.mod b/res/raw/androidrupture.mod deleted file mode 100644 index e95284c..0000000 Binary files a/res/raw/androidrupture.mod and /dev/null differ diff --git a/res/raw/applause.ogg b/res/raw/applause.ogg deleted file mode 100644 index 7924944..0000000 Binary files a/res/raw/applause.ogg and /dev/null differ diff --git a/res/raw/artificial.mod b/res/raw/artificial.mod deleted file mode 100644 index c047de3..0000000 Binary files a/res/raw/artificial.mod and /dev/null differ diff --git a/res/raw/bluestars.mod b/res/raw/bluestars.mod deleted file mode 100644 index 8261622..0000000 Binary files a/res/raw/bluestars.mod and /dev/null differ diff --git a/res/raw/chungababe.mod b/res/raw/chungababe.mod deleted file mode 100644 index f995316..0000000 Binary files a/res/raw/chungababe.mod and /dev/null differ diff --git a/res/raw/crystalhammer.mod b/res/raw/crystalhammer.mod deleted file mode 100644 index 2a79cd0..0000000 Binary files a/res/raw/crystalhammer.mod and /dev/null differ diff --git a/res/raw/destroy_group.ogg b/res/raw/destroy_group.ogg deleted file mode 100644 index 2c102d7..0000000 Binary files a/res/raw/destroy_group.ogg and /dev/null differ diff --git a/res/raw/dreamscope.mod b/res/raw/dreamscope.mod deleted file mode 100644 index d6c35d6..0000000 Binary files a/res/raw/dreamscope.mod and /dev/null differ diff --git a/res/raw/freefall.mod b/res/raw/freefall.mod deleted file mode 100644 index e6ee573..0000000 Binary files a/res/raw/freefall.mod and /dev/null differ diff --git a/res/raw/gaeasawakening.xm b/res/raw/gaeasawakening.xm deleted file mode 100644 index 0dc43a7..0000000 Binary files a/res/raw/gaeasawakening.xm and /dev/null differ diff --git a/res/raw/homesick.mod b/res/raw/homesick.mod deleted file mode 100644 index 3e0024b..0000000 Binary files a/res/raw/homesick.mod and /dev/null differ diff --git a/res/raw/hurry.ogg b/res/raw/hurry.ogg deleted file mode 100644 index b30926f..0000000 Binary files a/res/raw/hurry.ogg and /dev/null differ diff --git a/res/raw/ifcrystals.mod b/res/raw/ifcrystals.mod deleted file mode 100644 index 98952c5..0000000 Binary files a/res/raw/ifcrystals.mod and /dev/null differ diff --git a/res/raw/introzik.xm b/res/raw/introzik.xm deleted file mode 100644 index 6ddab99..0000000 Binary files a/res/raw/introzik.xm and /dev/null differ diff --git a/res/raw/launch.ogg b/res/raw/launch.ogg deleted file mode 100644 index 550753e..0000000 Binary files a/res/raw/launch.ogg and /dev/null differ diff --git a/res/raw/lose.ogg b/res/raw/lose.ogg deleted file mode 100644 index 75fb078..0000000 Binary files a/res/raw/lose.ogg and /dev/null differ diff --git a/res/raw/newroot_solo.ogg b/res/raw/newroot_solo.ogg deleted file mode 100644 index 1cc35c8..0000000 Binary files a/res/raw/newroot_solo.ogg and /dev/null differ diff --git a/res/raw/noh.ogg b/res/raw/noh.ogg deleted file mode 100644 index ad16948..0000000 Binary files a/res/raw/noh.ogg and /dev/null differ diff --git a/res/raw/popcorn.mod b/res/raw/popcorn.mod deleted file mode 100644 index 5bc2e59..0000000 Binary files a/res/raw/popcorn.mod and /dev/null differ diff --git a/res/raw/rebound.ogg b/res/raw/rebound.ogg deleted file mode 100644 index 9389c95..0000000 Binary files a/res/raw/rebound.ogg and /dev/null differ diff --git a/res/raw/stardustmemories.mod b/res/raw/stardustmemories.mod deleted file mode 100644 index c0b719a..0000000 Binary files a/res/raw/stardustmemories.mod and /dev/null differ diff --git a/res/raw/stick.ogg b/res/raw/stick.ogg deleted file mode 100644 index 237dfef..0000000 Binary files a/res/raw/stick.ogg and /dev/null differ diff --git a/res/raw/sunshineofthemorningsun.xm b/res/raw/sunshineofthemorningsun.xm deleted file mode 100644 index efdc594..0000000 Binary files a/res/raw/sunshineofthemorningsun.xm and /dev/null differ diff --git a/res/raw/technostyleiii.mod b/res/raw/technostyleiii.mod deleted file mode 100644 index 489b503..0000000 Binary files a/res/raw/technostyleiii.mod and /dev/null differ diff --git a/res/raw/whip.ogg b/res/raw/whip.ogg deleted file mode 100644 index 8a3de2f..0000000 Binary files a/res/raw/whip.ogg and /dev/null differ diff --git a/res/raw/worldofpeace.it b/res/raw/worldofpeace.it deleted file mode 100644 index dc6644f..0000000 Binary files a/res/raw/worldofpeace.it and /dev/null differ diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml deleted file mode 100644 index 3b0b2d4..0000000 --- a/res/values-de/strings.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - Frozen Bubble - Exit - Weiterleitung zum Android Market für den Download des Level-Editors… - Android Market nicht gefunden! Bitten installieren Sie den Level-Editor manuell. - Bluetooth Device - Starten neues Spiel - Darstellung mit Symbolen - Darstellung ohne Symbole - Vollbild An - Vollbild Aus - Soundoptionen - Über Frozen Bubble - Schießen Methode - Kein Zeitdruck - Zeitdruck - Level-Editor - Einstellungen - Abbrechen - OK - Musik Abspielen - Spielen Soundeffekte - Frozen Bubble - Frozen Bubble - "Original Development\n" - "------------------------\n" - "\nGuillaume Cottenceau - Design and Programming\n" - "\nAlexis Younes - Graphics\n" - "\nAmaury Amblard-Ladurantie - Coding and Graphics Support\n" - "\nMatthias Le Bidan - Sounds\n" - "\nhttp://www.frozen-bubble.org/\n\n\n" - "\nJava Development\n" - "------------------------\n" - "\nGlenn Sanson\n\n\n" - "\nAndroid Port\n" - "------------------------\n" - "\nPawel Aleksander Fedorynski - Project Owner\n" - "\nEric Fortin - Committer\n" - "\nhttps://code.google.com/p/frozenbubbleandroid/\n\n\n" - "\nAdditional Code\n" - "------------------------\n" - "\nAntoine Vianey - Accelerometer Manager\n" - "\nhttps://code.google.com/p/androgames-sample/\n\n" - "\nPatrick Casey - AndModPlug Library\n" - "\nhttp://www.peculiar-games.com/\n\n" - "\nMichel Racic - High Score Manager\n" - "\nhttp://www.2030.tk/\n\n\n" - "\nTranslations\n" - "------------------------\n" - "\nShanghai Ndoo Network Technology Ltd. - Chinese\n\n" - "\nCélim Hanifi - French\n\n" - "\nUwe Walschus - German\n\n" - "\nJuan Aguado - Spanish\n\n\n" - "\nMusic Credits\n" - "------------------------\n" - "\nAfter the Rain\nby Unknown Artist\n\n" - "\nAmbient Light\nby Vogue of Triton\n\n" - "\nAmbient Power\nby Vogue of Triton\n\n" - "\nAndroid Rupture\nby Baroque of Freelance\n\n" - "\nArtificial\nby Moby\n\n" - "\nBlue Stars\nby Blackstar\\Timetraveller of Cryptoburners\n\n" - "\nChunga-babe!\nby Yannis Brown\n\n" - "\nCrystalhammer\nby Karsten Obarski\n\n" - "\nDreamscope I\nby Counterpoint of Westower\n\n" - "\nFreefall\nby Baroque of Freelance\n\n" - "\nGaea\'s Awakening\nby Dreamsection\n\n" - "\nHomesick\nby Electric Keet\n\n" - "\nIf Crystals…\nby Tran of Renaissance\n\n" - "\nFrozen Bubble Intro\nby Matthias Le Bidan\n\n" - "\nPopcorn\nby Unknown Artist\n\n" - "\nStardust Memories\nby Jester of Sanity\n\n" - "\nSunshine of the Morning Sun\nby Area51 (Dan Nyman)\n\n" - "\nTechnostyle III\nby Xenox of Triad\n\n" - "\nWorld of Peace\nby Zanoma (Marwan Green Critter)\n\n" - "\nAll songs downloaded from:\n" - "http://modarchive.org/\n\n\n" - "\n\n\nThank You For Playing!" - - Einstellen, dann Schießen - Zeigen zum Schießen - Rotieren, dann Schießen - - - @string/play_sound_effects - @string/play_level_music - - - 0 - 1 - 2 - - diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml deleted file mode 100644 index a17d1af..0000000 --- a/res/values-es/strings.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - Frozen Bubble - Exit - Redireccionando a Google Play para descargar el editor de niveles... - No se puede encontrar la aplicación de Google Play. Por favor, instala el editor de niveles manualmente. - Bluetooth Device - Nuevo juego - Activar modo daltónico - Desactivar modo daltónico - Pantalla completa - Quitar pantalla completa - Opciones de sonido - Sobre Frozen Bubble - Modo de orientación - Sin prisas - Con prisas - Editor de niveles - Parámetros - Cancelar - OK - Tocar Música - Tocar Efectos Sonoros - Frozen Bubble - Frozen Bubble - "Original Development\n" - "------------------------\n" - "\nGuillaume Cottenceau - Design and Programming\n" - "\nAlexis Younes - Graphics\n" - "\nAmaury Amblard-Ladurantie - Coding and Graphics Support\n" - "\nMatthias Le Bidan - Sounds\n" - "\nhttp://www.frozen-bubble.org/\n\n\n" - "\nJava Development\n" - "------------------------\n" - "\nGlenn Sanson\n\n\n" - "\nAndroid Port\n" - "------------------------\n" - "\nPawel Aleksander Fedorynski - Project Owner\n" - "\nEric Fortin - Committer\n" - "\nhttps://code.google.com/p/frozenbubbleandroid/\n\n\n" - "\nAdditional Code\n" - "------------------------\n" - "\nAntoine Vianey - Accelerometer Manager\n" - "\nhttps://code.google.com/p/androgames-sample/\n\n" - "\nPatrick Casey - AndModPlug Library\n" - "\nhttp://www.peculiar-games.com/\n\n" - "\nMichel Racic - High Score Manager\n" - "\nhttp://www.2030.tk/\n\n\n" - "\nTranslations\n" - "------------------------\n" - "\nShanghai Ndoo Network Technology Ltd. - Chinese\n\n" - "\nCélim Hanifi - French\n\n" - "\nUwe Walschus - German\n\n" - "\nJuan Aguado - Spanish\n\n\n" - "\nMusic Credits\n" - "------------------------\n" - "\nAfter the Rain\nby Unknown Artist\n\n" - "\nAmbient Light\nby Vogue of Triton\n\n" - "\nAmbient Power\nby Vogue of Triton\n\n" - "\nAndroid Rupture\nby Baroque of Freelance\n\n" - "\nArtificial\nby Moby\n\n" - "\nBlue Stars\nby Blackstar\\Timetraveller of Cryptoburners\n\n" - "\nChunga-babe!\nby Yannis Brown\n\n" - "\nCrystalhammer\nby Karsten Obarski\n\n" - "\nDreamscope I\nby Counterpoint of Westower\n\n" - "\nFreefall\nby Baroque of Freelance\n\n" - "\nGaea\'s Awakening\nby Dreamsection\n\n" - "\nHomesick\nby Electric Keet\n\n" - "\nIf Crystals…\nby Tran of Renaissance\n\n" - "\nFrozen Bubble Intro\nby Matthias Le Bidan\n\n" - "\nPopcorn\nby Unknown Artist\n\n" - "\nStardust Memories\nby Jester of Sanity\n\n" - "\nSunshine of the Morning Sun\nby Area51 (Dan Nyman)\n\n" - "\nTechnostyle III\nby Xenox of Triad\n\n" - "\nWorld of Peace\nby Zanoma (Marwan Green Critter)\n\n" - "\nAll songs downloaded from:\n" - "http://modarchive.org/\n\n\n" - "\n\n\nThank You For Playing!" - - Apunta y luego dispara - Apunta y dispara - Rotar y luego disparar - - - @string/play_sound_effects - @string/play_level_music - - - 0 - 1 - 2 - - diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml deleted file mode 100644 index aec52f7..0000000 --- a/res/values-fr/strings.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - Frozen Bubble - Exit - Redirection vers le Play Store afin de télécharger l\'éditeur de niveau… - Play Store introuvable! Veuillez installer l\'éditeur de niveau Frozen Bubble manuellement. - Bluetooth Device - Nouvelle Partie - Activer Mode Daltonien - Désactiver Mode Daltonien - Activer Plein Écran - Désactiver Plein Écran - Options son - À propos de Frozen Bubble - Mode Ciblé - Ne Me Précipite Pas - Précipite Moi - Éditeur de niveau - Paramètres - Annuler - OK - Jouer Musique - Jouer Effets Sonores - Frozen Bubble - Frozen Bubble - "Développement Original\n" - "------------------------\n" - "\nGuillaume Cottenceau - Design et Programmation\n" - "\nAlexis Younes - Graphiques\n" - "\nAmaury Amblard-Ladurantie - Codage et Support Graphique\n" - "\nMatthias Le Bidan - Sons\n" - "\nhttp://www.frozen-bubble.org/\n\n\n" - "\nDéveloppement Java\n" - "------------------------\n" - "\nGlenn Sanson\n\n\n" - "\nPort sur Android\n" - "------------------------\n" - "\nPawel Aleksander Fedorynski - Détenteur du projet\n" - "\nEric Fortin - Validation\n" - "\nhttps://code.google.com/p/frozenbubbleandroid/\n\n\n" - "\nCode Additionnel\n" - "------------------------\n" - "\nAntoine Vianey - Gérant Accéléromètre\n" - "\nhttps://code.google.com/p/androgames-sample/\n\n" - "\nPatrick Casey - AndModPlug Library\n" - "\nhttp://www.peculiar-games.com/\n\n" - "\nMichel Racic - Gérant High Scores\n" - "\nhttp://www.2030.tk/\n\n\n" - "\nTraduction\n" - "------------------------\n" - "\nShanghai Ndoo Network Technology Ltd. - Chinese\n\n" - "\nCélim Hanifi - French\n\n" - "\nUwe Walschus - German\n\n" - "\nJuan Aguado - Spanish\n\n\n" - "\nCrédits Musique\n" - "------------------------\n" - "\nAfter the Rain\npar Artiste Inconnu\n\n" - "\nAmbient Light\npar Vogue of Triton\n\n" - "\nAmbient Power\npar Vogue of Triton\n\n" - "\nAndroid Rupture\npar Baroque of Freelance\n\n" - "\nArtificial\npar Moby\n\n" - "\nBlue Stars\npar Blackstar\\Timetraveller of Cryptoburners\n\n" - "\nChunga-babe!\npar Yannis Brown\n\n" - "\nCrystalhammer\npar Karsten\n\n" - "\nDreamscope I\npar Counterpoint of Westower\n\n" - "\nFreefall\npar Baroque of Freelance\n\n" - "\nGaea\'s Awakening\npar Dreamsection\n\n" - "\nHomesick\npar Electric Keet\n\n" - "\nIf Crystals…\npar Tran of Renaissance\n\n" - "\nFrozen Bubble Intro\npar Matthias Le Bidan\n\n" - "\nPopcorn\npar Artiste Inconnu\n\n" - "\nStardust Memories\npar Jester of Sanity\n\n" - "\nSunshine of the Morning Sun\npar Area51 (Dan Nyman)\n\n" - "\nTechnostyle III\npar Xenox of Triad\n\n" - "\nWorld of Peace\npar Zanoma (Marwan Green Critter)\n\n" - "\nMusiques téléchargées sur:\n" - "http://modarchive.org/\n\n\n" - "\n\n\nMerci d'avoir joué !" - - Viser Puis Tirer - Toucher Pour Tirer - Pivoter Puis Tirer - - - @string/play_sound_effects - @string/play_level_music - - - 0 - 1 - 2 - - diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml deleted file mode 100644 index 44f01db..0000000 --- a/res/values-sw600dp/dimens.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml deleted file mode 100644 index 61e3fa8..0000000 --- a/res/values-sw720dp-land/dimens.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - 128dp - - diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml deleted file mode 100644 index c74d662..0000000 --- a/res/values-zh-rCN/strings.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - 冰冻泡泡 - Exit - 推荐您直接到市场上下载关卡编辑器… - 找不到Android市场! 请手动安装冰冻泡泡编辑器. - Bluetooth Device - 开始新游戏 - 色盲模式开启 - 色盲模式关闭 - 全屏模式开启 - 全屏模式关闭 - 音效选项 - 关于冰冻泡泡 - 瞄准模式 - 不要催我 - 敦促我 - 关卡编辑器 - 设置 - 取消 - - 奏乐 - 播放声音效果 - 冰冻泡泡 - 冰冻泡泡 - "Original Development\n" - "------------------------\n" - "\nGuillaume Cottenceau - Design and Programming\n" - "\nAlexis Younes - Graphics\n" - "\nAmaury Amblard-Ladurantie - Coding and Graphics Support\n" - "\nMatthias Le Bidan - Sounds\n" - "\nhttp://www.frozen-bubble.org/\n\n\n" - "\nJava Development\n" - "------------------------\n" - "\nGlenn Sanson\n\n\n" - "\nAndroid Port\n" - "------------------------\n" - "\nPawel Aleksander Fedorynski - Project Owner\n" - "\nEric Fortin - Committer\n" - "\nhttps://code.google.com/p/frozenbubbleandroid/\n\n\n" - "\nAdditional Code\n" - "------------------------\n" - "\nAntoine Vianey - Accelerometer Manager\n" - "\nhttps://code.google.com/p/androgames-sample/\n\n" - "\nPatrick Casey - AndModPlug Library\n" - "\nhttp://www.peculiar-games.com/\n\n" - "\nMichel Racic - High Score Manager\n" - "\nhttp://www.2030.tk/\n\n\n" - "\nTranslations\n" - "------------------------\n" - "\nShanghai Ndoo Network Technology Ltd. - Chinese\n\n" - "\nCélim Hanifi - French\n\n" - "\nUwe Walschus - German\n\n" - "\nJuan Aguado - Spanish\n\n\n" - "\nMusic Credits\n" - "------------------------\n" - "\nAfter the Rain\nby Unknown Artist\n\n" - "\nAmbient Light\nby Vogue of Triton\n\n" - "\nAmbient Power\nby Vogue of Triton\n\n" - "\nAndroid Rupture\nby Baroque of Freelance\n\n" - "\nArtificial\nby Moby\n\n" - "\nBlue Stars\nby Blackstar\\Timetraveller of Cryptoburners\n\n" - "\nChunga-babe!\nby Yannis Brown\n\n" - "\nCrystalhammer\nby Karsten Obarski\n\n" - "\nDreamscope I\nby Counterpoint of Westower\n\n" - "\nFreefall\nby Baroque of Freelance\n\n" - "\nGaea\'s Awakening\nby Dreamsection\n\n" - "\nHomesick\nby Electric Keet\n\n" - "\nIf Crystals…\nby Tran of Renaissance\n\n" - "\nFrozen Bubble Intro\nby Matthias Le Bidan\n\n" - "\nPopcorn\nby Unknown Artist\n\n" - "\nStardust Memories\nby Jester of Sanity\n\n" - "\nSunshine of the Morning Sun\nby Area51 (Dan Nyman)\n\n" - "\nTechnostyle III\nby Xenox of Triad\n\n" - "\nWorld of Peace\nby Zanoma (Marwan Green Critter)\n\n" - "\nAll songs downloaded from:\n" - "http://modarchive.org/\n\n\n" - "\n\n\nThank You For Playing!" - - 瞄准后射击 - 点击射击 - 旋转和射击 - - - @string/play_sound_effects - @string/play_level_music - - - 0 - 1 - 2 - - diff --git a/res/values/color.xml b/res/values/color.xml deleted file mode 100644 index 253b87b..0000000 --- a/res/values/color.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #000000 - \ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml deleted file mode 100644 index 55c1e59..0000000 --- a/res/values/dimens.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - 16dp - 16dp - - diff --git a/res/values/strings.xml b/res/values/strings.xml deleted file mode 100644 index 1f8af42..0000000 --- a/res/values/strings.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - Frozen Bubble - Exit - Redirecting you to the Market to download the Frozen Bubble Level Editor… - Cannot find Android Market! Please install Frozen Bubble Level Editor manually. - Bluetooth Device - Start New Game - Colorblind Mode On - Colorblind Mode Off - Fullscreen On - Fullscreen Off - Sound Options - About Frozen Bubble - Targeting Mode - Don\'t Rush Me - Rush Me - Level Editor - Settings - Cancel - OK - Play Level Music - Play Sound Effects - Frozen Bubble - Frozen Bubble - "Original Development\n" - "------------------------\n" - "\nGuillaume Cottenceau - Design and Programming\n" - "\nAlexis Younes - Graphics\n" - "\nAmaury Amblard-Ladurantie - Coding and Graphics Support\n" - "\nMatthias Le Bidan - Sounds\n" - "\nhttp://www.frozen-bubble.org/\n\n\n" - "\nJava Development\n" - "------------------------\n" - "\nGlenn Sanson\n\n\n" - "\nAndroid Port\n" - "------------------------\n" - "\nPawel Aleksander Fedorynski - Project Owner\n" - "\nEric Fortin - Committer\n" - "\nhttps://code.google.com/p/frozenbubbleandroid/\n\n\n" - "\nAdditional Code\n" - "------------------------\n" - "\nAntoine Vianey - Accelerometer Manager\n" - "\nhttps://code.google.com/p/androgames-sample/\n\n" - "\nPatrick Casey - AndModPlug Library\n" - "\nhttp://www.peculiar-games.com/\n\n" - "\nMichel Racic - High Score Manager\n" - "\nhttp://www.2030.tk/\n\n\n" - "\nTranslations\n" - "------------------------\n" - "\nShanghai Ndoo Network Technology Ltd. - Chinese\n\n" - "\nCélim Hanifi - French\n\n" - "\nUwe Walschus - German\n\n" - "\nJuan Aguado - Spanish\n\n\n" - "\nMusic Credits\n" - "------------------------\n" - "\nAfter the Rain\nby Unknown Artist\n\n" - "\nAmbient Light\nby Vogue of Triton\n\n" - "\nAmbient Power\nby Vogue of Triton\n\n" - "\nAndroid Rupture\nby Baroque of Freelance\n\n" - "\nArtificial\nby Moby\n\n" - "\nBlue Stars\nby Blackstar\\Timetraveller of Cryptoburners\n\n" - "\nChunga-babe!\nby Yannis Brown\n\n" - "\nCrystalhammer\nby Karsten Obarski\n\n" - "\nDreamscope I\nby Counterpoint of Westower\n\n" - "\nFreefall\nby Baroque of Freelance\n\n" - "\nGaea\'s Awakening\nby Dreamsection\n\n" - "\nHomesick\nby Electric Keet\n\n" - "\nIf Crystals…\nby Tran of Renaissance\n\n" - "\nFrozen Bubble Intro\nby Matthias Le Bidan\n\n" - "\nPopcorn\nby Unknown Artist\n\n" - "\nStardust Memories\nby Jester of Sanity\n\n" - "\nSunshine of the Morning Sun\nby Area51 (Dan Nyman)\n\n" - "\nTechnostyle III\nby Xenox of Triad\n\n" - "\nWorld of Peace\nby Zanoma (Marwan Green Critter)\n\n" - "\nAll songs downloaded from:\n" - "http://modarchive.org/\n\n\n" - "\n\n\nThank You For Playing!" - - Aim Then Shoot - Point To Shoot - Rotate Then Shoot - - - @string/play_sound_effects - @string/play_level_music - - - 0 - 1 - 2 - - diff --git a/res/values/styles.xml b/res/values/styles.xml deleted file mode 100644 index 79a39af..0000000 --- a/res/values/styles.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/com/efortin/frozenbubble/AccelerometerManager.java b/src/com/efortin/frozenbubble/AccelerometerManager.java deleted file mode 100644 index d20bad1..0000000 --- a/src/com/efortin/frozenbubble/AccelerometerManager.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import java.util.List; - -import android.content.Context; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; - -/** - * Android Accelerometer Sensor Manager Archetype - * - *

Licensed under GPL v3: - *
http://www.gnu.org/licenses/gpl-3.0.html - * - * @author Antoine Vianey - * - */ -public class AccelerometerManager { - private static Sensor sensor; - private static SensorManager sensorManager; - - /** indicates whether or not Accelerometer Sensor is supported */ - private static Boolean supported; - /** indicates whether or not Accelerometer Sensor is running */ - private static boolean running = false; - - public interface AccelerometerListener { - public void onAccelerationChanged(float x, float y, float z); - } - - // you could use an OrientationListener array instead - // if you plans to use more than one listener - private static AccelerometerListener listener; - - /** - * Returns true if the manager is listening to orientation changes - */ - public static boolean isListening() { - return running; - } - - /** - * Unregisters listeners. - */ - public static void stopListening() { - running = false; - - try { - if (sensorManager != null && sensorEventListener != null) { - sensorManager.unregisterListener(sensorEventListener); - } - } catch (Exception e) {} - } - - /** - * Returns true if at least one Accelerometer sensor is available. - */ - public static boolean isSupported(Context context) { - if (supported == null) { - sensorManager = - (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - List sensors = - sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER); - supported = Boolean.valueOf(sensors.size() > 0); - } - return supported; - } - - /** - * Registers a listener and starts listening. - * - * @param accelerometerListener - * - Callback for accelerometer events. - */ - public static void startListening(Context context, - AccelerometerListener accelerometerListener) { - sensorManager = - (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - List sensors = - sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER); - - if (sensors.size() > 0) { - sensor = sensors.get(0); - running = - sensorManager.registerListener(sensorEventListener, sensor, - SensorManager.SENSOR_DELAY_FASTEST); - listener = accelerometerListener; - } - } - - /** - * The listener that listens to events from the accelerometer listener. - */ - private static SensorEventListener sensorEventListener = - new SensorEventListener() { - private float filter = 0.1f; - private float avgX = 0.0f; - private float avgY = 0.0f; - private float avgZ = 0.0f; - - public void onAccuracyChanged(Sensor sensor, int accuracy) {} - - public void onSensorChanged(SensorEvent event) { - avgX = event.values[0] * filter + (avgX * (1.0f-filter)); - avgY = event.values[1] * filter + (avgY * (1.0f-filter)); - avgZ = event.values[2] * filter + (avgZ * (1.0f-filter)); - - listener.onAccelerationChanged(avgX, avgY, avgZ); - } - }; -} diff --git a/src/com/efortin/frozenbubble/BluetoothManager.java b/src/com/efortin/frozenbubble/BluetoothManager.java deleted file mode 100644 index 68cda23..0000000 --- a/src/com/efortin/frozenbubble/BluetoothManager.java +++ /dev/null @@ -1,624 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2015 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; -import java.io.OutputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Set; -import java.util.UUID; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothServerSocket; -import android.bluetooth.BluetoothSocket; -import android.os.ParcelUuid; -import android.util.Log; - -/** - *

Bluetooth socket class. - *

Requires the following permissions: - * BLUETOOTH - * BLUETOOTH_ADMIN - * @author Eric Fortin, Wednesday, May 8, 2013 - */ -public class BluetoothManager { - private static final String LOG_TAG = UDPSocket.class.getSimpleName(); - private static final UUID SPP_UUID = UUID. - fromString("00001101-0000-1000-8000-00805F9B34FB"); - - /* - * BluetoothManager class member variables. - */ - private boolean isServer; - private boolean paused; - private boolean running; - private int deviceIndex; - private ArrayList txList = null; - private ArrayList listenerList = null; - private BluetoothAdapter myAdapter = null; - private BluetoothSocket mySocket = null; - private InputStream myInputStream = null; - private OutputStream myOutputStream = null; - private String remoteName = "not available"; - private Thread myRxThread = null; - private Thread myTxThread = null; - - /* - * Listener interface for various UDP socket events. - * - * This interface defines the abstract listener method that needs - * to be instantiated by the registrar, as well as the various - * events supported by the interface. - */ - public interface BluetoothListener { - public abstract void onBluetoothEvent(byte[] buffer, - int length); - } - - public void setBluetoothListener(BluetoothListener listener) { - listenerList.add(listener); - } - - /** - * Bluetooth socket class constructor. - */ - public BluetoothManager(boolean isServer, int deviceIndex) { - this.isServer = isServer; - this.deviceIndex = deviceIndex; - myInputStream = null; - myOutputStream = null; - myRxThread = null; - myTxThread = null; - txList = null; - txList = new ArrayList(); - listenerList = new ArrayList(); - paused = false; - running = true; - myRxThread = new Thread(new BluetoothRxThread(), "myRxThread"); - myRxThread.start(); - myTxThread = new Thread(new BluetoothTxThread(), "myTxThread"); - myTxThread.start(); - } - - final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); - public static String bytesToHex(byte[] bytes, int length) { - char[] hexChars = new char[length * 2]; - for ( int j = 0; j < length; j++ ) { - int v = bytes[j] & 0xFF; - hexChars[j * 2 ] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } - - /** - * Clean up the UDP socket by stopping the thread, closing the UDP - * socket and freeing resources. - */ - public void cleanUp() { - if (listenerList != null) { - listenerList.clear(); - } - listenerList = null; - stopThread(); - if (mySocket != null) { - try { - mySocket.close(); - } catch (IOException e) { - // Auto-generated catch block - e.printStackTrace(); - } - } - mySocket = null; - if (myInputStream != null) { - try { - myInputStream.close(); - } catch (IOException e) { - // Auto-generated catch block - e.printStackTrace(); - } - } - myInputStream = null; - if (myOutputStream != null) { - try { - myOutputStream.close(); - } catch (IOException e) { - // Auto-generated catch block - e.printStackTrace(); - } - } - myOutputStream = null; - if (txList != null) { - txList.clear(); - } - txList = null; - } - - /** - * Configure the Bluetooth socket settings. - */ - private void configureBluetoothSocket() { - mySocket = null; - myAdapter = BluetoothAdapter.getDefaultAdapter(); - - if (myAdapter != null) { - if (isServer) { - try { - BluetoothServerSocket myServer = - myAdapter.listenUsingInsecureRfcommWithServiceRecord(getLocalName(), - SPP_UUID); - myAdapter.cancelDiscovery(); - mySocket = myServer.accept(); - myServer .close(); - remoteName = mySocket.getRemoteDevice().getName(); - } catch (IOException e) { - // Auto-generated catch block - e.printStackTrace(); - mySocket = null; - } catch (NullPointerException e) { - e.printStackTrace(); - mySocket = null; - } - } - else { - BluetoothDevice device = getPairedDevice(deviceIndex); - remoteName = device.getName(); - try { - mySocket = device.createInsecureRfcommSocketToServiceRecord(SPP_UUID); - myAdapter.cancelDiscovery(); - mySocket .connect(); - } catch (IOException e) { - // Auto-generated catch block - e.printStackTrace(); - mySocket = null; - } catch (NullPointerException e) { - e.printStackTrace(); - mySocket = null; - } - } - - if (mySocket != null) { - try { - myInputStream = mySocket.getInputStream(); - myOutputStream = mySocket.getOutputStream(); - } catch (IOException e) { - // Auto-generated catch block - e.printStackTrace(); - try { - mySocket.close(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - mySocket = null; - } - } - } - } - - public String getLocalName() { - String name = "not available"; - - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - - if (adapter != null) { - if (!adapter.isEnabled()) { - name = "bluetooth disabled"; - } - else { - name = adapter.getName(); - } - } - - return name; - } - - /** - * Obtain the desired paired Bluetooth device. If the desired index - * is greater than the number of entries in the device list, the last - * entry is provided instead. - * @param deviceIndex - the index of the desired Bluetooth device. - * @return The desired Bluetooth device if it exists, otherwise - * null. - */ - public static BluetoothDevice getPairedDevice(int deviceIndex) { - BluetoothDevice[] pairedDevices = getPairedDevices(); - - if ((pairedDevices != null) && (pairedDevices.length > 0)) { - if (deviceIndex >= pairedDevices.length) { - deviceIndex = pairedDevices.length - 1; - } - return pairedDevices[deviceIndex]; - } - return null; - } - - /** - * Obtain an array of the paired Bluetooth devices. - * @return The array of paired Bluetooth devices if it exists, - * otherwise null. - */ - public static BluetoothDevice[] getPairedDevices() { - BluetoothAdapter localAdapter = null; - - localAdapter = BluetoothAdapter.getDefaultAdapter(); - if ((localAdapter != null) && !localAdapter.getBondedDevices().isEmpty()) { - Set deviceSet = localAdapter.getBondedDevices(); - return deviceSet.toArray(new BluetoothDevice[deviceSet.size()]); - } - return null; - } - - /** - * Obtain the desired local UUID. If the desired index is greater - * than the number of entries in the UUID list, the last entry is - * provided instead. - * @param uuidIndex - the index to pull from the local UUID list. - * @return The desired UUID. - */ - public UUID getLocalUuid(int uuidIndex) { - UUID serverUuid = null; - ParcelUuid[] parcelUuids = getLocalUuids(); - if ((parcelUuids != null) && (parcelUuids.length > 0 )) { - if (uuidIndex >= parcelUuids.length) { - uuidIndex = parcelUuids.length - 1; - } - serverUuid = UUID.fromString(parcelUuids[uuidIndex].toString()); - } - return serverUuid; - } - - private ParcelUuid[] getLocalUuids() { - Method method = null; - ParcelUuid[] uuids = null; - - if (myAdapter != null) { - try { - method = myAdapter.getClass().getMethod("getUuids", (Class[])null); - uuids = (ParcelUuid[]) method.invoke(myAdapter, (Object[])null); - } catch (SecurityException e1) { - // Auto-generated catch block - e1.printStackTrace(); - } catch (NoSuchMethodException e1) { - // Auto-generated catch block - e1.printStackTrace(); - } catch (IllegalArgumentException e) { - // Auto-generated catch block - e.printStackTrace(); - } catch (IllegalAccessException e) { - // Auto-generated catch block - e.printStackTrace(); - } catch (InvocationTargetException e) { - // Auto-generated catch block - e.printStackTrace(); - } - } - return (uuids); - } - - /** - * Obtain the desired UUID of the desired bonded device. If either - * index is greater than the number of entries, the last entry is - * provided instead. - * @param pairedIndex - the paired device index. - * @param uuidIndex - the index of the desired device UUID. - * @return - */ - public UUID getPairedUuid(int pairedIndex, int uuidIndex) { - UUID pairedUuid = null; - ParcelUuid[] parcelUuids = getPairedUuids(pairedIndex); - if ((parcelUuids != null) && (parcelUuids.length > 0 )) { - if (uuidIndex >= parcelUuids.length) { - uuidIndex = parcelUuids.length - 1; - } - pairedUuid = UUID.fromString(parcelUuids[uuidIndex].toString()); - } - return pairedUuid; - } - - private ParcelUuid[] getPairedUuids(int pairedIndex) { - Method method = null; - ParcelUuid[] uuids = null; - BluetoothDevice[] pairedArray = null; - - if (myAdapter != null) { - Set pairedDevices = myAdapter.getBondedDevices(); - if ((pairedDevices != null) && (pairedDevices.size() > 0 )) { - pairedArray = (BluetoothDevice[]) pairedDevices.toArray(); - if (pairedIndex >= pairedArray.length) { - pairedIndex = pairedArray.length - 1; - } - } - try { - method = pairedArray[pairedIndex].getClass().getMethod("getUuids", (Class[])null); - uuids = (ParcelUuid[]) method.invoke(pairedArray[pairedIndex], (Object[])null); - } catch (SecurityException e1) { - // Auto-generated catch block - e1.printStackTrace(); - } catch (NoSuchMethodException e1) { - // Auto-generated catch block - e1.printStackTrace(); - } catch (IllegalArgumentException e) { - // Auto-generated catch block - e.printStackTrace(); - } catch (IllegalAccessException e) { - // Auto-generated catch block - e.printStackTrace(); - } catch (InvocationTargetException e) { - // Auto-generated catch block - e.printStackTrace(); - } - } - return (uuids); - } - - public String getRemoteName() { - return remoteName; - } - - public boolean getIsConnected() { - return (mySocket != null); - } - - /** - * This is the Bluetooth InputStream receive thread declaration. - * @author Eric Fortin, Saturday, July 18, 2015 - * @see configureBluetoothSocket() - */ - private class BluetoothRxThread implements Runnable { - private byte[] rxBuffer = new byte[256]; - - /** - * Receive a Bluetooth InputStream message. - *

Given a nonzero socket timeout, it is expected behavior for - * this method to catch an InterruptedIOException. - * This method posts an EVENT_PACKET_RX event to the - * registered listener upon datagram receipt. - */ - private void receiveDatagram() { - if (!paused && running) try { - if (myInputStream != null) { - myInputStream.read(rxBuffer, 0, rxBuffer.length); - byte[] buffer = rxBuffer.clone(); - int length = rxBuffer.length; - - if (!paused && running && (length != 0) && (listenerList != null)) { - int size = listenerList.size(); - while (--size >= 0) { - listenerList.get(size).onBluetoothEvent(buffer, length); - } - Log.d(LOG_TAG, "received "+length+" bytes: 0x" + - bytesToHex(buffer, length)); - } - } - } catch (NullPointerException npe) { - npe.printStackTrace(); - } catch (InterruptedIOException iioe) { - /* - * Receive timeout. This is expected behavior. - */ - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - - /** - * This is the thread's run() call. - *

Receive Bluetooth data. - */ - @Override - public void run() { - while (running) { - if (mySocket == null) { - configureBluetoothSocket(); - } - else { - if (paused) try { - synchronized(this) { - wait(); - } - } catch (InterruptedException ie) { - /* - * Interrupted. This is expected behavior. - */ - } - - if (!paused && running) { - receiveDatagram(); - } - } - } - } - } - - /** - * This is the Bluetooth OutputStream transmit thread declaration. - * @author Eric Fortin, Saturday, July 18, 2015 - * @see configureBluetoothSocket() - */ - private class BluetoothTxThread implements Runnable { - /** - * This is the thread's run() call. - *

Send Bluetooth data. - */ - @Override - public void run() { - while (running) { - if (mySocket != null) { - if (paused) try { - synchronized(this) { - wait(); - } - } catch (InterruptedException ie) { - /* - * Interrupted. This is expected behavior. - */ - } - - if (!paused && running) { - sendDatagram(); - } - } - } - } - - /** - * Extract the next buffer from the FIFO transmit list and send it - * as a Bluetooth OutputStream message. - */ - private void sendDatagram() { - if (!paused && running && (txList != null) && txList.size() > 0) try { - byte[] bytes; - synchronized(txList) { - bytes = txList.get(0); - } - if (myOutputStream != null) { - myOutputStream.write(bytes, 0, bytes.length); - Log.d(LOG_TAG, "transmitted "+bytes.length+" bytes: 0x" + - bytesToHex(bytes, bytes.length)); - synchronized(txList) { - txList.remove(0); - } - } - } catch (NullPointerException npe) { - npe.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - } - - public void pause() { - if (running) { - paused = true; - } - } - - /** - * Stop and join() the Bluetooth RX and TX threads. - */ - private void stopThread() { - paused = false; - running = false; - if (myRxThread != null) { - synchronized(myRxThread) { - myRxThread.interrupt(); - } - } - if (myTxThread != null) { - synchronized(myTxThread) { - myTxThread.interrupt(); - } - } - /* - * Close and join() the Bluetooth thread. - */ - boolean retry = true; - while (retry && (myRxThread != null)) { - try { - myRxThread.join(); - retry = false; - } catch (InterruptedException e) { - /* - * Keep trying to close the Bluetooth thread. - */ - } - } - retry = true; - while (retry && (myTxThread != null)) { - try { - myTxThread.join(); - retry = false; - } catch (InterruptedException e) { - /* - * Keep trying to close the Bluetooth thread. - */ - } - } - } - - /** - * Send the desired byte buffer as a UDP datagram packet. - * @param buffer - the byte buffer to transmit. - * @return true if the buffer was successfully added to - * the outgoing datagram transmit list, false if the the - * buffer was unable to be added to the transmit list. - */ - public boolean transmit(byte[] buffer) { - if ((mySocket != null) && (myTxThread != null) && running) { - synchronized(txList) { - txList.add(buffer); - } - return true; - } - return false; - } - - public void unPause() { - paused = false; - if (myRxThread != null) { - synchronized(myRxThread) { - myRxThread.interrupt(); - } - } - if (myTxThread != null) { - synchronized(myTxThread) { - myTxThread.interrupt(); - } - } - } -}; diff --git a/src/com/efortin/frozenbubble/CRC16.java b/src/com/efortin/frozenbubble/CRC16.java deleted file mode 100644 index 9664236..0000000 --- a/src/com/efortin/frozenbubble/CRC16.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -/* - * Copyright 2008 - CommonCrawl Foundation - * - * 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 . - * - */ - -package com.efortin.frozenbubble; - -import java.util.zip.Checksum; - -/** - * 16 bit CRC implementation. - * - * @author rana - * - */ -public class CRC16 implements Checksum { - - int crcValue; - - /** - * Create a new CRC16 calculation utility object with the checksum - * initialized to the desired value. - * @param crcStart - the initial CRC value. - */ - public CRC16(int crcStart) { - crcValue = crcStart; - } - - /***************************************************************************/ - // 16bit CRC computation support - /***************************************************************************/ - - static final int[] crc16_table = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, - 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, - 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, - 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, - 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, - 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, - 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, - 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, - 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, - 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, - 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, - 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, - 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, - 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, - 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, - 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, - 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, - 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, - 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, - 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, - 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, - 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, - 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, - 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, - 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, - 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, - 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, - 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, - 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 }; - - @Override - public long getValue() { - return crcValue; - } - - @Override - public void reset() { - crcValue = 0; - } - - @Override - public void update(int b) { - crcValue = (crcValue >>> 8) ^ crc16_table[(crcValue ^ (byte) b) & 0xff]; - } - - @Override - public void update(byte[] b, int off, int len) { - for (int i = off; i < (off + len); ++i) { - crcValue = (crcValue >>> 8) ^ crc16_table[(crcValue ^ b[i]) & 0xff]; - } - } -} diff --git a/src/com/efortin/frozenbubble/ComputerAI.java b/src/com/efortin/frozenbubble/ComputerAI.java deleted file mode 100644 index 56930da..0000000 --- a/src/com/efortin/frozenbubble/ComputerAI.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import org.gsanson.frozenbubble.Freile; -import org.gsanson.frozenbubble.Freile.eventEnum; -import org.jfedor.frozenbubble.FrozenGame; -import org.jfedor.frozenbubble.GameScreen.gameEnum; - -import android.view.KeyEvent; - -public class ComputerAI extends Thread implements Freile.OpponentListener { - private int action; - private boolean running; - private FrozenGame myFrozenGame; - private Freile cpuOpponent; - private VirtualInput myPlayerInput; - - /** - * Game AI thread class constructor. - * @param gameRef - reference used to access game information for - * this player. - */ - public ComputerAI(FrozenGame gameRef, VirtualInput inputRef) { - myFrozenGame = gameRef; - myPlayerInput = inputRef; - cpuOpponent = new Freile(myFrozenGame.getGrid()); - cpuOpponent.setOpponentListener(this); - action = 0; - running = true; - } - - public void cleanUp() { - cpuOpponent.stopThread(); - cpuOpponent = null; - myFrozenGame = null; - } - - /** - * The parent must use this method to clear the bubble launch action, - * because this class does not know when to clear it. - */ - public void clearAction() { - if ((action == KeyEvent.KEYCODE_DPAD_UP) || - (action == KeyEvent.KEYCODE_DPAD_DOWN)) - action = 0; - - synchronized(this) { - this.notify(); - } - } - - /** - * Convert the supplied value to a normalized launcher position or - * launcher angle as desired. - * @param isAngle - if true, convert to position from - * angle. Otherwise convert to angle from position. - * @param value - the value to convert. - * @return The converted value. - */ - private double convert(boolean isAngle, double value) { - double result; - - if (isAngle) { - result = (value - Freile.MIN_LAUNCHER) / - (Freile.MAX_LAUNCHER - Freile.MIN_LAUNCHER); - result = FrozenGame.MIN_LAUNCH_DIRECTION + - (result * (FrozenGame.MAX_LAUNCH_DIRECTION - - FrozenGame.MIN_LAUNCH_DIRECTION)); - } - else { - result = ((double)(value - FrozenGame.MIN_LAUNCH_DIRECTION)) / - ((double)(FrozenGame.MAX_LAUNCH_DIRECTION - - FrozenGame.MIN_LAUNCH_DIRECTION)); - result = Freile.MIN_LAUNCHER + - (result * (Freile.MAX_LAUNCHER - Freile.MIN_LAUNCHER)); - } - return result; - } - - /** - * Return the current state of the opponent action. When the AI has - * generated the next action, the action is set to a non-zero value. - * @return returns the value of the CPU opponent action. - */ - public int getAction() { - return action; - } - - public void onOpponentEvent(eventEnum event) { - switch (event) { - case DONE_COMPUTING: - synchronized(this) { - this.notify(); - } - break; - - default: - break; - } - } - - @Override - public void run() { - while(running) { - try { - /* - * Compute the next CPU action. - */ - if (running && (myFrozenGame != null) && !cpuOpponent.isComputing() && - (myFrozenGame.getGameResult() == gameEnum.PLAYING)) - cpuOpponent.compute(myFrozenGame.getCurrentColor(), - myFrozenGame.getNextColor(), - myFrozenGame.getCompressorSteps()); - - /* - * Only fire if the game state permits, and the last virtual - * opponent action has been processed. - */ - if (running && (myFrozenGame != null) && myFrozenGame.getOkToFire() && - (action != KeyEvent.KEYCODE_DPAD_UP)) { - while (running && cpuOpponent.isComputing()) { - synchronized(this) { - wait(); - } - } - - /* - * Initialize a timeout interval to force a bubble launch if - * the CPU opponent takes too long to compute an action. - */ - long timeout = System.currentTimeMillis() + 10000; - - /* - * While the current action is to aim the launcher, keep - * pushing the directional aim command. - */ - int actionNew = 0; - while (running && (myFrozenGame != null) && - (actionNew != KeyEvent.KEYCODE_DPAD_UP) && - (System.currentTimeMillis() < timeout)) { - actionNew = cpuOpponent. - getAction(convert(false, myFrozenGame.getPosition())); - - if (actionNew != KeyEvent.KEYCODE_DPAD_UP) { - action = actionNew; - myPlayerInput.setAction(action, false); - } - - synchronized(this) { - wait(); - } - } - - /* - * Set the launch direction to be as accurate as possible. - */ - if (running && (myFrozenGame != null) && - myFrozenGame.getOkToFire()) { - myFrozenGame. - setPosition(convert(true, cpuOpponent.getExactDirection(0))); - action = actionNew; - myPlayerInput.setAction(action, false); - } - } - - if (running) { - synchronized(this) { - wait(); - } - } - } catch (InterruptedException e) { - } finally { - } - } - cleanUp(); - } - - /** - * Stop the thread run() execution. - *

Interrupt the thread when it is suspended via - * wait(). - */ - public void stopThread() { - running = false; - - synchronized(this) { - this.notify(); - } - } -} diff --git a/src/com/efortin/frozenbubble/HighscoreDB.java b/src/com/efortin/frozenbubble/HighscoreDB.java deleted file mode 100644 index 7bab2c2..0000000 --- a/src/com/efortin/frozenbubble/HighscoreDB.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * High score manager source - Copyright (c) 2010 Michel Racic. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -/** - * SQlite DB adapter class based on the code from:
- * http://www.screaming-penguin.com/node/7742 - * - * @author Michel Racic (http://www.2030.tk) - * - */ -import java.util.ArrayList; -import java.util.List; - -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.database.sqlite.SQLiteStatement; -import android.util.Log; - -public class HighscoreDB { - private static final int DATABASE_VERSION = 1; - private static final String TABLE_NAME = "highscore"; - private static String databaseName; - - private final Context context; - private final SQLiteDatabase db; - private final SQLiteStatement insertStmt; - private static final String INSERT = "insert into " + TABLE_NAME + - "(level, name, shots, time) values (?,?,?,?)"; - - - public HighscoreDB(Context context, String databaseName) { - this.context = context; - HighscoreDB.databaseName = databaseName; - OpenHelper openHelper = new OpenHelper(this.context); - db = openHelper.getWritableDatabase(); - insertStmt = db.compileStatement(INSERT); - } - - public void close() { - db.close(); - } - - public long insert(HighscoreDO hi) { - insertStmt.bindLong(1, hi.getLevel()); - insertStmt.bindString(2, hi.getName()); - insertStmt.bindLong(3, hi.getShots()); - insertStmt.bindLong(4, hi.getTime()); - return insertStmt.executeInsert(); - } - - public void deleteAll() { - db.delete(TABLE_NAME, null, null); - } - - public void deleteById(int id) { - db.delete(TABLE_NAME, "id=" + id, null); - } - - public List selectAll() { - List list = new ArrayList(); - Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, - "level asc, shots asc, time asc"); - if (cursor.moveToFirst()) { - do { - list.add(new HighscoreDO(cursor.getInt(0), cursor.getInt(1), - cursor.getString(2), cursor.getInt(3), cursor.getLong(4))); - } while (cursor.moveToNext()); - } - if ((cursor != null) && !cursor.isClosed()) { - cursor.close(); - } - return list; - } - - public List selectByLevel(int level, int limit) { - List list = new ArrayList(); - Cursor cursor = db.query(TABLE_NAME, null, "level=" + level, null, - null, null, "shots asc, time asc", "" + limit); - if (cursor.moveToFirst()) { - do { - list.add(new HighscoreDO(cursor.getInt(0), cursor.getInt(1), - cursor.getString(2), cursor.getInt(3), cursor.getLong(4))); - } while (cursor.moveToNext()); - } - if ((cursor != null) && !cursor.isClosed()) { - cursor.close(); - } - return list; - } - - public List selectLastByLevel(int level, int limit) { - List list = new ArrayList(); - Cursor cursor = db.query(TABLE_NAME, null, "level=" + level, null, - null, null, "shots asc, time asc", null); - if (cursor.moveToLast()) { - int index = 0; - do { - list.add(new HighscoreDO(cursor.getInt(0), cursor.getInt(1), - cursor.getString(2), cursor.getInt(3), cursor.getLong(4))); - index++; - } while (cursor.moveToPrevious() && (index < limit)); - } - if ((cursor != null) && !cursor.isClosed()) { - cursor.close(); - } - return list; - } - - private static class OpenHelper extends SQLiteOpenHelper { - OpenHelper(Context context) { - super(context, databaseName, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + TABLE_NAME + - " (id INTEGER PRIMARY KEY, level INTEGER, name TEXT, shots INTEGER, time LONG)"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w("Example", - "Upgrading database, this will drop tables and recreate."); - db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); - onCreate(db); - } - } -} diff --git a/src/com/efortin/frozenbubble/HighscoreDO.java b/src/com/efortin/frozenbubble/HighscoreDO.java deleted file mode 100644 index 5db9744..0000000 --- a/src/com/efortin/frozenbubble/HighscoreDO.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * High score manager source - Copyright (c) 2010 Michel Racic. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -/** - * @author Michel Racic (http://www.2030.tk) - * - */ -public class HighscoreDO { - private int id; - private int level; - private String name; - private int shots; - private long time; - - /** - * Used when reading entries from the database. - * - * @param id - * @param level - * @param name - * @param shots - * @param time - */ - public HighscoreDO(int id, int level, String name, int shots, long time) { - super(); - this.shots = shots; - this.id = id; - this.level = level; - this.name = name; - this.time = time; - } - - /** - * Used when an entry is not yet in the database (no ID). - * - * @param level - * @param name - * @param shots - * @param time - */ - public HighscoreDO(int level, String name, int shots, long time) { - super(); - this.shots = shots; - id = -1; - this.level = level; - this.name = name; - this.time = time; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public int getLevel() { - return level; - } - - public void setLevel(int level) { - this.level = level; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getShots() { - return shots; - } - - public void setShots(int shots) { - this.shots = shots; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } -} diff --git a/src/com/efortin/frozenbubble/HighscoreManager.java b/src/com/efortin/frozenbubble/HighscoreManager.java deleted file mode 100644 index c104816..0000000 --- a/src/com/efortin/frozenbubble/HighscoreManager.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * High score manager source - Copyright (c) 2010 Michel Racic. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * Eric Fortin - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import java.util.List; - -import android.content.Context; -import android.os.Bundle; - -/** - * A class to manage the highscore table for each level. - * @author Michel Racic (http://www.2030.tk) - * - */ -public class HighscoreManager { - - public static final String PUZZLE_DATABASE_NAME = "frozenbubble"; - public static final String MULTIPLAYER_DATABASE_NAME = "multiplayer"; - public static final String ARCADE_DATABASE_NAME = "arcade"; - - private boolean isPaused = true; - private int currentLevel = 0; - private long startTime = 0; - private long pausedTime = 0; - private long lastScoreId = -1; - private final HighscoreDB db; - private final Context ctx; - String name = null; - - public HighscoreManager(Context context, String databaseName) { - ctx = context; - db = new HighscoreDB(ctx, databaseName); - } - - public void close() { - db.close(); - } - - /** - * Take snapshots of the game statistics and store them in a database - * object. - * @param nbBubbles - The number of bubbles launched by the player. - */ - public void endLevel(int nbBubbles) { - long endTime = System.currentTimeMillis(); - long duration = (endTime - startTime) + pausedTime; - - if ( duration < 0 ) - duration = 0; - /* - if (name == null) { - SharedPreferences sp = ctx.getSharedPreferences(FrozenBubble.PREFS_NAME, - Context.MODE_PRIVATE); - name = sp.getString("highscorename", "anon"); - } - // - // Prompt the player to enter their name to enter into the high - // scores table. - // - // - AlertDialog.Builder alert = new AlertDialog.Builder(ctx); - alert.setTitle("Highscore name"); alert.setMessage("Set your name:"); - final EditText input = new EditText(ctx); input.setText(name); - alert.setView(input); - alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - SharedPreferences sp = - ctx.getSharedPreferences(FrozenBubble.PREFS_NAME, - Context.MODE_PRIVATE); - SharedPreferences.Editor editor = sp.edit(); - editor.putString("highscorename", input.getText() .toString()); - editor.commit(); - } - }); - alert.show(); - SharedPreferences sp = ctx.getSharedPreferences(FrozenBubble.PREFS_NAME, - Context.MODE_PRIVATE); - name = sp.getString("highscorename", "anon"); - */ - lastScoreId = db.insert(new HighscoreDO(currentLevel, "anon", - nbBubbles, duration)); - //Log.i("FrozenBubble-highscore", "endLevel() " + (duration / 1000F) + - // " seconds and " + nbBubbles + " shots used for level " + currentLevel); - } - - public void lostLevel() { - lastScoreId = -1; - } - - public void startLevel(int level) { - startTime = System.currentTimeMillis(); - currentLevel = level; - pausedTime = 0; - isPaused = false; - //Log.i("FrozenBubble-highscore", "startLevel(" + level + ")"); - } - - /** - * Accumulate the play time between pause/resume cycles. - *

pausedTime is an accumulation of the play time - * between pause/resume cycles. - */ - public void pauseLevel() { - long currentTime = System.currentTimeMillis(); - if (!isPaused) { - isPaused = true; - pausedTime += currentTime - startTime; - } - startTime = currentTime; - //Log.i("FrozenBubble-highscore", "pauseLevel() " + (pausedTime / 1000F) + - // " seconds used"); - } - - public void resumeLevel() { - startTime = System.currentTimeMillis(); - isPaused = false; - //Log.i("FrozenBubble-highscore", "resumeLevel() " + (pausedTime / 1000F) + - // " seconds used"); - } - - public void saveState(Bundle map) { - pauseLevel(); - map.putInt("HighscoreManager-currentLevel", currentLevel); - map.putLong("HighscoreManager-pausedTime", pausedTime); - //Log.i("FrozenBubble-highscore", "saveState() " + (pausedTime / 1000F) + - // " seconds used in level " + currentLevel); - } - - public void restoreState(Bundle map) { - currentLevel = map.getInt("LevelManager-currentLevel"); - pausedTime = map.getLong("HighscoreManager-pausedTime"); - resumeLevel(); - //Log.i("FrozenBubble-highscore", "restoreState() " + (pausedTime / 1000F) + - // " seconds used in level " + currentLevel); - } - - public List getLowScore(int level, int limit) { - return db.selectLastByLevel(level, limit); - } - - public List getHighScore(int level, int limit) { - return db.selectByLevel(level, limit); - } - - public int getLevel() { - return currentLevel; - } - - public long getLastScoreId() { - return lastScoreId; - } -} diff --git a/src/com/efortin/frozenbubble/HomeScreen.java b/src/com/efortin/frozenbubble/HomeScreen.java deleted file mode 100644 index 31ad6a9..0000000 --- a/src/com/efortin/frozenbubble/HomeScreen.java +++ /dev/null @@ -1,919 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import org.jfedor.frozenbubble.FrozenBubble; -import org.jfedor.frozenbubble.R; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.graphics.Typeface; -import android.os.Bundle; -import android.util.TypedValue; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.RelativeLayout.LayoutParams; - -public class HomeScreen extends Activity { - /* - * Provide unique IDs for the views associated with the relative - * layout. These are used to define relative view layout positions - * with respect to other views in the layout. - * - * These IDs are generated automatically if using an XML layout, but - * this object implements a RelativeLayout that is constructed purely - * programmatically. - */ - private final static int SCREEN_ID = 100; - private final static int BACK_ID = 101; - private final static int BTN1_ID = 102; - private final static int BTN2_ID = 103; - private final static int BTN3_ID = 104; - private final static int BTN4_ID = 105; - private final static int BTN5_ID = 106; - private final static int BTN6_ID = 107; - private final static int BTN7_ID = 108; - private final static int BTN8_ID = 109; - private final static int BTN9_ID = 110; - - private static int buttonSelected = BTN1_ID; - private static int buttonSelPage1 = BTN1_ID; - private static int buttonSelPage2 = BTN5_ID; - private static int buttonSelPage3 = BTN8_ID; - - private boolean finished = false; - private boolean homeShown = false; - private boolean musicOn = true; - private ImageView myImageView = null; - private RelativeLayout myLayout = null; - private ModPlayer myModPlayer = null; - private Thread splashThread = null; - - /** - * Given that we are using a relative layout for the home screen in - * order to display the background image and various buttons, this - * function programmatically adds an on-screen back button to the - * layout. - */ - private void addBackButton() { - /* - * Construct the back button. - */ - Button backButton = new Button(this); - backButton.setOnClickListener(new Button.OnClickListener(){ - public void onClick(View v){ - backKeyPress(); - } - }); - backButton.setOnTouchListener(new Button.OnTouchListener(){ - public boolean onTouch(View v, MotionEvent event){ - if (event.getAction() == MotionEvent.ACTION_DOWN) - v.requestFocus(); - return false; - } - }); - /* - * Set the back button text to the following Unicode character: - * Anticlockwise Top Semicircle Arrow - * http://en.wikipedia.org/wiki/Arrow_(symbol) - */ - backButton.setText("\u21B6"); - backButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 30); - backButton.setWidth((int) backButton.getTextSize() * 2); - backButton.setTypeface(null, Typeface.BOLD); - backButton.setBackgroundResource(R.drawable.round_button); - backButton.setId(BACK_ID); - backButton.setFocusable(true); - backButton.setFocusableInTouchMode(true); - LayoutParams myParams = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - myParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); - myParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); - myParams.topMargin = 25; - myParams.rightMargin = 25; - /* - * Add view to layout. - */ - myLayout.addView(backButton, myParams); - } - - /** - * Given that we are using a relative layout for the home screen in - * order to display the background image and various buttons, this - * function adds the buttons to the layout to provide game options to - * the player. - *

The buttons are defined in relation to one another so that when - * using keys to navigate the buttons, the appropriate button will be - * highlighted. - */ - private void addHomeButtons() { - /* - * Construct the 2 player game button. - */ - Button start2pGameButton = new Button(this); - start2pGameButton.setOnClickListener(new Button.OnClickListener(){ - public void onClick(View v){ - buttonSelected = BTN3_ID; - buttonSelPage1 = BTN3_ID; - /* - * Display the 2 player mode buttons page. - */ - displayButtonPage(2); - } - }); - start2pGameButton.setOnTouchListener(new Button.OnTouchListener(){ - public boolean onTouch(View v, MotionEvent event){ - if (event.getAction() == MotionEvent.ACTION_DOWN) - v.requestFocus(); - return false; - } - }); - start2pGameButton.setText("2 Player"); - start2pGameButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - start2pGameButton.setWidth((int) (start2pGameButton.getTextSize() * 9)); - start2pGameButton.setTypeface(null, Typeface.BOLD); - start2pGameButton.setHorizontalFadingEdgeEnabled(true); - start2pGameButton.setFadingEdgeLength(5); - start2pGameButton.setShadowLayer(5, 5, 5, R.color.black); - start2pGameButton.setId(BTN3_ID); - start2pGameButton.setFocusable(true); - start2pGameButton.setFocusableInTouchMode(true); - LayoutParams myParams1 = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - myParams1.addRule(RelativeLayout.CENTER_IN_PARENT); - myParams1.topMargin = 15; - myParams1.bottomMargin = 15; - /* - * Add view to layout. - */ - myLayout.addView(start2pGameButton, myParams1); - /* - * Construct the 1 player game button. - */ - Button start1pGameButton = new Button(this); - start1pGameButton.setOnClickListener(new Button.OnClickListener(){ - public void onClick(View v){ - buttonSelected = BTN2_ID; - buttonSelPage1 = BTN2_ID; - /* - * Process the button tap and start/resume a 1 player game. - */ - startFrozenBubble(VirtualInput.PLAYER1, 1, - FrozenBubble.HUMAN, - FrozenBubble.LOCALE_LOCAL, false); - } - }); - start1pGameButton.setOnTouchListener(new Button.OnTouchListener(){ - public boolean onTouch(View v, MotionEvent event){ - if (event.getAction() == MotionEvent.ACTION_DOWN) - v.requestFocus(); - return false; - } - }); - start1pGameButton.setText("Puzzle"); - start1pGameButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - start1pGameButton.setWidth((int) (start1pGameButton.getTextSize() * 9)); - start1pGameButton.setTypeface(null, Typeface.BOLD); - start1pGameButton.setHorizontalFadingEdgeEnabled(true); - start1pGameButton.setFadingEdgeLength(5); - start1pGameButton.setShadowLayer(5, 5, 5, R.color.black); - start1pGameButton.setId(BTN2_ID); - start1pGameButton.setFocusable(true); - start1pGameButton.setFocusableInTouchMode(true); - LayoutParams myParams2 = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - myParams2.addRule(RelativeLayout.CENTER_IN_PARENT); - myParams2.addRule(RelativeLayout.ABOVE, start2pGameButton.getId()); - myParams2.topMargin = 15; - myParams2.bottomMargin = 15; - /* - * Add view to layout. - */ - myLayout.addView(start1pGameButton, myParams2); - /* - * Construct the 1 player arcade game button. - */ - Button startArcadeGameButton = new Button(this); - startArcadeGameButton.setOnClickListener(new Button.OnClickListener(){ - public void onClick(View v){ - buttonSelected = BTN1_ID; - buttonSelPage1 = BTN1_ID; - /* - * Process the button tap and start/resume a 1 player arcade - * game. - */ - startFrozenBubble(VirtualInput.PLAYER1, 1, - FrozenBubble.HUMAN, - FrozenBubble.LOCALE_LOCAL, true); - } - }); - startArcadeGameButton.setOnTouchListener(new Button.OnTouchListener(){ - public boolean onTouch(View v, MotionEvent event){ - if (event.getAction() == MotionEvent.ACTION_DOWN) - v.requestFocus(); - return false; - } - }); - startArcadeGameButton.setText("Arcade"); - startArcadeGameButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - startArcadeGameButton.setWidth((int) (startArcadeGameButton.getTextSize() * 9)); - startArcadeGameButton.setTypeface(null, Typeface.BOLD); - startArcadeGameButton.setHorizontalFadingEdgeEnabled(true); - startArcadeGameButton.setFadingEdgeLength(5); - startArcadeGameButton.setShadowLayer(5, 5, 5, R.color.black); - startArcadeGameButton.setId(BTN1_ID); - startArcadeGameButton.setFocusable(true); - startArcadeGameButton.setFocusableInTouchMode(true); - LayoutParams myParams3 = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - myParams3.addRule(RelativeLayout.CENTER_IN_PARENT); - myParams3.addRule(RelativeLayout.ABOVE, start1pGameButton.getId()); - myParams3.topMargin = 15; - myParams3.bottomMargin = 15; - /* - * Add view to layout. - */ - myLayout.addView(startArcadeGameButton, myParams3); - /* - * Construct the options button. - */ - Button optionsButton = new Button(this); - optionsButton.setOnClickListener(new Button.OnClickListener(){ - public void onClick(View v){ - buttonSelected = BTN4_ID; - buttonSelPage1 = BTN4_ID; - /* - * Process the button tap and start the preferences activity. - */ - startPreferencesScreen(); - } - }); - optionsButton.setOnTouchListener(new Button.OnTouchListener(){ - public boolean onTouch(View v, MotionEvent event){ - if (event.getAction() == MotionEvent.ACTION_DOWN) - v.requestFocus(); - return false; - } - }); - optionsButton.setText("Options"); - optionsButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - optionsButton.setWidth((int) (optionsButton.getTextSize() * 9)); - optionsButton.setTypeface(null, Typeface.BOLD); - optionsButton.setHorizontalFadingEdgeEnabled(true); - optionsButton.setFadingEdgeLength(5); - optionsButton.setShadowLayer(5, 5, 5, R.color.black); - optionsButton.setId(BTN4_ID); - optionsButton.setFocusable(true); - optionsButton.setFocusableInTouchMode(true); - LayoutParams myParams4 = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - myParams4.addRule(RelativeLayout.CENTER_IN_PARENT); - myParams4.addRule(RelativeLayout.BELOW, start2pGameButton.getId()); - myParams4.topMargin = 15; - myParams4.bottomMargin = 15; - /* - * Add view to layout. - */ - myLayout.addView(optionsButton, myParams4); - } - - /** - * Given that we are using a relative layout for the home screen in - * order to display the background image and various buttons, this - * function adds the buttons to the layout to provide multiplayer game - * options to the player. - *

The buttons are defined in relation to one another so that when - * using keys to navigate the buttons, the appropriate button will be - * highlighted. - */ - private void addMultiplayerButtons() { - /* - * Construct the WiFi game button. - */ - Button startWiFiGameButton = new Button(this); - startWiFiGameButton.setOnClickListener(new Button.OnClickListener(){ - public void onClick(View v){ - buttonSelected = BTN6_ID; - buttonSelPage2 = BTN6_ID; - /* - * Display the player ID buttons page. - */ - displayButtonPage(3); - } - }); - startWiFiGameButton.setOnTouchListener(new Button.OnTouchListener(){ - public boolean onTouch(View v, MotionEvent event){ - if (event.getAction() == MotionEvent.ACTION_DOWN) - v.requestFocus(); - return false; - } - }); - startWiFiGameButton.setText("WiFi"); - startWiFiGameButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - startWiFiGameButton.setWidth((int) (startWiFiGameButton.getTextSize() * 9)); - startWiFiGameButton.setTypeface(null, Typeface.BOLD); - startWiFiGameButton.setHorizontalFadingEdgeEnabled(true); - startWiFiGameButton.setFadingEdgeLength(5); - startWiFiGameButton.setShadowLayer(5, 5, 5, R.color.black); - startWiFiGameButton.setId(BTN6_ID); - startWiFiGameButton.setFocusable(true); - startWiFiGameButton.setFocusableInTouchMode(true); - LayoutParams myParams1 = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - myParams1.addRule(RelativeLayout.CENTER_IN_PARENT); - myParams1.topMargin = 15; - myParams1.bottomMargin = 15; - /* - * Add view to layout. - */ - myLayout.addView(startWiFiGameButton, myParams1); - /* - * Construct the Player vs. CPU game button. - */ - Button startCPUGameButton = new Button(this); - startCPUGameButton.setOnClickListener(new Button.OnClickListener(){ - public void onClick(View v){ - buttonSelected = BTN5_ID; - buttonSelPage2 = BTN5_ID; - /* - * Process the button tap and start a 2 player game. - */ - startFrozenBubble(VirtualInput.PLAYER1, 2, - FrozenBubble.CPU, - FrozenBubble.LOCALE_LOCAL, false); - } - }); - startCPUGameButton.setOnTouchListener(new Button.OnTouchListener(){ - public boolean onTouch(View v, MotionEvent event){ - if (event.getAction() == MotionEvent.ACTION_DOWN) - v.requestFocus(); - return false; - } - }); - startCPUGameButton.setText("Player vs. CPU"); - startCPUGameButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - startCPUGameButton.setWidth((int) (startCPUGameButton.getTextSize() * 9)); - startCPUGameButton.setTypeface(null, Typeface.BOLD); - startCPUGameButton.setHorizontalFadingEdgeEnabled(true); - startCPUGameButton.setFadingEdgeLength(5); - startCPUGameButton.setShadowLayer(5, 5, 5, R.color.black); - startCPUGameButton.setId(BTN5_ID); - startCPUGameButton.setFocusable(true); - startCPUGameButton.setFocusableInTouchMode(true); - LayoutParams myParams2 = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - myParams2.addRule(RelativeLayout.CENTER_IN_PARENT); - myParams2.addRule(RelativeLayout.ABOVE, startWiFiGameButton.getId()); - myParams2.topMargin = 15; - myParams2.bottomMargin = 15; - /* - * Add view to layout. - */ - myLayout.addView(startCPUGameButton, myParams2); - /* - * Construct the Bluetooth network game button. - */ - Button startBluetoothGameButton = new Button(this); - startBluetoothGameButton.setOnClickListener(new Button.OnClickListener(){ - public void onClick(View v){ - buttonSelected = BTN7_ID; - buttonSelPage2 = BTN7_ID; - /* - * Display the player ID buttons page. - */ - displayButtonPage(3); - } - }); - startBluetoothGameButton.setOnTouchListener(new Button.OnTouchListener(){ - public boolean onTouch(View v, MotionEvent event){ - if (event.getAction() == MotionEvent.ACTION_DOWN) - v.requestFocus(); - return false; - } - }); - startBluetoothGameButton.setText("Bluetooth"); - startBluetoothGameButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - startBluetoothGameButton.setWidth((int) (startBluetoothGameButton.getTextSize() * 9)); - startBluetoothGameButton.setTypeface(null, Typeface.BOLD); - startBluetoothGameButton.setHorizontalFadingEdgeEnabled(true); - startBluetoothGameButton.setFadingEdgeLength(5); - startBluetoothGameButton.setShadowLayer(5, 5, 5, R.color.black); - startBluetoothGameButton.setId(BTN7_ID); - startBluetoothGameButton.setFocusable(true); - startBluetoothGameButton.setFocusableInTouchMode(true); - if (BluetoothManager.getPairedDevices() == null) { - startBluetoothGameButton.setEnabled(false); - } - LayoutParams myParams3 = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - myParams3.addRule(RelativeLayout.CENTER_IN_PARENT); - myParams3.addRule(RelativeLayout.BELOW, startWiFiGameButton.getId()); - myParams3.topMargin = 15; - myParams3.bottomMargin = 15; - /* - * Add view to layout. - */ - myLayout.addView(startBluetoothGameButton, myParams3); - } - - /** - * Given that we are using a relative layout for the home screen in - * order to display the background image and various buttons, this - * function adds the buttons to the layout to provide player ID - * selection options to the player. - *

The buttons are defined in relation to one another so that when - * using keys to navigate the buttons, the appropriate button will be - * highlighted. - */ - private void addPlayerSelectButtons() { - /* - * Construct the player 2 button. - */ - Button player2Button = new Button(this); - player2Button.setOnClickListener(new Button.OnClickListener(){ - public void onClick(View v){ - buttonSelected = BTN9_ID; - buttonSelPage3 = BTN9_ID; - /* - * Process the button tap and start a 2 player game. - */ - if (buttonSelPage2 == BTN7_ID) { - startFrozenBubble(VirtualInput.PLAYER2, 2, - FrozenBubble.HUMAN, - FrozenBubble.LOCALE_BLUETOOTH, false); - } - else { - startFrozenBubble(VirtualInput.PLAYER2, 2, - FrozenBubble.HUMAN, - FrozenBubble.LOCALE_WIFI, false); - } - } - }); - player2Button.setOnTouchListener(new Button.OnTouchListener(){ - public boolean onTouch(View v, MotionEvent event){ - if (event.getAction() == MotionEvent.ACTION_DOWN) - v.requestFocus(); - return false; - } - }); - player2Button.setText("Player 2"); - player2Button.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - player2Button.setWidth((int) (player2Button.getTextSize() * 9)); - player2Button.setTypeface(null, Typeface.BOLD); - player2Button.setHorizontalFadingEdgeEnabled(true); - player2Button.setFadingEdgeLength(5); - player2Button.setShadowLayer(5, 5, 5, R.color.black); - player2Button.setId(BTN9_ID); - player2Button.setFocusable(true); - player2Button.setFocusableInTouchMode(true); - LayoutParams myParams1 = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - myParams1.addRule(RelativeLayout.CENTER_IN_PARENT); - myParams1.topMargin = 15; - myParams1.bottomMargin = 15; - /* - * Add view to layout. - */ - myLayout.addView(player2Button, myParams1); - /* - * Construct the player 1 button. - */ - Button player1Button = new Button(this); - player1Button.setOnClickListener(new Button.OnClickListener(){ - public void onClick(View v){ - buttonSelected = BTN8_ID; - buttonSelPage3 = BTN8_ID; - /* - * Process the button tap and start a 2 player game. - */ - if (buttonSelPage2 == BTN7_ID) { - startFrozenBubble(VirtualInput.PLAYER1, 2, - FrozenBubble.HUMAN, - FrozenBubble.LOCALE_BLUETOOTH, false); - } - else { - startFrozenBubble(VirtualInput.PLAYER1, 2, - FrozenBubble.HUMAN, - FrozenBubble.LOCALE_WIFI, false); - } - } - }); - player1Button.setOnTouchListener(new Button.OnTouchListener(){ - public boolean onTouch(View v, MotionEvent event){ - if (event.getAction() == MotionEvent.ACTION_DOWN) - v.requestFocus(); - return false; - } - }); - player1Button.setText("Player 1"); - player1Button.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - player1Button.setWidth((int) (player1Button.getTextSize() * 9)); - player1Button.setTypeface(null, Typeface.BOLD); - player1Button.setHorizontalFadingEdgeEnabled(true); - player1Button.setFadingEdgeLength(5); - player1Button.setShadowLayer(5, 5, 5, R.color.black); - player1Button.setId(BTN8_ID); - player1Button.setFocusable(true); - player1Button.setFocusableInTouchMode(true); - LayoutParams myParams2 = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - myParams2.addRule(RelativeLayout.CENTER_IN_PARENT); - myParams2.addRule(RelativeLayout.ABOVE, player2Button.getId()); - myParams2.topMargin = 15; - myParams2.bottomMargin = 15; - /* - * Add view to layout. - */ - myLayout.addView(player1Button, myParams2); - } - - private void backKeyPress() { - /* - * When one of the multiplayer game buttons was selected, if the - * back button was pressed, remove the multiplayer buttons and - * display the home buttons. The 2 player button becomes selected - * by default on the home screen. - * - * Otherwise if one of the base level buttons was selected, then - * terminate the home screen activity. - */ - if ((buttonSelected == BTN5_ID) || - (buttonSelected == BTN6_ID) || - (buttonSelected == BTN7_ID)) { - displayButtonPage(1); - } - else if ((buttonSelected == BTN8_ID) || - (buttonSelected == BTN9_ID)) { - displayButtonPage(2); - } - else { - finished = true; - cleanUp(); - finish(); - } - } - - private void cleanUp() { - if (myModPlayer != null) { - myModPlayer.destroyMusicPlayer(); - myModPlayer = null; - } - } - - /** - * Manage a set of button "pages", where each page displays buttons. - * The pages are indexed by a unique identifier. When a valid page - * identifier is provided, all buttons corresponding to other pages - * are removed and the buttons for the requested page ID are added. - * @param pageID - the requested page identifier (1-based). - */ - private void displayButtonPage(int pageID) { - if (pageID == 1) { - buttonSelected = buttonSelPage1; - removeViewByID(BTN5_ID); - removeViewByID(BTN6_ID); - removeViewByID(BTN7_ID); - removeViewByID(BTN8_ID); - removeViewByID(BTN9_ID); - addHomeButtons(); - selectInitialButton(); - } - else if (pageID == 2) { - buttonSelected = buttonSelPage2; - removeViewByID(BTN1_ID); - removeViewByID(BTN2_ID); - removeViewByID(BTN3_ID); - removeViewByID(BTN4_ID); - removeViewByID(BTN8_ID); - removeViewByID(BTN9_ID); - addMultiplayerButtons(); - selectInitialButton(); - } - else if (pageID == 3) { - buttonSelected = buttonSelPage3; - removeViewByID(BTN1_ID); - removeViewByID(BTN2_ID); - removeViewByID(BTN3_ID); - removeViewByID(BTN4_ID); - removeViewByID(BTN5_ID); - removeViewByID(BTN6_ID); - removeViewByID(BTN7_ID); - addPlayerSelectButtons(); - selectInitialButton(); - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - boolean handled = false; - if (keyCode == KeyEvent.KEYCODE_BACK) { - backKeyPress(); - handled = true; - } - return handled || super.onKeyDown(keyCode, event); - } - - /* - * (non-Javadoc) - * @see android.app.Activity#onCreate(android.os.Bundle) - * Called when the activity is first created. - */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - finished = false; - restoreGamePrefs(); - /* - * Configure the window presentation and layout. - */ - setWindowLayout(); - myLayout = new RelativeLayout(this); - myLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, - LayoutParams.FILL_PARENT)); - myImageView = new ImageView(this); - - if (FrozenBubble.numPlayers != 0) - startFrozenBubble(FrozenBubble.myPlayerId, - FrozenBubble.numPlayers, - FrozenBubble.opponentId, - FrozenBubble.gameLocale, - FrozenBubble.arcadeGame); - else if (getIntent().hasExtra("startHomeScreen")) { - setBackgroundImage(R.drawable.home_screen); - setContentView(myLayout); - startHomeScreen(); - } - else { - setBackgroundImage(R.drawable.splash); - setContentView(myLayout); - /* - * Thread for managing the splash screen. - */ - splashThread = new Thread() { - @Override - public void run() { - try { - synchronized(this) { - /* - * TODO: The splash screen waits before launching the - * game activity. Change this so that the game activity - * is started immediately, and notifies the splash screen - * activity when it is done loading saved state data and - * preferences, so the splash screen functions as a - * distraction from game loading latency. There is no - * advantage in doing this right now, because there is no - * perceivable lag. - */ - /* - * Display the splash screen image for 3 seconds. - */ - wait(3000); - } - } catch (InterruptedException e) { - } finally { - if (!finished) { - runOnUiThread(new Runnable() { - public void run() { - startHomeScreen(); - } - }); - } - } - } - }; - splashThread.start(); - } - } - - @Override - public void onPause() { - super.onPause(); - if (myModPlayer != null) { - myModPlayer.pausePlay(); - } - } - - @Override - public void onResume() { - super.onPause(); - if (myModPlayer != null) { - restoreGamePrefs(); - if (musicOn) - myModPlayer.unPausePlay(); - } - } - - /* - * (non-Javadoc) - * @see android.app.Activity#onTouchEvent(android.view.MotionEvent) - * Invoked when the screen is touched. - */ - @Override - public boolean onTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - if (splashThread != null) { - synchronized(splashThread) { - splashThread.notifyAll(); - } - } - } - return true; - } - - private void removeViewByID(int id) { - if (myLayout != null) { - myLayout.removeView(myLayout.findViewById(id)); - } - } - - private void restoreGamePrefs() { - SharedPreferences mConfig = getSharedPreferences(FrozenBubble.PREFS_NAME, - Context.MODE_PRIVATE); - musicOn = mConfig.getBoolean("musicOn", true ); - } - - private void selectInitialButton() { - /* - * Select the last button that was pressed. - */ - Button selectedButton = (Button) myLayout.findViewById(buttonSelected); - selectedButton.requestFocus(); - selectedButton.setSelected(true); - } - - private void setBackgroundImage(int resId) { - if (myImageView.getParent() != null) - myLayout.removeView(myImageView); - - myImageView.setBackgroundColor(getResources().getColor(R.color.black)); - myImageView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, - LayoutParams.FILL_PARENT)); - myImageView.setImageResource(resId); - myImageView.setId(SCREEN_ID); - myLayout.addView(myImageView); - } - - /** - * Set the window layout according to the game preferences. - *

Requesting that the title bar be removed must be - * performed before setting the view content by applying the XML - * layout, or it will generate an exception. - */ - private void setWindowLayout() { - final int flagFs = WindowManager.LayoutParams.FLAG_FULLSCREEN; - final int flagNoFs = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN; - /* - * Remove the title bar. - */ - requestWindowFeature(Window.FEATURE_NO_TITLE); - /* - * Set full screen mode based on the game preferences. - */ - SharedPreferences mConfig = - getSharedPreferences(FrozenBubble.PREFS_NAME, Context.MODE_PRIVATE); - boolean fullscreen = mConfig.getBoolean("fullscreen", true); - - if (fullscreen) { - getWindow().addFlags(flagFs); - getWindow().clearFlags(flagNoFs); - } - else { - getWindow().clearFlags(flagFs); - getWindow().addFlags(flagNoFs); - } - } - - /** - * Start the game with the specified number of players in the - * specified locale. A 1 player game can only be played locally. - * @param myPlayerId - the local player ID. - * @param numPlayers - the number of players (1 or 2). - * @param opponentId - the opponent type ID, human or CPU. - * @param gameLocale - the location of the opponent. A local opponent - * will be played by the CPU. A LAN opponent will be played over the - * network using multicasting, and an internet opponent will be played - * using TCP. - * @param arcadeGame - endless arcade game that scrolls new bubbles. - */ - private void startFrozenBubble(int myPlayerId, - int numPlayers, - int opponentId, - int gameLocale, - boolean arcadeGame) { - finished = true; - /* - * Since the default game activity creates its own player, - * destroy the current player. - */ - cleanUp(); - /* - * Create an intent to launch the activity to play the game. - */ - Intent intent = new Intent(this, FrozenBubble.class); - intent.putExtra("myPlayerId", (int) myPlayerId); - intent.putExtra("numPlayers", (int) numPlayers); - intent.putExtra("opponentId", (int) opponentId); - intent.putExtra("gameLocale", (int) gameLocale); - intent.putExtra("arcadeGame", (boolean) arcadeGame); - - startActivity(intent); - /* - * Terminate the splash screen activity. - */ - finish(); - } - - private void startHomeScreen() { - if (!homeShown) { - homeShown = true; - setBackgroundImage(R.drawable.home_screen); - addBackButton(); - if ((buttonSelected == BTN1_ID) || - (buttonSelected == BTN2_ID) || - (buttonSelected == BTN3_ID) || - (buttonSelected == BTN4_ID)) - addHomeButtons(); - else if ((buttonSelected == BTN5_ID) || - (buttonSelected == BTN6_ID) || - (buttonSelected == BTN7_ID)) - addMultiplayerButtons(); - else - addPlayerSelectButtons(); - setContentView(myLayout); - myLayout.setFocusable(true); - myLayout.setFocusableInTouchMode(true); - myLayout.requestFocus(); - /* - * Highlight the appropriate button to show as selected. - */ - selectInitialButton(); - /* - * Create a new music player to play the home screen music. - */ - myModPlayer = new ModPlayer(this, R.raw.introzik, musicOn, false); - } - } - - private void startPreferencesScreen() { - Intent intent = new Intent(this, PreferencesActivity.class); - startActivity(intent); - } -} diff --git a/src/com/efortin/frozenbubble/ModPlayer.java b/src/com/efortin/frozenbubble/ModPlayer.java deleted file mode 100644 index 4d20a9f..0000000 --- a/src/com/efortin/frozenbubble/ModPlayer.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import android.content.Context; - -import com.peculiargames.andmodplug.MODResourcePlayer; -import com.peculiargames.andmodplug.PlayerThread; - -public class ModPlayer { - private MODResourcePlayer resPlayer = null; - - public ModPlayer(Context context, - int songId, - boolean musicOn, - boolean startPaused) { - newMusicPlayer(context, songId, musicOn, startPaused); - } - - /** - * Stop the music player, close the thread, and free the instance. - */ - public void destroyMusicPlayer() { - synchronized(this) { - if (resPlayer != null) { - resPlayer.stopAndClose(); - resPlayer = null; - } - } - } - - /** - * Load a new song. - * @param songId - The song resource ID. - * @param startPlaying - If true, the song starts playing - * immediately. Otherwise it is paused and must be unpaused to start - * playing. - */ - public void loadNewSong(int songId, boolean startPlaying) { - if (resPlayer != null) { - // Pause the current song. - resPlayer.pausePlay(true); - // Load the current MOD into the player. - resPlayer.loadModuleResource(songId); - if (startPlaying) - resPlayer.unPausePlay(); - } - } - - /** - * Create a new music player. - * @param context - The application context. - * @param songId - The song resource ID. - * @param startPaused - If false, the song starts playing - * immediately. Otherwise it is paused and must be unpaused to start - * playing. - */ - private void newMusicPlayer(Context context, - int songId, - boolean musicOn, - boolean startPaused) { - // Create a new music player. - resPlayer = new MODResourcePlayer(context); - // Load the MOD file. - resPlayer.loadModuleResource(songId); - // Loop the song forever. - resPlayer.setLoopCount(PlayerThread.LOOP_SONG_FOREVER); - // Turn the music on or off. - setMusicOn(musicOn); - // Start the music thread. - resPlayer.startPaused(startPaused); - resPlayer.start(); - } - - public void pausePlay() { - if (resPlayer != null) - resPlayer.pausePlay(false); - } - - public void setMusicOn(boolean musicOn) { - if (musicOn) { - resPlayer.setVolume(255); - } - else { - resPlayer.setVolume(0); - } - } - - public void unPausePlay() { - if (resPlayer != null) - resPlayer.unPausePlay(); - } -} diff --git a/src/com/efortin/frozenbubble/NetworkManager.java b/src/com/efortin/frozenbubble/NetworkManager.java deleted file mode 100644 index eecab4d..0000000 --- a/src/com/efortin/frozenbubble/NetworkManager.java +++ /dev/null @@ -1,2045 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.nio.ByteBuffer; -import java.util.ArrayList; - -import org.jfedor.frozenbubble.BubbleSprite; -import org.jfedor.frozenbubble.FrozenBubble; -import org.jfedor.frozenbubble.FrozenGame; -import org.jfedor.frozenbubble.GameView.NetGameInterface; -import org.jfedor.frozenbubble.LevelManager; - -import android.bluetooth.BluetoothAdapter; -import android.content.Context; -import android.content.SharedPreferences; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.os.AsyncTask; -import android.preference.PreferenceManager; -import android.text.format.Formatter; - -import com.efortin.frozenbubble.BluetoothManager.BluetoothListener; -import com.efortin.frozenbubble.UDPSocket.UDPListener; - -/** - * This class manages the actions in a network multiplayer game by - * sending the local actions to the remote player, and queueing the - * incoming remote player actions for enactment on the local machine. - *

The thread created by this class will not run() until - * newGame() is called. - *

Attach VirtualInput objects to this manager for each - * player in the network game. - * @author Eric Fortin - * - */ -public class NetworkManager extends Thread - implements BluetoothListener, UDPListener, NetGameInterface { - - /* - * UDP unicast and multicast connection type enumeration. - */ - public static enum connectEnum { - BLUETOOTH, - UDP_UNICAST, - UDP_MULTICAST; - } - - private static final String HOST = "225.0.0.15"; - private static final int PORT = 5500; - - private static boolean hasBluetooth = false; - - /* - * Message identifier definitions. - */ - public static final byte MSG_ID_HELLO = 0; - public static final byte MSG_ID_STATUS = 1; - public static final byte MSG_ID_PREFS = 2; - public static final byte MSG_ID_ACTION = 3; - public static final byte MSG_ID_FIELD = 4; - - /* - * Datagram size definitions. - */ - public static final int ACTION_BYTES = 37; - public static final int FIELD_BYTES = 112; - public static final int HELLO_BYTES = 6; - public static final int PREFS_BYTES = Preferences.PREFS_BYTES; - public static final int STATUS_BYTES = 14; - - /* - * Network game management definitions. - */ - private static final long ACTION_TIMEOUT = 521L; - private static final long STATUS_TIMEOUT = 503L; - private static final byte PROTOCOL_VERSION = 1; - - private boolean gameFinished; - private boolean missedAction; - private boolean newGameStarted; - private boolean paused; - private boolean running; - private long actionTxTime; - private long statusTxTime; - private connectEnum mode; - private BluetoothManager sessionBluetooth = null; - private Context myContext = null; - private GameFieldData remoteGameFieldData = null; - private InetAddress localIpAddress = null; - private InetAddress opponentAddress = null; - private PlayerAction remotePlayerAction = null; - private PlayerStatus localStatus = null; - private PlayerStatus remoteStatus = null; - private Preferences localPrefs = null; - private Preferences remotePrefs = null; - private RemoteInterface remoteInterface = null; - private String remoteIpAddress = null; - private UDPSocket session = null; - private VirtualInput localPlayer = null; - private VirtualInput remotePlayer = null; - - /* - * Keep action lists for action retransmission requests and game - * access. - */ - private ArrayList localActionList = null; - private ArrayList remoteActionList = null; - - /** - * Class constructor. - * @param myContext - the context from which to obtain the application - * context to pass to the transport layer. - * @param mode - the connection type. - * @param localPlayer - reference to the local player input object. - * @param remotePlayer - reference to the remote player input object. - * transport layer to create a socket connection. - */ - public NetworkManager(Context myContext, - connectEnum mode, - VirtualInput localPlayer, - VirtualInput remotePlayer) { - this.myContext = myContext.getApplicationContext(); - this.mode = mode; - this.localPlayer = localPlayer; - this.remotePlayer = remotePlayer; - missedAction = false; - newGameStarted = false; - localIpAddress = getLocalIPaddress(); - opponentAddress = null; - remoteIpAddress = HOST; - localPrefs = new Preferences(); - remotePrefs = new Preferences(); - localStatus = null; - remoteStatus = null; - remoteGameFieldData = new GameFieldData(null); - remotePlayerAction = new PlayerAction (null); - remoteInterface = new RemoteInterface(remotePlayerAction, - remoteGameFieldData); - session = null; - sessionBluetooth = null; - /* - * Determine if the local device has bluetooth hardware. - */ - hasBluetooth = hasBluetooth(); - /* - * Obtain a copy of the local game preferences. - */ - SharedPreferences sp = - PreferenceManager.getDefaultSharedPreferences(myContext); - localPrefs = PreferencesActivity.getDefaultPrefs(sp); - /* - * Create the player action arrays. The actions are inserted - * chronologically based on message receipt order, but are extracted - * based on consecutive action ID. - */ - localActionList = new ArrayList(); - remoteActionList = new ArrayList(); - /* - * Set the preference request flag to request the game option data - * from the remote player. If this player is player 1, then don't - * request the preference data, since player 1's preferences are - * used as the game preferences for all players. - */ - boolean requestPrefs; - if (localPlayer.playerID == VirtualInput.PLAYER1) { - requestPrefs = false; - } - else { - requestPrefs = true; - } - /* - * Initialize the local status local action ID to zero, as it is - * pre-incremented for every action transmitted to the remote - * player. - * - * Initialize the local status remote action ID to 1, as it must be - * the first action ID received from the remote player. - */ - localStatus = new PlayerStatus((byte) localPlayer.playerID, - (short) 0, (short) 1, - false, false, false, requestPrefs, - (short) 0, (short) 0); - } - - private class ReconnectTask extends AsyncTask { - @Override - protected Void doInBackground(Void... params) { - if (session != null) { - session.cleanUp(); - } - createUDPsocketSession(); - return null; - } - } - - /** - * This class represents the current state of an individual player - * game field. The game field consists of the launcher bubbles, the - * bubbles fixed to the game field, and the the attack bar. - * @author Eric Fortin - * - */ - public class GameFieldData { - public byte playerID = 0; - public short localActionID = 0; - public byte compressorSteps = 0; - public byte launchBubbleColor = -1; - public byte nextBubbleColor = -1; - public short attackBarBubbles = 0; - /* - * The game field is represented by a 2-dimensional array, with 8 - * rows and 13 columns. This is displayed on the screen as 13 rows - * with 8 columns. - */ - public byte[][] gameField = - {{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }}; - - /** - * Class constructor. - * @param action - GameFieldData object to copy to this instance. - */ - public GameFieldData(GameFieldData fieldData) { - copyFromFieldData(fieldData); - } - - /** - * Class constructor. - * @param buffer - buffer contents to copy to this instance. - */ - public GameFieldData(byte[] buffer, int startIndex) { - copyFromBuffer(buffer, startIndex); - } - - /** - * Copy the contents of the supplied field data to this field data. - * @param action - the action to copy - */ - public void copyFromFieldData(GameFieldData fieldData) { - if (fieldData != null) { - this.playerID = fieldData.playerID; - this.localActionID = fieldData.localActionID; - this.compressorSteps = fieldData.compressorSteps; - this.launchBubbleColor = fieldData.launchBubbleColor; - this.nextBubbleColor = fieldData.nextBubbleColor; - this.attackBarBubbles = fieldData.attackBarBubbles; - - for (int x = 0; x < LevelManager.NUM_COLS; x++) { - for (int y = 0; y < LevelManager.NUM_ROWS; y++) { - this.gameField[x][y] = fieldData.gameField[x][y]; - } - } - } - } - - /** - * Copy the contents of the buffer to this field data. - * @param buffer - the buffer to convert and copy - * @param startIndex - the start of the data to convert - */ - public void copyFromBuffer(byte[] buffer, int startIndex) { - byte[] shortBytes = new byte[2]; - - if (buffer != null) { - this.playerID = buffer[startIndex++]; - shortBytes[0] = buffer[startIndex++]; - shortBytes[1] = buffer[startIndex++]; - this.localActionID = toShort(shortBytes); - this.compressorSteps = buffer[startIndex++]; - this.launchBubbleColor = buffer[startIndex++]; - this.nextBubbleColor = buffer[startIndex++]; - shortBytes[0] = buffer[startIndex++]; - shortBytes[1] = buffer[startIndex++]; - this.attackBarBubbles = toShort(shortBytes); - - for (int x = 0; x < LevelManager.NUM_COLS; x++) { - for (int y = 0; y < LevelManager.NUM_ROWS; y++) { - this.gameField[x][y] = buffer[startIndex++]; - } - } - } - } - - /** - * Copy the contents of this field data to the buffer. - * @param buffer - the buffer to copy to - * @param startIndex - the start location to copy to - */ - public void copyToBuffer(byte[] buffer, int startIndex) { - byte[] shortBytes = new byte[2]; - - if (buffer != null) { - buffer[startIndex++] = this.playerID; - toByteArray(this.localActionID, shortBytes); - buffer[startIndex++] = shortBytes[0]; - buffer[startIndex++] = shortBytes[1]; - buffer[startIndex++] = this.compressorSteps; - buffer[startIndex++] = this.launchBubbleColor; - buffer[startIndex++] = this.nextBubbleColor; - toByteArray(this.attackBarBubbles, shortBytes); - buffer[startIndex++] = shortBytes[0]; - buffer[startIndex++] = shortBytes[1]; - - for (int x = 0; x < LevelManager.NUM_COLS; x++) { - for (int y = 0; y < LevelManager.NUM_ROWS; y++) { - buffer[startIndex++] = this.gameField[x][y]; - } - } - } - } - }; - - /** - * This class encapsulates variables used to identify all possible - * player actions. - * @author Eric Fortin - * - */ - public class PlayerAction { - public byte playerID; // player ID associated with this action - public short localActionID; // ID of this particular action - public short remoteActionID; // ID of expected remote player action - /* - * The following three booleans are flags associated with player - * actions. - * - * compress - - * This flag indicates whether to lower the game field compressor. - * - * launchBubble - - * This flag indicates that the player desires a bubble launch to - * occur. This flag must be set with a valid aimPosition value, - * as well as valid values for launchBubbleColor and - * nextBubbleColor. - * - * swapBubble - - * This flag indicates that the player desires that the current - * launch bubble be swapped with the next launch bubble. This - * flag must be set with a valid aimPosition value, as well as - * valid values for launchBubbleColor and nextBubbleColor. - */ - public boolean compress; - public boolean launchBubble; - public boolean swapBubble; - public byte keyCode; - public byte launchBubbleColor; - public byte nextBubbleColor; - public byte newNextBubbleColor; - public short attackBarBubbles; - public byte attackBubbles[] = { -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1 }; - public double aimPosition; - - /** - * Class constructor. - * @param action - PlayerAction object to copy to this instance. - */ - public PlayerAction(PlayerAction action) { - copyFromAction(action); - } - - /** - * Class constructor. - * @param buffer - buffer contents to copy to this instance. - */ - public PlayerAction(byte[] buffer, int startIndex) { - copyFromBuffer(buffer, startIndex); - } - - /** - * Copy the contents of the supplied action to this action. - * @param action - the action to copy. - */ - public void copyFromAction(PlayerAction action) { - if (action != null) { - this.playerID = action.playerID; - this.localActionID = action.localActionID; - this.remoteActionID = action.remoteActionID; - this.compress = action.compress; - this.launchBubble = action.launchBubble; - this.swapBubble = action.swapBubble; - this.keyCode = action.keyCode; - this.launchBubbleColor = action.launchBubbleColor; - this.nextBubbleColor = action.nextBubbleColor; - this.newNextBubbleColor = action.newNextBubbleColor; - this.attackBarBubbles = action.attackBarBubbles; - - for (int index = 0; index < 15; index++) { - this.attackBubbles[index] = action.attackBubbles[index]; - } - - this.aimPosition = action.aimPosition; - } - } - - /** - * Copy the contents of the buffer to this action. - * @param buffer - the buffer to convert and copy. - * @param startIndex - the start of the data to convert. - */ - public void copyFromBuffer(byte[] buffer, int startIndex) { - byte[] shortBytes = new byte[2]; - byte[] doubleBytes = new byte[8]; - - if (buffer != null) { - this.playerID = buffer[startIndex++]; - shortBytes[0] = buffer[startIndex++]; - shortBytes[1] = buffer[startIndex++]; - this.localActionID = toShort(shortBytes); - shortBytes[0] = buffer[startIndex++]; - shortBytes[1] = buffer[startIndex++]; - this.remoteActionID = toShort(shortBytes); - this.compress = buffer[startIndex++] == 1; - this.launchBubble = buffer[startIndex++] == 1; - this.swapBubble = buffer[startIndex++] == 1; - this.keyCode = buffer[startIndex++]; - this.launchBubbleColor = buffer[startIndex++]; - this.nextBubbleColor = buffer[startIndex++]; - this.newNextBubbleColor = buffer[startIndex++]; - shortBytes[0] = buffer[startIndex++]; - shortBytes[1] = buffer[startIndex++]; - this.attackBarBubbles = toShort(shortBytes); - - for (int index = 0; index < 15; index++) { - this.attackBubbles[index] = buffer[startIndex++]; - } - - for (int index = 0; index < 8; index++) { - doubleBytes[index] = buffer[startIndex++]; - } - - this.aimPosition = toDouble(doubleBytes); - } - } - - /** - * Copy the contents of this action to the buffer. - * @param buffer - the buffer to copy to. - * @param startIndex - the start location to copy to. - */ - public void copyToBuffer(byte[] buffer, int startIndex) { - byte[] shortBytes = new byte[2]; - byte[] doubleBytes = new byte[8]; - - if (buffer != null) { - buffer[startIndex++] = this.playerID; - toByteArray(this.localActionID, shortBytes); - buffer[startIndex++] = shortBytes[0]; - buffer[startIndex++] = shortBytes[1]; - toByteArray(this.remoteActionID, shortBytes); - buffer[startIndex++] = shortBytes[0]; - buffer[startIndex++] = shortBytes[1]; - buffer[startIndex++] = (byte) ((this.compress == true)?1:0); - buffer[startIndex++] = (byte) ((this.launchBubble == true)?1:0); - buffer[startIndex++] = (byte) ((this.swapBubble == true)?1:0); - buffer[startIndex++] = this.keyCode; - buffer[startIndex++] = this.launchBubbleColor; - buffer[startIndex++] = this.nextBubbleColor; - buffer[startIndex++] = this.newNextBubbleColor; - toByteArray(this.attackBarBubbles, shortBytes); - buffer[startIndex++] = shortBytes[0]; - buffer[startIndex++] = shortBytes[1]; - - for (int index = 0; index < 15; index++) { - buffer[startIndex++] = this.attackBubbles[index]; - } - - toByteArray(this.aimPosition, doubleBytes); - - for (int index = 0; index < 8; index++) { - buffer[startIndex++] = doubleBytes[index]; - } - } - } - }; - - /** - * This class encapsulates variables used to indicate the local game - * and player status, and is used to synchronize the exchange of - * information over the network. - *

This data is intended to be send periodically to the remote - * player(s) to keep all the players synchronized and informed of - * potential network issues with lost datagrams. This is especially - * common with multicasting, which is implemented via the User - * Datagram Protocol (UDP), which is unreliable.
- * Refer to: - * http://en.wikipedia.org/wiki/User_Datagram_Protocol - * @author Eric Fortin - * - */ - public class PlayerStatus { - /* - * The following ID is the player associated with this status. - */ - public byte playerID; - public byte protocolVersion; - /* - * The following action IDs represent the associated player's - * current game state. localActionID will refer to that player's - * last transmitted action identifer, and remoteActionID will refer - * to that player's pending action identifier (the action it is - * expecting to receive next). - * - * This is useful for noting if a player has missed player action - * datagrams from another player, because its remoteActionID will be - * less than or equal to the localActionID of the other player if it - * has not received all the action transmissions from the other - * player(s). - */ - public short localActionID; - public short remoteActionID; - /* - * The following flags are used to manage game synchronization. - */ - public boolean readyToPlay; - public boolean gameWonLost; - /* - * The following flags are used to request data from the remote - * player(s) - either their game preferences, or game field data. - * When one or either of these flags is true, then the other - * player(s) shall transmit the appropriate information. - */ - private boolean fieldRequest; - private boolean prefsRequest; - /* - * The following values are the bubble grid CRC16 values for the - * local and remote game fields. When the CRC16 value is zero, the - * CRC16 value has not been calculated (or improbably, is zero). - */ - public short localChecksum; - public short remoteChecksum; - - /** - * Class constructor. - * @param id - the player ID associated with this status - * @param localId - the local last transmitted action ID. - * @param remoteId - the remote current pending action ID. - * @param ready - player is ready to play flag. - * @param wonLost - player won or lost the game. - * @param field - request field data. - * @param prefs - request preference data. - * @param localCRC - the local player bubble grid CRC16 checksum. - * @param remoteCRC - the remote player bubble grid CRC16 checksum. - */ - public PlayerStatus(byte id, - short localId, - short remoteId, - boolean ready, - boolean wonLost, - boolean field, - boolean prefs, - short localCRC, - short remoteCRC) { - init(id, localId, remoteId, ready, wonLost, field, prefs, - localCRC, remoteCRC); - } - - /** - * Class constructor. - * @param action - PlayerAction object to copy to this instance. - */ - public PlayerStatus(PlayerStatus status) { - copyFromStatus(status); - } - - /** - * Class constructor. - * @param buffer - buffer contents to copy to this instance. - */ - public PlayerStatus(byte[] buffer, int startIndex) { - copyFromBuffer(buffer, startIndex); - } - - /** - * Copy the contents of the supplied action to this action. - * @param action - the action to copy. - */ - public void copyFromStatus(PlayerStatus status) { - if (status != null) { - this.playerID = status.playerID; - this.protocolVersion = PROTOCOL_VERSION; - this.localActionID = status.localActionID; - this.remoteActionID = status.remoteActionID; - this.readyToPlay = status.readyToPlay; - this.gameWonLost = status.gameWonLost; - this.fieldRequest = status.fieldRequest; - this.prefsRequest = status.prefsRequest; - this.localChecksum = status.localChecksum; - this.remoteChecksum = status.remoteChecksum; - } - } - - /** - * Copy the contents of the buffer to this status. - * @param buffer - the buffer to convert and copy. - * @param startIndex - the start of the data to convert. - */ - public void copyFromBuffer(byte[] buffer, int startIndex) { - byte[] shortBytes = new byte[2]; - - if (buffer != null) { - this.playerID = buffer[startIndex++]; - this.protocolVersion = buffer[startIndex++]; - shortBytes[0] = buffer[startIndex++]; - shortBytes[1] = buffer[startIndex++]; - this.localActionID = toShort(shortBytes); - shortBytes[0] = buffer[startIndex++]; - shortBytes[1] = buffer[startIndex++]; - this.remoteActionID = toShort(shortBytes); - this.readyToPlay = buffer[startIndex++] == 1; - this.gameWonLost = buffer[startIndex++] == 1; - this.fieldRequest = buffer[startIndex++] == 1; - this.prefsRequest = buffer[startIndex++] == 1; - shortBytes[0] = buffer[startIndex++]; - shortBytes[1] = buffer[startIndex++]; - this.localChecksum = toShort(shortBytes); - shortBytes[0] = buffer[startIndex++]; - shortBytes[1] = buffer[startIndex++]; - this.remoteChecksum = toShort(shortBytes); - } - } - - /** - * Copy the contents of this status to the buffer. - * @param buffer - the buffer to copy to. - * @param startIndex - the start location to copy to. - */ - public void copyToBuffer(byte[] buffer, int startIndex) { - byte[] shortBytes = new byte[2]; - - if (buffer != null) { - buffer[startIndex++] = this.playerID; - buffer[startIndex++] = this.protocolVersion; - toByteArray(this.localActionID, shortBytes); - buffer[startIndex++] = shortBytes[0]; - buffer[startIndex++] = shortBytes[1]; - toByteArray(this.remoteActionID, shortBytes); - buffer[startIndex++] = shortBytes[0]; - buffer[startIndex++] = shortBytes[1]; - buffer[startIndex++] = (byte) ((this.readyToPlay == true)?1:0); - buffer[startIndex++] = (byte) ((this.gameWonLost == true)?1:0); - buffer[startIndex++] = (byte) ((this.fieldRequest == true)?1:0); - buffer[startIndex++] = (byte) ((this.prefsRequest == true)?1:0); - toByteArray(this.localChecksum, shortBytes); - buffer[startIndex++] = shortBytes[0]; - buffer[startIndex++] = shortBytes[1]; - toByteArray(this.remoteChecksum, shortBytes); - buffer[startIndex++] = shortBytes[0]; - buffer[startIndex++] = shortBytes[1]; - } - } - - /** - * Initialize this object with the provided data. - * @param id - the player ID associated with this status - * @param localId - the local last transmitted action ID. - * @param remoteId - the remote current pending action ID. - * @param ready - player is ready to play. - * @param wonLost - player won or lost the game. - * @param field - request field data - * @param prefs - request preference data - * @param localCRC - the local player bubble grid CRC16 checksum. - * @param remoteCRC - the remote player bubble grid CRC16 checksum. - */ - public void init(byte id, - short localId, - short remoteId, - boolean ready, - boolean wonLost, - boolean field, - boolean prefs, - short localCRC, - short remoteCRC) { - this.playerID = id; - this.protocolVersion = PROTOCOL_VERSION; - this.localActionID = localId; - this.remoteActionID = remoteId; - this.readyToPlay = ready; - this.gameWonLost = wonLost; - this.fieldRequest = field; - this.prefsRequest = prefs; - this.localChecksum = localCRC; - this.remoteChecksum = remoteCRC; - } - }; - - private boolean actionTimerExpired() { - return System.currentTimeMillis() >= actionTxTime; - } - - /** - * Add a player action to the appropriate action list. Do not allow - * duplicate actions to populate the lists. - * @param newAction - the action to add to the appropriate list. - */ - private void addAction(PlayerAction newAction) { - if ((localPlayer != null) && (remotePlayer != null)) { - /* - * If an action is a local player action, add it to the action - * list if it is not already in the list. - * - * If it is a remote player action, add it to the action list if - * it is not already in the list. - */ - if (newAction.playerID == localPlayer.playerID) { - synchronized(localActionList) { - int listSize = localActionList.size(); - - for (int index = 0; index < listSize; index++) { - /* - * If a match is found, return from this function without - * adding the action to the list since it is a duplicate. - */ - if (localActionList.get(index).localActionID == - newAction.localActionID) { - return; - } - } - localActionList.add(newAction); - } - } - else if (newAction.playerID == remotePlayer.playerID) { - synchronized(remoteActionList) { - int listSize = remoteActionList.size(); - /* - * Update the remote player remote action ID to the ID of this - * action if it is exactly 1 greater than the local player - * local action ID. This signifies that the remote player has - * received all the local player action messages, since they - * are expecting an action datagram that has not yet been sent - * by the local player because it hasn't occurred. - */ - if (newAction.remoteActionID == - localStatus.localActionID + 1) { - remoteStatus.remoteActionID = newAction.remoteActionID; - } - - for (int index = 0; index < listSize; index++) { - /* - * If a match is found, return from this function without - * adding the action to the list since it is a duplicate. - */ - if (remoteActionList.get(index).localActionID == - newAction.localActionID) { - return; - } - } - /* - * Clear the list when the first action is received to remove - * spurious entries. - */ - if (newAction.localActionID == 1) { - remoteActionList.clear(); - } - remoteActionList.add(newAction); - } - } - } - } - - public void checkRemoteChecksum() { - if ((localStatus != null) && (remoteStatus != null)) { - if ((localStatus.remoteActionID == (remoteStatus.localActionID + 1)) && - (localStatus.remoteChecksum != 0) && - (remoteStatus.localChecksum != 0) && - (localStatus.remoteChecksum != remoteStatus.localChecksum)) { - localStatus.fieldRequest = true; - } - } - } - - /** - * Check the local action list for actions that have been received - * by the remote player. When this is the case, the local action - * list entries will have action IDs lower than the remote player - * remote action ID. - *

Each call of this function will remove one entry. - * @return true if an entry was removed. - */ - private boolean cleanLocalActionList() { - boolean removed = false; - synchronized(localActionList) { - int listSize = localActionList.size(); - - for (int index = 0; index < listSize; index++) { - /* - * If the local action ID in the list is less than the remote - * player remote action ID, remove it from the list. Only one - * entry is removed per function call. - */ - if (localActionList.get(index).localActionID < - remoteStatus.remoteActionID) { - localActionList.remove(index); - removed = true; - break; - } - } - } - return removed; - } - - public void cleanUp() { - stopThread(); - - if (session != null) { - session.cleanUp(); - } - session = null; - - if (sessionBluetooth != null) { - sessionBluetooth.cleanUp(); - } - sessionBluetooth = null; - - /* - * Restore the local game preferences in the event that they were - * overwritten by the remote player's preferences. - */ - if (localPrefs != null) { - FrozenBubble.setPrefs(localPrefs); - } - - localPrefs = null; - remotePrefs = null; - localPlayer = null; - remotePlayer = null; - remoteGameFieldData = null; - remotePlayerAction = null; - - if (remoteInterface != null) - remoteInterface.cleanUp(); - remoteInterface = null; - - if (localActionList != null) - localActionList.clear(); - localActionList = null; - - if (remoteActionList != null) - remoteActionList.clear(); - remoteActionList = null; - } - - private void createUDPsocketSession() { - try { - session = new UDPSocket(myContext, mode, remoteIpAddress, PORT); - } catch (UnknownHostException uhe) { - uhe.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - if (session != null) { - session.setUDPListener(this); - session.setLocalIPaddress(getLocalIPaddress()); - } - } - - /** - * Copy the contents of the buffer to the designated preferences. - * @param buffer - the buffer to convert and copy. - * @param startIndex - the start of the data to convert. - */ - private void copyPrefsFromBuffer(Preferences prefs, - byte[] buffer, - int startIndex) { - byte[] intBytes = new byte[4]; - - if (buffer != null) { - intBytes[0] = buffer[startIndex++]; - intBytes[1] = buffer[startIndex++]; - intBytes[2] = buffer[startIndex++]; - intBytes[3] = buffer[startIndex++]; - prefs.collision = toInt(intBytes); - prefs.compressor = buffer[startIndex++] == 1; - intBytes[0] = buffer[startIndex++]; - intBytes[1] = buffer[startIndex++]; - intBytes[2] = buffer[startIndex++]; - intBytes[3] = buffer[startIndex++]; - prefs.difficulty = toInt(intBytes); - prefs.dontRushMe = buffer[startIndex++] == 1; - prefs.fullscreen = buffer[startIndex++] == 1; - intBytes[0] = buffer[startIndex++]; - intBytes[1] = buffer[startIndex++]; - intBytes[2] = buffer[startIndex++]; - intBytes[3] = buffer[startIndex++]; - prefs.gameMode = toInt(intBytes); - prefs.musicOn = buffer[startIndex++] == 1; - prefs.soundOn = buffer[startIndex++] == 1; - intBytes[0] = buffer[startIndex++]; - intBytes[1] = buffer[startIndex++]; - intBytes[2] = buffer[startIndex++]; - intBytes[3] = buffer[startIndex++]; - prefs.targetMode = toInt(intBytes); - } - } - - /** - * Copy the contents of this preferences object to the buffer. - * @param buffer - the buffer to copy to. - * @param startIndex - the start location to copy to. - */ - private void copyPrefsToBuffer(Preferences prefs, - byte[] buffer, - int startIndex) { - byte[] intBytes = new byte[4]; - - if (buffer != null) { - toByteArray(prefs.collision, intBytes); - buffer[startIndex++] = intBytes[0]; - buffer[startIndex++] = intBytes[1]; - buffer[startIndex++] = intBytes[2]; - buffer[startIndex++] = intBytes[3]; - buffer[startIndex++] = (byte) ((prefs.compressor == true)?1:0); - toByteArray(prefs.difficulty, intBytes); - buffer[startIndex++] = intBytes[0]; - buffer[startIndex++] = intBytes[1]; - buffer[startIndex++] = intBytes[2]; - buffer[startIndex++] = intBytes[3]; - buffer[startIndex++] = (byte) ((prefs.dontRushMe == true)?1:0); - buffer[startIndex++] = (byte) ((prefs.fullscreen == true)?1:0); - toByteArray(prefs.gameMode, intBytes); - buffer[startIndex++] = intBytes[0]; - buffer[startIndex++] = intBytes[1]; - buffer[startIndex++] = intBytes[2]; - buffer[startIndex++] = intBytes[3]; - buffer[startIndex++] = (byte) ((prefs.musicOn == true)?1:0); - buffer[startIndex++] = (byte) ((prefs.soundOn == true)?1:0); - toByteArray(prefs.targetMode, intBytes); - buffer[startIndex++] = intBytes[0]; - buffer[startIndex++] = intBytes[1]; - buffer[startIndex++] = intBytes[2]; - buffer[startIndex++] = intBytes[3]; - } - } - - /** - * Check if the network game is finished. The game is finished when - * both players have either won or lost the game. - */ - public boolean getGameIsFinished() { - if (remoteStatus == null) { - gameFinished = false; - } - else if (!gameFinished) { - gameFinished = localStatus .gameWonLost && - remoteStatus.gameWonLost; - } - return gameFinished; - } - - /** - * Check if the network game is ready for action. The game is ready - * to begin play when all data synchronization tasks are completed, at - * which point every respective player's readyToPlay flag will be set. - * @return true if game synchronization is complete. - */ - public boolean gameIsReadyForAction() { - if (remoteStatus == null) - return false; - else - return localStatus.readyToPlay && remoteStatus.readyToPlay; - } - - private void getGameFieldData(GameFieldData gameData) { - FrozenGame gameRef = localPlayer.mGameRef; - - gameData.playerID = (byte) localPlayer.playerID; - gameData.localActionID = localStatus.localActionID; - gameData.compressorSteps = (byte) gameRef.getCompressorSteps(); - gameData.launchBubbleColor = (byte) gameRef.getCurrentColor(); - gameData.nextBubbleColor = (byte) gameRef.getNextColor(); - gameData.attackBarBubbles = (short) gameRef.getAttackBarBubbles(); - - BubbleSprite[][] bubbleGrid = gameRef.getGrid(); - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < LevelManager.NUM_ROWS; j++) { - if (bubbleGrid[i][j] != null) { - gameData.gameField[i][j] = (byte) bubbleGrid[i][j].getColor(); - } - else { - gameData.gameField[i][j] = -1; - } - } - } - } - - public short getLatestRemoteActionId() { - if (remoteStatus != null) { - return remoteStatus.localActionID; - } - else { - return -1; - } - } - - /** - * Obtain the local IP address from the WiFiManager. - *

The following uses permission must be addeded to - * the Android project manifest to obtain the network connection - * status:
- * ACCESS_WIFI_STATE - * @return the local WiFi IP address. - * @see WifiManager - */ - public InetAddress getLocalIPaddress() { - WifiManager wifiManager = - (WifiManager) myContext.getSystemService(Context.WIFI_SERVICE); - WifiInfo wifiInfo = wifiManager.getConnectionInfo(); - InetAddress address = null; - try { - address = - InetAddress.getByName(Formatter.formatIpAddress(wifiInfo.getIpAddress())); - } catch (UnknownHostException e) { - /* - * Auto-generated catch block. - */ - e.printStackTrace(); - } - return address; - } - - /** - * Peek into the remote action list to see if we have obtained the - * current expected remote action. - * @return The reference to the current remote action if it exists, - * and null if we haven't received it yet. - */ - public PlayerAction getRemoteActionPreview() { - PlayerAction tempAction = null; - - synchronized(remoteActionList) { - int listSize = remoteActionList.size(); - - for (int index = 0; index < listSize; index++) { - /* - * When a match is found, return a reference to it. - */ - if (remoteActionList.get(index).localActionID == - localStatus.remoteActionID) { - tempAction = new PlayerAction(remoteActionList.get(index)); - break; - } - } - } - - return tempAction; - } - - /** - * This function obtains the expected remote player action (based on - * action ID) and places it into the remote player interface. - *

This function must be called periodically as it is assumed - * that the actions will be performed at the most appropriate time as - * determined by caller. - * @return true if the appropriate remote player action - * was retrieved from the remote action list. - */ - public boolean getRemoteAction() { - remoteInterface.gotAction = false; - synchronized(remoteActionList) { - int listSize = remoteActionList.size(); - - for (int index = 0; index < listSize; index++) { - /* - * When a match is found, copy the necessary element from the - * list, remove it, and exit the loop. - */ - if (remoteActionList.get(index).localActionID == - localStatus.remoteActionID) { - remoteInterface.playerAction.copyFromAction(remoteActionList.get(index)); - try { - remoteActionList.remove(index); - } catch (IndexOutOfBoundsException ioobe) { - ioobe.printStackTrace(); - } - remoteInterface.gotAction = true; - localStatus.remoteActionID++; - /* - * The local player status was updated. Set the status - * timeout to expire immediately and wake up the network - * manager thread. - */ - setStatusTimeout(0L); - synchronized(this) { - notify(); - } - break; - } - } - } - - return remoteInterface.gotAction; - } - - /** - * This function obtains the remote player interface and returns a - * reference to it to the caller. - * @return A reference to the remote player network game interface - * which provides all necessary remote player data. - */ - public RemoteInterface getRemoteInterface() { - return remoteInterface; - } - - /** - * Check if Bluetooth is available and enabled on this device. - *

The following uses permission must be added to the - * Android project manifest to obtain Bluetooth network status:
- * BLUETOOTH - * @return true if Bluetooth is enabled. - */ - public static boolean hasBluetooth() - { - BluetoothAdapter myAdapter = BluetoothAdapter.getDefaultAdapter(); - if (myAdapter != null) { - if (!myAdapter.isEnabled()) { - myAdapter.enable(); - } - return true; - } - return false; - } - - /** - * Check with the ConnectivityManager if the device is - * connected to the internet. - *

The following uses permission must be addeded to - * the Android project manifest to obtain the network connection - * status:
- * ACCESS_NETWORK_STATE - * @return true if the device is connected to the - * internet. - * @see ConnectivityManager - */ - public boolean hasInternetConnection() - { - ConnectivityManager cm = - (ConnectivityManager) myContext.getSystemService(Context. - CONNECTIVITY_SERVICE); - NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); - if ((activeNetwork != null) && activeNetwork.isConnected()) - { - return true; - } - return false; - } - - /** - * This function is called from manager thread's run() - * method. This performs the network handshaking amongst peers to - * ensure proper game synchronization and operation. - */ - private void manageNetworkGame() { - if (localStatus == null) { - return; - } - - if (remoteStatus != null) { - /* - * On a new game, wait for the remote player to start a new game - * before requesting field data from the remote player. - */ - if (!remoteInterface.gotFieldData && - !localStatus.fieldRequest && - !remoteStatus.readyToPlay) { - localStatus.fieldRequest = true; - } - /* - * If the last action transmitted by the local player has not yet - * been received by the remote player, the remote player remote - * action ID will match or be less than the local player local - * action ID. If this is the case, transmit the action ID - * expected by the remote player. - */ - if (localStatus.localActionID >= remoteStatus.remoteActionID) { - if (!missedAction) { - missedAction = true; - setActionTimeout(ACTION_TIMEOUT); - } - else if (actionTimerExpired()) { - sendLocalPlayerAction(remoteStatus.remoteActionID); - setActionTimeout(ACTION_TIMEOUT); - } - } - else { - missedAction = false; - } - - cleanLocalActionList(); - } - - /* - * Check whether various datagrams require transmission, such as - * player status, game field data, or preferences. - */ - if (statusTimerExpired()) { - /* - * The UDP socket connection mode is set to multicast until an - * opponent has been identified. Until then, transmit the network - * peer discovery message. - */ - if (mode != connectEnum.BLUETOOTH) { - if ((mode == connectEnum.UDP_MULTICAST) || - (remoteStatus == null)) { - transmitHello(); - } - } - - if (remoteStatus != null) { - if (remoteStatus.prefsRequest) { - transmitPrefs(); - /* - * Clear the remote request flag to potentially reduce network - * overhead. If the remote player does not receive the data, - * the next remote status message will set the flag again. - */ - remoteStatus.prefsRequest = false; - } - - /* - * Only transmit the local game field if the local player local - * action ID is one less than the remote player remote action - * ID. This signifies that the distributed game is synchronized - * with respect to the local player. Actions must be executed - * synchronously with respect to the corresponding game field in - * order for performance to be identical on each distributed - * device. - */ - if (remoteStatus.fieldRequest && - ((localStatus.localActionID + 1) == remoteStatus.remoteActionID)) { - GameFieldData tempField = new GameFieldData(null); - getGameFieldData (tempField); - transmitGameField(tempField); - /* - * Clear the remote request flag to potentially reduce network - * overhead. If the remote player does not receive the data, - * the next remote status message will set the flag again. - */ - remoteStatus.fieldRequest = false; - } - } - - transmitStatus (localStatus ); - setStatusTimeout(STATUS_TIMEOUT); - } - } - - public void newGame() { - gameFinished = false; - remoteInterface.gotFieldData = false; - if (localStatus != null) { - localStatus.readyToPlay = false; - localStatus.localActionID = 0; - localStatus.remoteActionID = 1; - localStatus.localChecksum = 0; - localStatus.remoteChecksum = 0; - } - if (localActionList != null) { - synchronized(localActionList) { - localActionList.clear(); - } - } - if (remoteActionList != null) { - synchronized(remoteActionList) { - remoteActionList.clear(); - } - } - /* - * Initialize the various timers. - */ - setActionTimeout(0L); - setStatusTimeout(0L); - - /* - * If a UDP session has not yet been created, create a new one and - * start the NetworkGameManager thread. - */ - if (((mode == connectEnum.UDP_MULTICAST) || - (mode == connectEnum.UDP_UNICAST )) && - (session == null)) { - createUDPsocketSession(); - - /* - * Start the network manager thread. - */ - try { - start(); - } catch (IllegalThreadStateException itse) { - /* - * The thread was already started. - */ - itse.printStackTrace(); - } - } - else if ((mode == connectEnum.BLUETOOTH) && (sessionBluetooth == null)) { - sessionBluetooth = new BluetoothManager(localPlayer.playerID == - VirtualInput.PLAYER1, - FrozenBubble.getBluetooth()); - sessionBluetooth.setBluetoothListener(this); - - /* - * Start the network manager thread. - */ - try { - start(); - } catch (IllegalThreadStateException itse) { - /* - * The thread was already started. - */ - itse.printStackTrace(); - } - } - else { - /* - * Wake up the thread. - */ - synchronized(this) { - notify(); - } - } - newGameStarted = true; - } - - public boolean newGameStarted() { - boolean gameWasStarted = newGameStarted; - newGameStarted = false; - return gameWasStarted; - } - - @Override - public void onBluetoothEvent(byte[] buffer, int length) { - /* - * Process the Bluetooth message if it possesses a payload. - */ - if ((buffer != null) && (buffer.length > 2)) { - /* - * The first two bytes of every message must contain the same - * two fields - the message ID, and the player ID. - * - * The message ID is prefixed prior to each datagram transmission, - * as it is used by the network layer and is of no significance to - * any other module. The player ID must be the first byte of - * every datagram class implemented by the Cold Cash network game - * protocol. The exception to this is the peer discovery message. - * - * The message ID is used to identify the message type - either a - * player status datagram, game field datagram, player preferences - * datagram, or a player action datagram. - * - * The player ID is used to identify who originated the message. - * This must be unique amongst all the players in the same game. - */ - byte playerId = buffer[1]; - - if (playerId == remotePlayer.playerID) { - processEventData(buffer, length); - } - } - } - - @Override - public void onUDPEvent(InetAddress address, byte[] buffer, int length) { - /* - * Process the UDP message if it is a successfully received - * datagram that possesses a payload. - */ - if ((buffer != null) && (buffer.length > 2)) { - /* - * The first two bytes of every message must contain the same - * two fields - the message ID, and the player ID. - * - * The message ID is prefixed prior to each datagram transmission, - * as it is used by the network layer and is of no significance to - * any other module. The player ID must be the first byte of - * every datagram class implemented by the Cold Cash network game - * protocol. The exception to this is the peer discovery message. - * - * The message ID is used to identify the message type - either a - * player status datagram, game field datagram, player preferences - * datagram, or a player action datagram. - * - * The player ID is used to identify who originated the message. - * This must be unique amongst all the players in the same game. - */ - byte msgId = buffer[0]; - byte playerId = buffer[1]; - - if ((mode == connectEnum.UDP_MULTICAST) && - (playerId == remotePlayer.playerID) && - (msgId == MSG_ID_HELLO) && (length >= HELLO_BYTES)) { - opponentAddress = address; - /* - * If the payload of the message is the IP address of this local - * host, then the remote host has designated this host as the - * other player for the network game. The remote host IP - * address becomes the payload for our own network game - * discovery message. - */ - byte[] addressData = new byte[4]; - for (int index = 0; index < 4; index++) { - addressData[index] = buffer[index + 2]; - } - InetAddress tempAddress = null; - try { - tempAddress = InetAddress.getByAddress(addressData); - } catch (UnknownHostException e) { - /* - * Auto-generated catch block. - */ - e.printStackTrace(); - } - if ((tempAddress != null) && localIpAddress.equals(tempAddress)) { - /* - * Reconnect the UDP socket session in unicast mode using - * the provided opponent IP address. - */ - mode = connectEnum.UDP_UNICAST; - remoteIpAddress = opponentAddress.getHostAddress(); - new ReconnectTask().execute(); - } - return; - } - - if (mode == connectEnum.UDP_UNICAST) { - if ((opponentAddress != null) && (playerId == remotePlayer.playerID) && - opponentAddress.equals(address)) { - processEventData(buffer, length); - } - } - } - } - - public void pause() { - if (running) { - if (session != null) { - session.pause(); - } - if (sessionBluetooth != null) { - sessionBluetooth.pause(); - } - paused = true; - } - } - - private void processEventData(byte[] buffer, int length) { - byte msgId = buffer[0]; - byte playerId = buffer[1]; - - /* - * If the message contains the remote player status, copy it to - * the remote player status object. The remote player status - * object will be null until the first remote status datagram is - * received. - * - * If the game ID has not yet been set, then player status - * messages are the only messages that will be processed. - */ - if ((msgId == MSG_ID_STATUS) && (length >= (STATUS_BYTES + 1))) { - /* - * Process the remote player status. - */ - if (remoteStatus == null) { - remoteStatus = new PlayerStatus(buffer, 1); - } - else { - remoteStatus.copyFromBuffer(buffer, 1); - } - } - - /* - * If the message contains game preferences from player 1, then - * update the game preferences. The game preferences for all - * players are set per player 1. - */ - if ((msgId == MSG_ID_PREFS) && (length >= (PREFS_BYTES + 2))) { - if ((playerId == VirtualInput.PLAYER1) && localStatus.prefsRequest) { - copyPrefsFromBuffer(remotePrefs, buffer, 2); - /* - * In a network game, do not override any of the local game - * options that can be configuring during game play. Only - * set the bubble collision sensitivity and the compressor - * on/off option as specified by player 1, as these options - * are inaccessible during game play, and are absolutely - * necessary for distributed game behavior synchronization. - * All the other options are purely cosmetic, or may cause - * confusion if they are changed without notification. - */ - FrozenBubble.setCollision (remotePrefs.collision ); - FrozenBubble.setCompressor(remotePrefs.compressor); - /* - * If all new game data synchronization requests have been - * fulfilled, then the network game is ready to begin. - */ - remoteInterface.gotPrefsData = true; - localStatus .prefsRequest = false; - if (remoteInterface.gotFieldData && - !localStatus.fieldRequest && - !localStatus.readyToPlay) { - localStatus.readyToPlay = true; - localStatus.gameWonLost = false; - } - /* - * The local player status was updated. Set the status - * timeout to expire immediately and wake up the network - * manager thread. - */ - setStatusTimeout(0L); - synchronized(this) { - notify(); - } - } - } - - /* - * If the message contains a remote player game action, add it - * to the remote player action list if we are ready to play. - */ - if ((msgId == MSG_ID_ACTION) && (length >= (ACTION_BYTES + 1))) { - if (localStatus.readyToPlay && (playerId == remotePlayer.playerID)) { - addAction(new PlayerAction(buffer, 1)); - } - } - - /* - * If the message contains the remote player game field, update - * the remote player interface game field object. - */ - if ((msgId == MSG_ID_FIELD) && (length >= (FIELD_BYTES + 1))) { - if ((playerId == remotePlayer.playerID) && - localStatus.fieldRequest) { - remoteInterface.gameFieldData.copyFromBuffer(buffer, 1); - remoteInterface.gotFieldData = true; - localStatus .fieldRequest = false; - /* - * If all new game data synchronization requests have been - * fulfilled, then the network game is ready to begin. - */ - if (!localStatus.prefsRequest && !localStatus.readyToPlay) { - localStatus.readyToPlay = true; - localStatus.gameWonLost = false; - } - /* - * The local player status was updated. Set the status - * timeout to expire immediately and wake up the network - * manager thread. - */ - setStatusTimeout(0L); - synchronized(this) { - notify(); - } - } - } - } - - /** - * This is the network game manager thread's run() call. - */ - @Override - public void run() { - paused = false; - running = true; - - while (running) - { - if (paused) try { - synchronized(this) { - wait(); - } - } catch (InterruptedException ie) { - /* - * Interrupted. This is expected behavior. - */ - } - - if (!paused && running) try { - synchronized(this) { - wait(100); - } - } catch (InterruptedException ie) { - /* - * Timed out. This is expected behavior. - */ - } - - if (!paused && running) { - manageNetworkGame(); - } - } - } - - /** - * Send the specified local player action from the local action list. - * @param actionId - the ID of the action to transmit. - */ - private void sendLocalPlayerAction(short actionId) { - synchronized(localActionList) { - int listSize = localActionList.size(); - - for (int index = 0; index < listSize; index++) { - /* - * If a match is found, transmit the action. - */ - if (localActionList.get(index).localActionID == actionId) { - transmitAction(localActionList.get(index)); - } - } - } - } - - /** - * Transmit the local player action to the remote player. The action - * counter identifier is incremented automatically. - * @param playerId - the local player ID. - * @param compress - set true to lower the compressor. - * @param launch - set true to launch a bubble. - * @param swap - set true to swap the launch bubble with - * the next bubble. - * @param keyCode - set to the key code value of the player key press. - * @param launchColor - the launch bubble color. - * @param nextColor - the next bubble color. - * @param newNextColor - when a bubble is launched, this is the new - * next bubble color. The prior next color is promoted to the - * launch bubble color. - * @param attackBarBubbles - the number of attack bubbles stored on - * the attack bar. If there are attack bubbles being launched, this - * should be the value prior to launch. - * @param attackBubbles - the array of attack bubble colors. A value - * of -1 denotes no color, and thus no attack bubble at that column. - * @param aimPosition - the launcher aim position. - */ - public void sendLocalPlayerAction(int playerId, - boolean compress, - boolean launch, - boolean swap, - int keyCode, - int launchColor, - int nextColor, - int newNextColor, - int attackBarBubbles, - byte attackBubbles[], - double aimPosition) { - PlayerAction tempAction = new PlayerAction(null); - tempAction.playerID = (byte) playerId; - tempAction.localActionID = ++localStatus.localActionID; - tempAction.remoteActionID = localStatus.remoteActionID; - tempAction.compress = compress; - tempAction.launchBubble = launch; - tempAction.swapBubble = swap; - tempAction.keyCode = (byte) keyCode; - tempAction.launchBubbleColor = (byte) launchColor; - tempAction.nextBubbleColor = (byte) nextColor; - tempAction.newNextBubbleColor = (byte) newNextColor; - tempAction.attackBarBubbles = (short) attackBarBubbles; - if (attackBubbles != null) - for (int index = 0;index < 15; index++) - tempAction.attackBubbles[index] = attackBubbles[index]; - tempAction.aimPosition = aimPosition; - addAction(tempAction); - transmitAction(tempAction); - /* - * The most current action IDs are being transmitted with this - * action. Postpone the player status message as it will be mostly - * redundant with the information in this message, albeit the - * delayed game field checksums may potentially lead to a more - * significant game synchronization discrepancy if one is currently - * present. - */ - setStatusTimeout(STATUS_TIMEOUT); - } - - /** - * Set the action message timeout. - * @param timeout - the timeout expiration interval. - */ - public void setActionTimeout(long timeout) { - actionTxTime = System.currentTimeMillis() + timeout; - } - - /** - * Set the flag to indicate that the local player won or lost the - * network game. Only set it once, otherwise calling this function - * multiple times in succession would flood the network with player - * status messages due to how an immediate local player status message - * transmission is initiated whenever the player status changes. - */ - public void setGameIsFinished() { - if (!localStatus.gameWonLost) { - localStatus.gameWonLost = true; - /* - * The local player status was updated. Set the status timeout to - * expire immediately and wake up the network manager thread. - */ - setStatusTimeout(0L); - synchronized(this) { - notify(); - } - } - } - - /** - * Set the local player local game field checksum. The checksum is - * set to zero immediately after every local player action, and must - * be set as soon as the game field has become static and a new - * checksum has been calculated. - * @param checksum - the new game field checksum. - */ - public void setLocalChecksum(short checksum) { - localStatus.localChecksum = checksum; - } - - /** - * Set the local player remote game field checksum. The checksum is - * set to zero immediately after every remote player action, and must - * be set as soon as the game field has become static and a new - * checksum has been calculated. - * @param checksum - the new game field checksum. - */ - public void setRemoteChecksum(short checksum) { - localStatus.remoteChecksum = checksum; - } - - /** - * Set the status message timeout. - * @param timeout - the timeout expiration interval. - */ - public void setStatusTimeout(long timeout) { - statusTxTime = System.currentTimeMillis() + timeout; - } - - private boolean statusTimerExpired() { - return System.currentTimeMillis() >= statusTxTime; - } - - /** - * Stop and join() the network game manager thread. - */ - private void stopThread() { - paused = false; - running = false; - synchronized(this) { - interrupt(); - } - /* - * Close and join() the multicast thread. - */ - boolean retry = true; - while (retry) { - try { - join(); - retry = false; - } catch (InterruptedException e) { - /* - * Keep trying to close the multicast thread. - */ - } - } - } - - /** - * Populate a byte array with the byte representation of a short. - * The byte array must consist of at least 2 bytes. - * @param value - the short to convert to a byte array. - * @param array - the byte array where the converted short is placed. - */ - public static void toByteArray(short value, byte[] array) { - ByteBuffer.wrap(array).putShort(value); - } - - /** - * Populate a byte array with the byte representation of an integer. - * The byte array must consist of at least 4 bytes. - * @param value - the integer to convert to a byte array. - * @param array - the byte array where the converted int is placed. - */ - public static void toByteArray(int value, byte[] array) { - ByteBuffer.wrap(array).putInt(value); - } - - /** - * Populate a byte array with the byte representation of a double. - * The byte array must consist of at least 8 bytes. - * @param value - the double to convert to a byte array. - * @param array - the byte array where the converted double is placed. - */ - public static void toByteArray(double value, byte[] array) { - ByteBuffer.wrap(array).putDouble(value); - } - - /** - * Convert a byte array into a double value. - * @param bytes - the byte array to convert into a double. - * @return The double representation of the supplied byte array. - */ - public static double toDouble(byte[] bytes) { - return ByteBuffer.wrap(bytes).getDouble(); - } - - /** - * Convert a byte array into an integer value. - * @param bytes - the byte array to convert into an integer. - * @return The double representation of the supplied byte array. - */ - public static int toInt(byte[] bytes) { - return ByteBuffer.wrap(bytes).getInt(); - } - - /** - * Convert a byte array into a short value. - * @param bytes - the byte array to convert into a short. - * @return The short representation of the supplied byte array. - */ - public static short toShort(byte[] bytes) { - return ByteBuffer.wrap(bytes).getShort(); - } - - /** - * Transmit the local player action to the remote player via the - * network interface. - * @param action - the player action to transmit. - * @return true if the transmission was successful. - */ - private boolean transmitAction(PlayerAction action) { - byte[] buffer = new byte[ACTION_BYTES + 1]; - buffer[0] = MSG_ID_ACTION; - action.copyToBuffer(buffer, 1); - /* - * Send the datagram via UDP socket. - */ - if (session != null) { - return session.transmit(buffer); - } - else if (sessionBluetooth != null) { - return sessionBluetooth.transmit(buffer); - } - else { - return false; - } - } - - /** - * Transmit the local player game field to the remote player via the - * network interface. - * @param gameField - the player game field data to transmit. - * @return true if the transmission was successful. - */ - private boolean transmitGameField(GameFieldData gameField) { - byte[] buffer = new byte[FIELD_BYTES + 1]; - buffer[0] = MSG_ID_FIELD; - gameField.copyToBuffer(buffer, 1); - /* - * Send the datagram via UDP socket. - */ - if (session != null) { - return session.transmit(buffer); - } - else if (sessionBluetooth != null) { - return sessionBluetooth.transmit(buffer); - } - else { - return false; - } - } - - /** - * Transmit the hello datagram. - * @param helloData - the hello datagram contents to transmit. - * @return true if the transmission was successful. - */ - private boolean transmitHello() { - byte[] buffer = new byte[HELLO_BYTES]; - buffer[0] = MSG_ID_HELLO; - buffer[1] = (byte) localPlayer.playerID; - if (opponentAddress != null) { - byte[] address = opponentAddress.getAddress(); - for (int index = 0; index < 4; index++) { - buffer[index + 2] = address[index]; - } - } - /* - * Send the datagram via UDP socket. - */ - if (session != null) { - return session.transmit(buffer); - } - else if (sessionBluetooth != null) { - return sessionBluetooth.transmit(buffer); - } - else { - return false; - } - } - - /** - * Transmit the player status message. - * @return true if the transmission was successful. - */ - private boolean transmitStatus(PlayerStatus status) { - byte[] buffer = new byte[STATUS_BYTES + 1]; - buffer[0] = MSG_ID_STATUS; - status.copyToBuffer(buffer, 1); - /* - * Send the datagram via the UDP socket. - */ - if (session != null) { - return session.transmit(buffer); - } - else if (sessionBluetooth != null) { - return sessionBluetooth.transmit(buffer); - } - else { - return false; - } - } - - /** - * Transmit the local player preferences to the remote player via the - * network interface. - * @return true if the transmission was successful. - */ - private boolean transmitPrefs() { - byte[] buffer = new byte[Preferences.PREFS_BYTES + 2]; - buffer[0] = MSG_ID_PREFS; - buffer[1] = (byte) localPlayer.playerID; - copyPrefsToBuffer(localPrefs, buffer, 2); - /* - * Send the datagram via UDP socket. - */ - if (session != null) { - return session.transmit(buffer); - } - else if (sessionBluetooth != null) { - return sessionBluetooth.transmit(buffer); - } - else { - return false; - } - } - - public void unPause() { - paused = false; - synchronized(this) { - interrupt(); - } - if (session != null) { - session.unPause(); - } - if (sessionBluetooth != null) { - sessionBluetooth.unPause(); - } - } - - public void updateNetworkStatus(NetworkStatus status) { - if (localIpAddress == null) { - localIpAddress = getLocalIPaddress(); - if (session != null) { - session.setLocalIPaddress(localIpAddress); - } - } - status.localPlayerId = localPlayer .playerID; - status.remotePlayerId = remotePlayer.playerID; - if ((mode == connectEnum.UDP_MULTICAST) || (mode == connectEnum.UDP_UNICAST)) { - status.isConnected = hasInternetConnection(); - status.localIpAddress = localIpAddress.getHostAddress(); - status.remoteIpAddress = remoteIpAddress; - status.playerJoined = opponentAddress != null; - } - else if (mode == connectEnum.BLUETOOTH) { - status.isConnected = hasBluetooth; - status.localIpAddress = sessionBluetooth.getLocalName ().toLowerCase(); - status.remoteIpAddress = sessionBluetooth.getRemoteName ().toLowerCase(); - status.playerJoined = sessionBluetooth.getIsConnected(); - } - if (localStatus != null) { - status.gotFieldData = remoteInterface.gotFieldData; - status.gotPrefsData = remoteInterface.gotPrefsData; - } - else { - status.gotFieldData = false; - status.gotPrefsData = false; - } - status.readyToPlay = gameIsReadyForAction(); - } -}; diff --git a/src/com/efortin/frozenbubble/Preferences.java b/src/com/efortin/frozenbubble/Preferences.java deleted file mode 100644 index c49cbbd..0000000 --- a/src/com/efortin/frozenbubble/Preferences.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import org.jfedor.frozenbubble.BubbleSprite; -import org.jfedor.frozenbubble.FrozenBubble; -import org.jfedor.frozenbubble.LevelManager; - -public class Preferences { - public static final int PREFS_BYTES = 22; - - public int bluetooth; - public int collision; - public boolean colorMode; - public boolean compressor; - public int difficulty; - public boolean dontRushMe; - public boolean fullscreen; - public int gameMode; - public boolean musicOn; - public boolean soundOn; - public int targetMode; - - /** - * Preferences class constructor. Variables are - * initialized to defaults. - */ - public Preferences() { - bluetooth = 0; - collision = BubbleSprite.MIN_PIX; - colorMode = false; - compressor = false; - difficulty = LevelManager.MODERATE; - dontRushMe = true; - fullscreen = true; - gameMode = FrozenBubble.GAME_NORMAL; - musicOn = true; - soundOn = true; - targetMode = FrozenBubble.POINT_TO_SHOOT; - } - - /** - * Preferences class constructor. - * @param prefs - object reference used to initialize this object. - * Pass null to create a default instance. - */ - public Preferences(Preferences prefs) { - copy(prefs); - } - - /** - * Copy the values of the supplied object to this object. - * @param prefs - the object to copy to this object. - */ - public void copy(Preferences prefs) { - if (prefs != null) { - this.bluetooth = prefs.bluetooth; - this.collision = prefs.collision; - this.colorMode = prefs.colorMode; - this.compressor = prefs.compressor; - this.difficulty = prefs.difficulty; - this.dontRushMe = prefs.dontRushMe; - this.fullscreen = prefs.fullscreen; - this.gameMode = prefs.gameMode; - this.musicOn = prefs.musicOn; - this.soundOn = prefs.soundOn; - this.targetMode = prefs.targetMode; - } - } -}; diff --git a/src/com/efortin/frozenbubble/PreferencesActivity.java b/src/com/efortin/frozenbubble/PreferencesActivity.java deleted file mode 100644 index afe3090..0000000 --- a/src/com/efortin/frozenbubble/PreferencesActivity.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import java.util.ArrayList; - -import org.jfedor.frozenbubble.BubbleSprite; -import org.jfedor.frozenbubble.FrozenBubble; -import org.jfedor.frozenbubble.LevelManager; -import org.jfedor.frozenbubble.R; - -import android.bluetooth.BluetoothDevice; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.Preference.OnPreferenceClickListener; -import android.preference.PreferenceActivity; -import android.preference.PreferenceManager; -import android.view.KeyEvent; - -public class PreferencesActivity extends PreferenceActivity{ - - private ListPreference bluetoothDeviceList; - private SeekBarPreference collisionSlider; - private SeekBarPreference difficultySlider; - - private void cleanUp() { - collisionSlider = null; - difficultySlider = null; - } - - public static Preferences getDefaultPrefs(SharedPreferences sp) { - Preferences prefs = new Preferences(); - prefs.bluetooth = Integer.valueOf(sp.getString("bluetooth_list", "0")); - prefs.collision = sp.getInt("collision_option", BubbleSprite.MIN_PIX); - prefs.compressor = sp.getBoolean("compressor_option", false); - prefs.difficulty = sp.getInt("difficulty_option", LevelManager.MODERATE); - prefs.dontRushMe = sp.getBoolean("rush_me_option", true); - prefs.fullscreen = sp.getBoolean("fullscreen_option", true); - prefs.colorMode = sp.getBoolean("colorblind_option", false); - prefs.musicOn = sp.getBoolean("play_music_option", true); - prefs.soundOn = sp.getBoolean("sound_effects_option", true); - prefs.targetMode = Integer.valueOf(sp.getString("targeting_option", - Integer.toString(FrozenBubble.POINT_TO_SHOOT))); - - if (!prefs.colorMode) - prefs.gameMode = FrozenBubble.GAME_NORMAL; - else - prefs.gameMode = FrozenBubble.GAME_COLORBLIND; - - return prefs; - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - addPreferencesFromResource(R.layout.activity_preferences_screen); - collisionSlider = (SeekBarPreference) findPreference("collision_option" ); - difficultySlider = (SeekBarPreference) findPreference("difficulty_option"); - bluetoothDeviceList = (ListPreference ) findPreference("bluetooth_list" ); - - setBluetoothListPreferenceData(bluetoothDeviceList); - - bluetoothDeviceList.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - setBluetoothListPreferenceData(bluetoothDeviceList); - return false; - } - }); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - - cleanUp(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent msg) { - boolean result = false; - - if (keyCode == KeyEvent.KEYCODE_BACK) { - FrozenBubble.setPrefs(getDefaultPrefs(PreferenceManager. - getDefaultSharedPreferences(this))); - finish(); - } - else { - result = collisionSlider .onKey(keyCode, msg); - result |= difficultySlider.onKey(keyCode, msg); - } - - return result || super.onKeyDown(keyCode, msg); - } - - public static void saveDefaultPreferences(Preferences prefs, - SharedPreferences sp) { - SharedPreferences.Editor editor = sp.edit(); - editor.putString ("bluetooth_list", Integer.toString(prefs.bluetooth)); - editor.putInt ("collision_option", prefs.collision ); - editor.putBoolean("compressor_option", prefs.compressor ); - editor.putInt ("difficulty_option", prefs.difficulty ); - editor.putBoolean("rush_me_option", !prefs.dontRushMe ); - editor.putBoolean("fullscreen_option", prefs.fullscreen ); - editor.putBoolean("colorblind_option", prefs.colorMode ); - editor.putBoolean("play_music_option", prefs.musicOn ); - editor.putBoolean("sound_effects_option", prefs.soundOn ); - editor.putString ("targeting_option", Integer.toString(prefs.targetMode)); - editor.commit(); - } - - protected static void setBluetoothListPreferenceData(ListPreference lp) { - ArrayList entryStrings = new ArrayList(); - ArrayList valueStrings = new ArrayList(); - - BluetoothDevice[] devices = BluetoothManager.getPairedDevices(); - if ((devices != null) && (devices.length > 0)) { - int index = 0; - while (index < devices.length) { - entryStrings.add(devices[index++].getName()); - valueStrings.add(Integer.toString(index)); - } - CharSequence[] entries = entryStrings.toArray(new CharSequence[entryStrings.size()]); - CharSequence[] entryValues = valueStrings.toArray(new CharSequence[valueStrings.size()]); - lp.setEntries (entries ); - lp.setDefaultValue(entryValues[0]); - lp.setEntryValues (entryValues ); - lp.setEnabled (true ); - } - else { - lp.setEnabled(false); - } - } -} diff --git a/src/com/efortin/frozenbubble/ScrollingCredits.java b/src/com/efortin/frozenbubble/ScrollingCredits.java deleted file mode 100644 index c658dc5..0000000 --- a/src/com/efortin/frozenbubble/ScrollingCredits.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import org.jfedor.frozenbubble.FrozenBubble; -import org.jfedor.frozenbubble.R; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.graphics.Color; -import android.os.Bundle; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.LinearLayout.LayoutParams; - -public class ScrollingCredits extends Activity implements Runnable { - private boolean victoryScreenShown = false; - private ScrollingTextView credits; - private ModPlayer myModPlayer = null; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - // Configure the window presentation and layout. - setWindowLayout(R.layout.activity_scrolling_credits); - // Get the instance of the ScrollingTextView object. - credits = (ScrollingTextView)findViewById(R.id.scrolling_credits); - // Configure the credits text presentation. - credits.setScrollRepeatLimit(0); - credits.setSpeed(50.0f); - credits.setScrollDirection(ScrollingTextView.SCROLL_UP); - credits.setTextSize(18.0f); - // Start the credits music. - myModPlayer = new ModPlayer(this, R.raw.worldofpeace, - FrozenBubble.getMusicOn(), false); - // Post this runnable instance to the scrolling text view. - credits.postDelayed(this, 100); - } - - @Override - public void onPause() { - super.onPause(); - pauseCredits(); - } - - @Override - public void onResume() { - super.onResume(); - resumeCredits(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - cleanUp(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent msg) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - end(); - return true; - } - return checkCreditsDone(); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - return checkCreditsDone(); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - - if (hasFocus) - resumeCredits(); - else - pauseCredits(); - } - - private void displayImage(int id) { - // Construct a new LinearLayout programmatically. - LinearLayout linearLayout = new LinearLayout(this); - linearLayout.setOrientation(LinearLayout.VERTICAL); - linearLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, - LayoutParams.FILL_PARENT)); - // ImageView setup for the image. - ImageView imageView = new ImageView(this); - // Set image resource. - imageView.setImageResource(id); - // Set image position and scaling. - imageView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, - LayoutParams.FILL_PARENT)); - // Add view to layout. - linearLayout.addView(imageView); - // Set the content view to this layout and display the image. - setContentView(linearLayout); - } - - /** - * Set the window layout according to the settings in the specified - * layout XML file. Then apply the full screen option according to - * the player preference setting. - *

Note that the title bar is not desired for the scrolling - * credits, and requesting that the title bar be removed must - * be applied before setting the view content by applying the XML - * layout or it will generate an exception. - * @param layoutResID - The resource ID of the XML layout to use for - * the window layout settings. - */ - private void setWindowLayout(int layoutResID) { - final int flagFs = WindowManager.LayoutParams.FLAG_FULLSCREEN; - final int flagNoFs = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN; - - // Remove the title bar. - requestWindowFeature(Window.FEATURE_NO_TITLE); - // Load and apply the specified XML layout. - setContentView(layoutResID); - // Set full screen mode based on the game preferences. - SharedPreferences mConfig = - getSharedPreferences(FrozenBubble.PREFS_NAME, Context.MODE_PRIVATE); - boolean fullscreen = mConfig.getBoolean("fullscreen", true); - - if (fullscreen) { - getWindow().addFlags(flagFs); - getWindow().clearFlags(flagNoFs); - } - else { - getWindow().clearFlags(flagFs); - getWindow().addFlags(flagNoFs); - } - } - - public boolean checkCreditsDone() { - if (!credits.isScrolling()) { - end(); - return true; - } - return false; - } - - public void cleanUp() { - if (myModPlayer != null) { - myModPlayer.destroyMusicPlayer(); - myModPlayer = null; - } - } - - public void end() { - credits.abort(); - /* - * Since the default game activity creates its own player, - * destroy the current player. - */ - cleanUp(); - /* - * Create an intent to launch the game activity. Since it was - * running in the background while this activity was running, it - * may have been stopped by the system. - */ - Intent intent = new Intent(this, FrozenBubble.class); - startActivity(intent); - finish(); - } - - public void pauseCredits() { - if (myModPlayer != null) - myModPlayer.pausePlay(); - credits.setPaused(true); - } - - public void resumeCredits() { - if (myModPlayer != null) - myModPlayer.unPausePlay(); - credits.setPaused(false); - } - - @Override - public void run() { - /* - * Check if we need to display the end of game victory image. - */ - if (!credits.isScrolling() && !victoryScreenShown) { - victoryScreenShown = true; - // Make the credits text transparent. - credits.setTextColor(Color.TRANSPARENT); - // Display the end of game victory image. - displayImage(R.drawable.victory); - } - credits.postDelayed(this, 100); - } -} diff --git a/src/com/efortin/frozenbubble/ScrollingTextView.java b/src/com/efortin/frozenbubble/ScrollingTextView.java deleted file mode 100644 index 1c287a7..0000000 --- a/src/com/efortin/frozenbubble/ScrollingTextView.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.animation.LinearInterpolator; -import android.widget.Scroller; -import android.widget.TextView; - -/** - * This is an implementation of a vertically scrolling TextView. - * - *

The scroll direction is configurable, as is the scrolling speed - * and the the number of times to scroll the text. - */ -public class ScrollingTextView extends TextView implements Runnable { - private static final float DEFAULT_SPEED = 15.0f; - public static final boolean SCROLL_DOWN = true; - public static final boolean SCROLL_UP = false; - public static final int SCROLL_FOREVER = -1; - - private Scroller scroller; - - private int duration; - private int scrollCount = SCROLL_FOREVER; - private boolean scrollDirection = SCROLL_DOWN; - private float speed = DEFAULT_SPEED; - private boolean started; - private int y_distance; - private int y_offset; - - public boolean scrollingPaused; - - /* - * Constructors. - */ - public ScrollingTextView(Context context) { - super(context); - setup(context); - init(); - } - - public ScrollingTextView(Context context, AttributeSet attributes) { - super(context, attributes); - setup(context); - init(); - } - - /* - * Private methods. - */ - private void refreshScroll() { - if (scrollingPaused) { - /** - * TODO: forceFinished() should be stopping the scroll right - * where it is, but it isn't for some reason while the window - * is in fullscreen mode. This should be fixed. On the other - * hand, when scrolling is resumed, it starts where it should, - * which is absolutely necessary. - */ - scroller.forceFinished(true); - } - else { - y_distance -= scroller.getCurrY() - y_offset; - y_offset = scroller.getCurrY(); - duration = (int) (Math.abs(y_distance) * speed); - /** - * Revert any animation currently in progress. - */ - scroller.forceFinished(true); - scroller.startScroll(0, y_offset, 0, y_distance, duration); - if (scrollCount != 0) - post(this); - } - /** - * Invalidate the view to request a redraw. - */ - invalidate(); - } - - private void setup(Context context) { - scroller = new Scroller(context, new LinearInterpolator()); - setScroller(scroller); - } - - private void startScroll() { - int viewHeight = getHeight(); - int visibleHeight = viewHeight - getPaddingBottom() - getPaddingTop(); - int lineHeight = getLineHeight(); - - if (scrollDirection == SCROLL_UP) { - y_offset = -visibleHeight; - y_distance = visibleHeight + (getLineCount() * lineHeight); - } - else { - y_offset = getLineCount() * lineHeight; - y_distance = -(visibleHeight + ((getLineCount() + 1) * lineHeight)); - } - - duration = (int) (Math.abs(y_distance) * speed); - scroller.startScroll(0, y_offset, 0, y_distance, duration); - - if (scrollCount != 0) { - if(scrollCount > 0) - scrollCount--; - - post(this); - } - started = true; - } - - /* - * Protected methods. - */ - @Override - protected void onLayout(boolean changed, - int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - /** - * TODO: when the layout is changed, the scrolling offset and - * distance should be re-mapped to the new screen height from - * the previous screen height. - */ - if (!started) - startScroll(); - } - - /* - * Public methods. - */ - public void init() { - scrollingPaused = false; - started = false; - } - - @Override - public void run() { - if (!scrollingPaused) { - if (scroller.isFinished()) { - startScroll(); - } - else { - post(this); - } - } - } - - public void abort() { - scrollCount = 0; - scrollingPaused = false; - scroller.forceFinished(true); - } - - public float getSpeed() { - return speed; - } - - public boolean isScrolling() { - return (scrollCount != 0) || !scroller.isFinished() || scrollingPaused || - !started; - } - - public void setPaused(boolean paused) { - synchronized (this) { - if (isScrolling() && started) { - if (paused && !scrollingPaused) { - scrollingPaused = true; - refreshScroll(); - } - else if (!paused && scrollingPaused) { - scrollingPaused = false; - refreshScroll(); - } - } - } - } - - public void setScrollDirection(boolean scrollDirection) { - this.scrollDirection = scrollDirection; - } - - /** - * This method sets the additional number of times to scroll the - * text. The text will always scroll at least once. - * - *

If the scroll count is set to -1, then the text will scroll - * indefinitely. - * - * @param scrollCount - * - The additional number of times to scroll the text. If - * this parameter is zero, the text will still scroll once. - */ - public void setScrollRepeatLimit(int scrollCount) { - this.scrollCount = scrollCount; - } - - public void setSpeed(float speed) { - this.speed = speed; - } -} diff --git a/src/com/efortin/frozenbubble/SeekBarPreference.java b/src/com/efortin/frozenbubble/SeekBarPreference.java deleted file mode 100644 index 46c34fa..0000000 --- a/src/com/efortin/frozenbubble/SeekBarPreference.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import org.jfedor.frozenbubble.R; - -import android.content.Context; -import android.content.res.TypedArray; -import android.preference.Preference; -import android.util.AttributeSet; -import android.util.Log; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.widget.RelativeLayout; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.TextView; - -public class SeekBarPreference extends Preference - implements OnSeekBarChangeListener { - - private final String TAG = getClass().getName(); - - private static final String ANDROIDNS = - "http://schemas.android.com/apk/res/android"; - private static final String FROZENBUBBLENS = - "https://code.google.com/p/frozenbubbleandroid"; - private static final int DEFAULT_VALUE = 50; - - private int mMaxValue = 100; - private int mMinValue = 0; - private int mInterval = 1; - private int mCurrentValue; - private String mUnitsLeft = ""; - private String mUnitsRight = ""; - private SeekBar mSeekBar; - private TextView mStatusText; - - public SeekBarPreference(Context context, AttributeSet attrs) { - super(context, attrs); - initPreference(context, attrs); - } - - public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initPreference(context, attrs); - } - - private String getAttributeStringValue(AttributeSet attrs, String namespace, - String name, String defaultValue) { - String value = attrs.getAttributeValue(namespace, name); - if(value == null) - value = defaultValue; - - return value; - } - - private void initPreference(Context context, AttributeSet attrs) { - setValuesFromXml(attrs); - mSeekBar = new SeekBar(context, attrs); - mSeekBar.setMax(mMaxValue - mMinValue); - mSeekBar.setOnSeekBarChangeListener(this); - mSeekBar.setFocusable(true); - mSeekBar.setFocusableInTouchMode(true); - this.setSelectable(true); - } - - @Override - public void onBindView(View view) { - super.onBindView(view); - - try { - // move our seekbar to the new view we've been given - ViewParent oldContainer = mSeekBar.getParent(); - ViewGroup newContainer = - (ViewGroup)view.findViewById(R.id.seekBarPrefBarContainer); - - if (oldContainer != newContainer) { - // remove the seekbar from the old view - if (oldContainer != null) { - ((ViewGroup)oldContainer).removeView(mSeekBar); - } - // remove the existing seekbar (there may not be one) and add ours - newContainer.removeAllViews(); - newContainer.addView(mSeekBar, ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - } - } catch(Exception ex) { - Log.e(TAG, "Error binding view: " + ex.toString()); - } - - updateView(view); - } - - @Override - protected View onCreateView(ViewGroup parent){ - RelativeLayout layout = null; - - try { - LayoutInflater mInflater = (LayoutInflater)getContext(). - getSystemService(Context.LAYOUT_INFLATER_SERVICE); - layout = (RelativeLayout)mInflater. - inflate(R.layout.seek_bar_preference, parent, false); - } - catch(Exception e) - { - Log.e(TAG, "Error creating seek bar preference", e); - } - - return layout; - } - - @Override - protected Object onGetDefaultValue(TypedArray ta, int index) { - int defaultValue = ta.getInt(index, DEFAULT_VALUE); - return defaultValue; - } - - public boolean onKey(int keyCode, KeyEvent event) { - if (mSeekBar.isSelected() && (event.getAction() == KeyEvent.ACTION_DOWN)) { - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_LEFT: - if (mCurrentValue > mMinValue) { - mSeekBar.setProgress((mCurrentValue - mMinValue) - mInterval); - return true; - } - break; - case KeyEvent.KEYCODE_DPAD_RIGHT: - if (mCurrentValue < mMaxValue) { - mSeekBar.setProgress((mCurrentValue - mMinValue) + mInterval); - return true; - } - break; - } - } - return false; - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, - boolean fromUser) { - int newValue = progress + mMinValue; - - if(newValue > mMaxValue) - newValue = mMaxValue; - else if(newValue < mMinValue) - newValue = mMinValue; - else if(mInterval != 1 && newValue % mInterval != 0) - newValue = Math.round(((float)newValue)/mInterval)*mInterval; - - // change rejected, revert to the previous value - if(!callChangeListener(newValue)){ - seekBar.setProgress(mCurrentValue - mMinValue); - return; - } - - // change accepted, store it - mCurrentValue = newValue; - mStatusText.setText(String.valueOf(newValue)); - persistInt(newValue); - } - - @Override - protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { - if(restoreValue) { - mCurrentValue = getPersistedInt(mCurrentValue); - } - else { - int temp = 0; - try { - temp = (Integer)defaultValue; - } - catch(Exception ex) { - Log.e(TAG, "Invalid default value: " + defaultValue.toString()); - } - - persistInt(temp); - mCurrentValue = temp; - } - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) {} - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - notifyChanged(); - } - - public void setDefaultValue(int newValue) { - mCurrentValue = newValue; - } - - private void setValuesFromXml(AttributeSet attrs) { - mMaxValue = attrs.getAttributeIntValue(ANDROIDNS, "max", 100); - mMinValue = attrs.getAttributeIntValue(FROZENBUBBLENS, "min", 0); - - mUnitsLeft = getAttributeStringValue(attrs, FROZENBUBBLENS, - "unitsLeft", ""); - String units = getAttributeStringValue(attrs, FROZENBUBBLENS, "units", ""); - mUnitsRight = getAttributeStringValue(attrs, FROZENBUBBLENS, - "unitsRight", units); - - try { - String newInterval = attrs.getAttributeValue(FROZENBUBBLENS, "interval"); - if(newInterval != null) - mInterval = Integer.parseInt(newInterval); - } - catch(Exception e) { - Log.e(TAG, "Invalid interval value", e); - } - } - - /** - * Update a SeekBarPreference view with our current state. - * @param view - */ - protected void updateView(View view) { - try { - RelativeLayout layout = (RelativeLayout)view; - - mStatusText = (TextView)layout.findViewById(R.id.seekBarPrefValue); - mStatusText.setText(String.valueOf(mCurrentValue)); - mStatusText.setMinimumWidth(30); - - mSeekBar.setProgress(mCurrentValue - mMinValue); - - TextView unitsRight = - (TextView)layout.findViewById(R.id.seekBarPrefUnitsRight); - unitsRight.setText(mUnitsRight); - - TextView unitsLeft = - (TextView)layout.findViewById(R.id.seekBarPrefUnitsLeft); - unitsLeft.setText(mUnitsLeft); - } catch(Exception e) { - Log.e(TAG, "Error updating seek bar preference", e); - } - } -} diff --git a/src/com/efortin/frozenbubble/UDPSocket.java b/src/com/efortin/frozenbubble/UDPSocket.java deleted file mode 100644 index 71810f7..0000000 --- a/src/com/efortin/frozenbubble/UDPSocket.java +++ /dev/null @@ -1,522 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.BindException; -import java.net.DatagramPacket; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.MulticastSocket; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.ArrayList; - -import com.efortin.frozenbubble.NetworkManager.connectEnum; - -import android.content.Context; -import android.net.wifi.WifiManager; -import android.util.Log; - -/** - * UDP socket class - implements UDP unicast and multicast datagram - * sending and receiving. This implementation currently only supports - * IPv4 internet addresses. - *

This class instantiates a thread to send and receive WiFi UDP - * unicast or multicast messages. The MulticastSocket - * class is a descendant of DatagramSocket, the UDP - * datagram socket class. Thus a UDP socket can be used to send and - * receive either UDP unicast datagrams, or UDP multicast datagrams, - * which makes it convenient to use either peer to peer networking - * scheme using virtually identical methods. - *

Multicast host addresses must be in the IPv4 class D address - * range, with the first octet being within the 224 to 239 range. - * For example, "225.0.0.15" is an actual IPv4 multicast - * address. - *

Refer to: - * http://en.wikipedia.org/wiki/Multicast_address for - * information regarding Multicast address usage and restrictions. - *

A typical UDP implementation looks like this: - *


- * UDPSocket session =
- *     new UDPSocket(context, mode, hostName, port);
- * session.setUDPListener(this);
- * 
- *

The context from which to obtain the application context, the - * connection mode, the IP address or host name of the UDP peer, and the - * port of the UDP socket session must be supplied when creating a new - * UDPSocket instance. - *

The following uses permissions must be added to the - * Android project manifest to access all the API functionality required - * to perform UDP unicast or multicast networking as implemented:
- * ACCESS_NETWORK_STATE
- * ACCESS_WIFI_STATE
- * CHANGE_WIFI_MULTICAST_STATE
- * INTERNET
- * @author Eric Fortin, Wednesday, May 8, 2013 - */ -public class UDPSocket { - private static final String LOG_TAG = UDPSocket.class.getSimpleName(); - - /* - * MulticastManager class member variables. - */ - private boolean paused; - private boolean running; - private int mPort; - private connectEnum mType; - private ArrayList txList = null; - private ArrayList listenerList = null; - private Context mContext = null; - private InetAddress remoteAddress = null; - private InetAddress localAddress = null; - private MulticastSocket mSocket = null; - private Thread mThread = null; - private WifiManager.MulticastLock mLock = null; - - /* - * Listener interface for various UDP socket events. - * - * This interface defines the abstract listener method that needs - * to be instantiated by the registrar, as well as the various - * events supported by the interface. - */ - public interface UDPListener { - public abstract void onUDPEvent(InetAddress address, - byte[] buffer, - int length); - } - - public void setUDPListener(UDPListener listener) { - listenerList.add(listener); - } - - /** - * UDP socket class constructor. - *

When created, this class instantiates a thread to send and - * receive WiFi UDP unicast or multicast messages. - *

A typical implementation looks like this: - *


-   * UDPSocket session =
-   *     new UDPSocket(context, mode, hostName, port);
-   * session.setUDPListener(this);
-   * 
- *

The context from which to obtain the application context, the - * connection mode, the host name of the UDP unicast peer or multicast - * group to connect to, and the port of the UDP socket session must be - * supplied when creating a new UDPSocket instance. - *

The following uses permissions must be addeded to - * the Android project manifest to perform UDP unicast networking:
- * INTERNET - *

Multicast host addresses must be in the IPv4 class D address - * range, with the first octet being within the 224 to 239 range. - * For example, "225.0.0.15" is an actual IPv4 multicast - * address. - *

Refer to: - * http://en.wikipedia.org/wiki/Multicast_address - * for information regarding Multicast address usage and restrictions. - *

A typical implementation looks like this: - *


-   * UDPSocket session =
-   *     new UDPSocket(context, mode, hostName, port);
-   * session.setUDPListener(this);
-   * 
- *

The context from which to obtain the application context, the - * connection mode, the IP address of the UDP multicast session, and - * the port of the UDP socket must be supplied when creating a new - * UDPSocket instance. - *

The following uses permissions must be added to the - * Android project manifest to perform UDP multicast networking:
- * CHANGE_WIFI_MULTICAST_STATE
- * INTERNET
- * @param context - the context from which to obtain the application - * context for the purpose of obtaining WiFi service access. - * @param mode - the connection mode, either UNICAST or MULTICAST. - * @param hostName - the host name of the UDP unicast peer or - * multicast group. - * @param port - the port number to use for the UDP socket. - * @throws UnknownHostException the host name is invalid. - * @throws IOException socket creation failed. - */ - public UDPSocket(Context context, connectEnum mode, String hostName, - int port) throws UnknownHostException, IOException { - mContext = context.getApplicationContext(); - mPort = port; - mLock = null; - mThread = null; - txList = null; - mType = mode; - configureUDPSocket(hostName, port); - txList = new ArrayList(); - listenerList = new ArrayList(); - if (mode == connectEnum.UDP_MULTICAST) { - WifiManager wm = - (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE); - mLock = wm.createMulticastLock("UDPLock"); - mLock.setReferenceCounted(true); - mLock.acquire(); - } - mThread = new Thread(new UDPThread(), "mThread"); - mThread.start(); - } - - final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); - public static String bytesToHex(byte[] bytes, int length) { - char[] hexChars = new char[length * 2]; - for ( int j = 0; j < length; j++ ) { - int v = bytes[j] & 0xFF; - hexChars[j * 2 ] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } - - /** - * Clean up the UDP socket by stopping the thread, closing the UDP - * socket and freeing resources. - */ - public void cleanUp() { - if (listenerList != null) { - listenerList.clear(); - } - listenerList = null; - stopThread(); - if (mSocket != null) { - if (mSocket.isConnected()) { - if (mType == connectEnum.UDP_MULTICAST) { - try { - mSocket.leaveGroup(remoteAddress); - } catch (IOException ioe) { - /* - * Auto-generated catch block. - */ - ioe.printStackTrace(); - } - } - else { - mSocket.disconnect(); - } - } - mSocket.close(); - } - mSocket = null; - if (mLock != null) { - if (mLock.isHeld()) { - mLock.release(); - } - } - mLock = null; - if (txList != null) { - txList.clear(); - } - txList = null; - } - - /** - * Configure the UDP socket settings. - *

This must be called before start()ing the thread. - * @param hostName - the IP address or host name of the UDP unicast - * peer or multicast group. - * @param port - the port number to use for the UDP socket. - * @throws UnknownHostException the host name is invalid. - * @throws IOException socket creation failed. - */ - private void configureUDPSocket(String hostName, int port) throws - UnknownHostException, IOException{ - remoteAddress = null; - mSocket = null; - remoteAddress = InetAddress.getByName(hostName); - mSocket = new MulticastSocket(port); - mSocket.setSoTimeout(101); - mSocket.setBroadcast(false); - mSocket.setLoopbackMode(true); - mSocket.setReuseAddress(true); - if (mType == connectEnum.UDP_MULTICAST) { - mSocket.joinGroup(remoteAddress); - } - } - - /** - * This is the UDP socket receive and transmit thread declaration. - *

To support being able to send and receive packets in the same - * thread, a nonzero socket read timeout must be set, because - * MulticastSocket.receive() blocks until a packet is - * received or the socket times out. Thus, if a timeout of zero is - * set (which is the default, and denotes that the socket will never - * time out), a datagram will never be sent unless one has just been - * received. - * @author Eric Fortin, Wednesday, May 8, 2013 - * @see configureUDPSocket() - */ - private class UDPThread implements Runnable { - private byte[] rxBuffer = new byte[256]; - - /** - * Receive a UDP datagram. - *

Given a nonzero socket timeout, it is expected behavior for - * this method to catch an InterruptedIOException. - * This method posts an EVENT_PACKET_RX event to the - * registered listener upon datagram receipt. - */ - private void receiveDatagram() { - if (!paused && running) try { - DatagramPacket dpRX = new DatagramPacket(rxBuffer, rxBuffer.length, - remoteAddress, mPort); - mSocket.receive(dpRX); - byte[] buffer = dpRX.getData(); - int length = dpRX.getLength(); - InetAddress address = dpRX.getAddress(); - - if (!paused && running && (length != 0) && (address != localAddress) && - (listenerList != null)) { - int size = listenerList.size(); - while (--size >= 0) { - listenerList.get(size).onUDPEvent(address, buffer, length); - } - Log.d(LOG_TAG, "received "+length+" bytes from "+ remoteAddress + - ": 0x" + bytesToHex(buffer, length)); - } - } catch (NullPointerException npe) { - npe.printStackTrace(); - } catch (InterruptedIOException iioe) { - /* - * Receive timeout. This is expected behavior. - */ - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - - /** - * This is the thread's run() call. - *

Send and receive UDP datagrams. - *

To support being able to send and receive packets in the same - * thread, a nonzero socket read timeout must be set, because - * MulticastSocket.receive() blocks until a packet is - * received or the socket times out. Thus, if a timeout of zero is - * set (which is the default, and denotes that the socket will never - * time out), a datagram will never be sent unless one has just been - * received. - *

Thus the maximum time between datagram transmissions is the - * socket timeout if no datagrams are being recieved. If messages - * are being received, available TX throughput will be increased. - */ - @Override - public void run() { - paused = false; - running = true; - - while (running) { - if (paused) try { - synchronized(this) { - wait(); - } - } catch (InterruptedException ie) { - /* - * Interrupted. This is expected behavior. - */ - } - - if (!paused && running) { - sendDatagram(); - receiveDatagram(); - } - } - } - - /** - * Extract the next buffer from the FIFO transmit list and send it - * as a UDP datagram packet. - */ - private void sendDatagram() { - if (!paused && running && txList.size() > 0) try { - byte[] bytes; - synchronized(txList) { - bytes = txList.get(0); - } - mSocket.send( - new DatagramPacket(bytes, bytes.length, remoteAddress, mPort)); - Log.d(LOG_TAG, "transmitted "+bytes.length+" bytes to "+ - remoteAddress.getHostAddress() + ": 0x" + - bytesToHex(bytes, bytes.length)); - synchronized(txList) { - txList.remove(0); - } - } catch (NullPointerException npe) { - npe.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - } - - public void pause() { - if (running) { - paused = true; - if (mSocket.isConnected()) { - if (mType == connectEnum.UDP_MULTICAST) { - try { - mSocket.leaveGroup(remoteAddress); - } catch (IOException ioe) { - /* - * Auto-generated catch block. - */ - ioe.printStackTrace(); - } - } - else { - mSocket.disconnect(); - } - if (mLock != null) { - if (mLock.isHeld()) { - mLock.release(); - } - } - } - } - } - - public void setLocalIPaddress(InetAddress address) { - localAddress = address; - } - - /** - * Stop and join() the UDP thread. - */ - private void stopThread() { - paused = false; - running = false; - if (mThread != null) { - synchronized(mThread) { - mThread.interrupt(); - } - } - /* - * Close and join() the UDP thread. - */ - boolean retry = true; - while (retry && (mThread != null)) { - try { - mThread.join(); - retry = false; - } catch (InterruptedException e) { - /* - * Keep trying to close the UDP thread. - */ - } - } - } - - /** - * Send the desired byte buffer as a UDP datagram packet. - * @param buffer - the byte buffer to transmit. - * @return true if the buffer was successfully added to - * the outgoing datagram transmit list, false if the the - * buffer was unable to be added to the transmit list. - */ - public boolean transmit(byte[] buffer) { - if ((mThread != null) && running) { - synchronized(txList) { - txList.add(buffer); - } - return true; - } - return false; - } - - public void unPause() { - paused = false; - try { - if (mLock != null) { - if (!mLock.isHeld()) { - mLock.acquire(); - } - } - if (mType == connectEnum.UDP_MULTICAST) { - try { - mSocket.joinGroup(remoteAddress); - } catch (SocketException se) { - /* - * Rejoining the multicast group will result in a - * SocketException being thrown. This occurs even if you - * left the group before rejoining it. This is expected - * behavior. - */ - } - } - else { - /* - * If the bind attempt throws a BindException, skip connecting - * the socket as it is already bound. - */ - try { - mSocket.bind (new InetSocketAddress(remoteAddress, mPort)); - mSocket.connect(new InetSocketAddress(remoteAddress, mPort)); - } catch(BindException be) { - /* - * If the socket was already bound to a port, it will throw a - * BindException. This is expected behavior. - */ - } - } - } catch (IOException ioe) { - ioe.printStackTrace(); - } - if (mThread != null) { - synchronized(mThread) { - mThread.interrupt(); - } - } - } -}; diff --git a/src/com/efortin/frozenbubble/VirtualInput.java b/src/com/efortin/frozenbubble/VirtualInput.java deleted file mode 100644 index 9139ef7..0000000 --- a/src/com/efortin/frozenbubble/VirtualInput.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.efortin.frozenbubble; - -import org.jfedor.frozenbubble.FrozenGame; - -import android.view.KeyEvent; - -/** - * This class encapsulates variables used to interface all possible - * virtual player actions. - * @author Eric Fortin - * - */ -public abstract class VirtualInput { - /* - * Player ID definitions. - */ - public static final byte PLAYER1 = 1; - public static final byte PLAYER2 = 2; - - public int playerID = PLAYER1; - public boolean isCPU = false; - public boolean isRemote = false; - public FrozenGame mGameRef = null; - protected boolean mTouchFire = false; - protected boolean mWasCenter = false; - protected boolean mWasDown = false; - protected boolean mWasLeft = false; - protected boolean mWasRight = false; - protected boolean mWasUp = false; - - /* - * The following are abstract methods that must be implemented by - * descendants. They must clear the appropriate action flag and - * return its original value. - */ - public abstract boolean actionCenter(); - public abstract boolean actionDown(); - public abstract boolean actionLeft(); - public abstract boolean actionRight(); - public abstract boolean actionUp(); - - /* The following are abstract methods that must be implemented by - * descendants to handle all the various input events. - */ - public abstract boolean checkNewActionKeyPress(int keyCode); - public abstract boolean setKeyDown(int keyCode); - public abstract boolean setKeyUp(int keyCode); - public abstract boolean setTouchEvent(int event, double x, double y); - public abstract void setTrackBallDx(double trackBallDX); - - /** - * Configure this player input instance. - * @param id - this player ID, e.g., PLAYER1. - * @param type - true if this player is a CPU simulation. - * @param remote - true if this player is playing on a - * remote machine, false if this player is local. - * @see VirtualInput - */ - protected final void configure(int id, - boolean type, - boolean remote) { - playerID = id; - isCPU = type; - isRemote = remote; - } - - /** - * Initialize class variables to defaults. - */ - public final void init_vars() { - mGameRef = null; - mTouchFire = false; - mWasCenter = false; - mWasDown = false; - mWasLeft = false; - mWasRight = false; - mWasUp = false; - } - - /** - * Process virtual key presses. This method only sets the - * historical keypress flags, which must be cleared by ancestors - * that inherit this class. - *

The touch flag is a special case that denotes that - * this is purely a launch request, regardless of the keypress. - * @param keyCode - the virtual keypress to simulate. - * @param touchFire - true to set the flag to simulate a - * launch request. - */ - public final void setAction(int keyCode, boolean touchFire) { - if (touchFire) { - mTouchFire = true; - } - else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { - mWasCenter = true; - } - else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { - mWasDown = true; - } - else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { - mWasLeft = true; - } - else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { - mWasRight = true; - } - else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { - mWasUp = true; - } - } - - /** - * Set the game reference for this player. - * @param gameRef - the reference to this player's game object. - */ - public final void setGameRef(FrozenGame gameRef) { - mGameRef = gameRef; - } -} diff --git a/src/com/peculiargames/andmodplug/MODResourcePlayer.java b/src/com/peculiargames/andmodplug/MODResourcePlayer.java deleted file mode 100644 index ef61c4e..0000000 --- a/src/com/peculiargames/andmodplug/MODResourcePlayer.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * MOD player source - Copyright (c) 2011 Patrick Casey. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package com.peculiargames.andmodplug; - -import java.io.IOException; -import java.io.InputStream; - -import android.content.Context; - -/** - * Convenience class extending PlayerThread, handling all the file - * operations, accepting Android resource IDs for MOD/XM song files. - *

Typical call order: - *
// get player instance (in topmost activity, etc.) - *
mrp = MODResourcePlayer(); - *
// load MOD/XM data into player - *
mrp.loadModuleResource(R.raw.coolsong); - *
mrp.start(); // start thread (playing song)
- *
Then when changing songs (new game level or transition to - * another sub-activity, etc.): - *
mrp.pausePlay(); - *
mrp.loadModuleResource(R.raw.newcoolsong); - *
mrp.unPausePlay(); - *
// repeat...
- * @version 1.0 - * @author P.A. Casey (crow) Peculiar-Games.com - * @author Eric Fortin - * - */ -public class MODResourcePlayer extends PlayerThread { - /* - * Application context, for accessing the resources - specifically the - * the R.raw. resources which are MOD music files. - */ - private Context mContext; - - /** - * Allocates a MOD/XM/etc. song Player object that can handle Android - * resource files (typically the songs are stored in the res/raw - * project directory and conform to Android build process rules, - * lower-case names, etc.) - *

Note about extensions: - *
Developers using Eclipse as an IDE should note that it allows - * the .xm file extension but may be fussy about other tracker format - * extensions. - *

The context argument is the application context - * which allows MODResourcePlayer to load resources directly. - * @param context - Application context creating this instance. - */ - public MODResourcePlayer(Context context) { - // Get super class (PlayerThread) with default rate. - super(0); - mContext = context; - // Set full volume. - setVolume(255); - } - - /** - * Load a MOD/XM/etc. song file from an Android resource. - *

Note about extensions: - *
Developers using Eclipse as an IDE should note that it allows - * the .xm file extension but may be fussy about other tracker format - * extensions. - *

The modResource argument is the resource id for the - * MOD/XM song file, e.g. R.raw.coolsong - * @param modResource - Android resource ID for a MOD/XM/etc. (tracker - * format) song file. - */ - public boolean loadModuleResource(int modResource) { - byte[] modData = null; - int currfilesize = 0; - InputStream mModfileInStream; - - /* - * Unload any MOD file we have currently loaded. - */ - unLoadMod(); - - /* - * Get an input stream for the MOD file resource. - */ - mModfileInStream = mContext.getResources().openRawResource(modResource); - try { - currfilesize = mModfileInStream.available(); - } catch (IOException ioe1) { - try { - mModfileInStream.close(); - } catch (IOException ioe2) { - /* - * Should never happen. - */ - } - return false; - } - - /* - * Allocate a buffer that can hold the current MOD file data. - */ - try { - modData = new byte[currfilesize]; - } catch (OutOfMemoryError oome) { - // Auto-generated catch block. - oome.printStackTrace(); - try { - mModfileInStream.close(); - } catch (IOException e) { - /* - * Should never happen. - */ - } - return false; - } - - try { - setModSize(mModfileInStream.read(modData, 0, currfilesize)); - mModfileInStream.close(); - } catch (IOException e) { - // Auto-generated catch block. - e.printStackTrace(); - } - - /* - * Load the song into the player. - */ - loadModuleData(modData); - return true; - } - - /** - * Stop playing the song, close down the player and - * join() the player thread. - *

Typically called in the application's main activity - * onDestroy() method. - */ - public void stopAndClose() { - stopThread(); - /* - * Now close and join() the MOD player thread. - */ - boolean retry = true; - while (retry) { - try { - join(); - retry = false; - } catch (InterruptedException e) { - /* - * Keep trying to close the player thread. - */ - } - } - closeLibModPlug(); - } -} diff --git a/src/com/peculiargames/andmodplug/PlayerThread.java b/src/com/peculiargames/andmodplug/PlayerThread.java deleted file mode 100644 index ccf4344..0000000 --- a/src/com/peculiargames/andmodplug/PlayerThread.java +++ /dev/null @@ -1,1066 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * MOD player source - Copyright (c) 2011 Patrick Casey. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -// -// This class is for a separate thread to control the modplug player, -// getting commands from the Activity. -// -// TODO: Needs more error checking - I ignore the minbuffer size when -// getting the audio track, LoadMODData() may fail, etc. -// -// Typical call order: -// -// PlayerThreadOLD() - to get player instance (in top most activity -// that will use music) -// LoadMODData() - to call libmodplug's Load() function with the -// MOD data -// or -// PlayerThreadOLD(moddatabuffer) - to get player instance and load -// data in one call -// then -// start() -// -// Then when changing songs (i.e. new game level or transition to -// another sub-activity, etc.) -// -// PausePlay() -// UnLoadMod() -// LoadMODData(newmodfiledata) -// UnPausePlay() -// repeat... -// -// *NOTE* -// This class assumes there's only one player thread for a whole -// application (all activities) thus the static lock objects (mPVlock, -// mRDlock) below, and lots of other probably bad coding practice -// below... :-( -// -// For a multi-Activity application, you can try the TakeOwnership() -// and GiveUpOwnership() calls, e.g. TakeOwnership(this) in an -// Activity's OnCreate(), and then GiveUpOwnership(this) in onPause(). -// -// - -package com.peculiargames.andmodplug; - -import android.media.AudioFormat; -import android.media.AudioManager; -import android.media.AudioTrack; -import android.util.Log; - -/** - * Player class for MOD/XM song files (extends Java Thread). Has - * methods to load song file data, play the song, get information about - * the song, pause, unpause, etc. - *

Typical call order: - *
// get player instance (in topmost activity, etc.) - *
pt = PlayerThread(); - *
pt.loadModuleData(); // load MOD/XM data into player
- *
or:
- * // get player & load data in one call - *
pt = PlayerThread(modDataBuffer);
- *
then:
- * pt.start(); // start thread (playing song)
- * To play a different song: - *
// changing songs... - *
pt.pausePlay(); - *
pt.unLoadMod(); - *
pt.loadModuleData(newModFileData); - *
pt.unPausePlay(); - *
// repeat...
- * @version 1.0 - * @author P.A. Casey (crow) Peculiar-Games.com - * @author Eric Fortin - * - */ -public class PlayerThread extends Thread { - - public final static String VERS = "1.0"; - private final static String LOGPREFIX = "PLAYERTHREAD"; - - /* - * Constant for setPatternLoopRange() calls - change to - * new pattern range immediately. - */ - public final static int PATTERN_CHANGE_IMMEDIATE = 1; - - /* - * Constant for setPatternLoopRange() calls - change to - * new pattern range after currently playing pattern finishes. - */ - public final static int PATTERN_CHANGE_AFTER_CURRENT = 2; - - /* - * Constant for setPatternLoopRange() calls - change to - * new pattern range after current range of patterns finishes playing. - */ - public final static int PATTERN_CHANGE_AFTER_GROUP = 3; - - /* - * Constant for setLoopCount() calls - loop song forever. - */ - public final static int LOOP_SONG_FOREVER = -1; - - /* - * Limit volume volume steps to 8 steps (just an arbitrary decision). - * There's also a setVolume() method that accepts a float. - */ - public final static float[] sVolume_floats = {0.0f, 0.125f, 0.25f, 0.375f, - 0.5f, 0.625f, 0.75f, 1.0f}; - - /* - * Object for lock on ReadData call (to prevent UI thread messing - * with player thread's GetSoundData() calls). - */ - private Object sRDlock; - - /* - * Private audio playback control flags. - */ - private boolean mFlushed = false; - private boolean mPaused = false; - private boolean mPausedWas = false; - private boolean mRunning = true; - - /* - * Android will report the minimum buffer size needed to keep playing - * audio at our requested rate smoothly. - */ - private int mMinbuffer; - private int mModsize; // holds the size in bytes of the MOD file - private final static int BUFFERSIZE = 20000; // the sample buffer size - private AudioTrack mMyTrack; - private boolean mLoadOk; - - /* - * Variables for storing info about the MOD file currently loaded. - */ - private String mModname; - private int mNumChannels; - private int mRate; - private int posWas; - private boolean songFinished; - private boolean songFinishedWas; - - /* - * Track if player has started (after loading a new MOD). - */ - private boolean playerStarted; - - /* - * Start the player in a paused state? - */ - private boolean startPaused; - - /* - * Audio sampling rate definitions. - */ - private static final int NUM_RATES = 5; - private final int[] try_rates = {44100, 32000, 22000, 16000, 8000}; - - /* - * Static initializer block. This block is executed if a static - * PlayerThread field is accessed, even without prior instantiation - * of a PlayerThread object. - */ - static { - try { - System.loadLibrary("modplug-"+VERS); - //System.loadLibrary("modplug"); - } catch (UnsatisfiedLinkError ule) { - Log.e(LOGPREFIX, "WARNING: Could not load libmodplug-"+VERS+".so"); - Log.e(LOGPREFIX, "------ older or differently named libmodplug???"); - } - } - - //******************************************************************** - // Listener interface for various events - //******************************************************************** - - /* - * Event types enumeration. - */ - public static enum eventEnum { - PLAYER_STARTED, - PATTERN_CHANGE, - SONG_COMPLETED; - } - - /** - * Music player event listener set. - * @author P.A. Casey (crow) Peculiar-Games.com - * - */ - public interface PlayerListener { - public abstract void onPlayerEvent(eventEnum event); - } - - private PlayerListener mPlayerListener = null; - - public void setPlayerListener(PlayerListener pl) { - mPlayerListener = pl; - } - - /* - * Here's (one of) the constructor(s) - grabs an audio track and loads - * a MOD file. - * - * MOD file data has already been read in (using a FileStream) by the - * caller -- that functionality could probably be included here, but - * for now we'll do it this way. - * - * You could use this in the top parent activity (like a game menu) - * to create a PlayerThread and load the MOD data in one call. - */ - - /** - * Allocates a MOD/XM/etc. song PlayerThread - *

The modData argument is a byte[] array with the MOD file - * preloaded into it. The desiredRate argument is a specifier that - * attempts to set the rate audio data will play at - will be - * overridden if the OS doesn't allow that rate. - * @param modData - A byte[] array containing the MOD file data. - * @param desiredRate - Rate of playback (e.g. 44100Hz, or 0 for - * default rate) for system audio data playback. - */ - public PlayerThread(byte[] modData, int desiredRate) { - /* - * Just call the regular constructor and then load in the supplied - * MOD file data. - */ - this(desiredRate); - - /* - * Load the module file (data) into libmodplug and initialize module - * information variables. - */ - loadModuleInfo(modData); - } - - /** - * Allocates a MOD/XM/etc. song PlayerThread. This method just gets - * an audio track. The MOD file will be loaded later with a call to - * LoadMODData(). - *

The desiredRate argument is a specifier that attempts to set the - * rate audio data will play at - will be overridden if the OS doesn't - * allow that rate. - *

General call order when using this constructor is: - *
pt = new PlayerThread(0); - *
pt.loadModuleData(modData); - *
pt.start();
- * @param desiredRate - Rate of playback (e.g. 44100Hz, or 0 for - * default rate) for system audio data playback. - */ - public PlayerThread(int desiredRate) { - /* - * No Activity owns this player yet. - */ - mMyTrack = null; - startPaused = false; - playerStarted = false; - - /* - * Get lock object for synchronizing access to GetSoundData() call. - */ - sRDlock = new Object(); - - /* - * Try to get the audio track. - */ - if (!getAndroidAudioTrack(desiredRate)) { - return; - } - } - - /** - * Determine when a song has played to completion. This method also - * detects when a looping track has started over from the beginning. - */ - private void checkSongCompleted() { - int posNow = getCurrentPos(); - - if ((posNow >= posWas) && (posNow < getMaxPos())) { - songFinished = false; - } - - if (!songFinished && ((posNow < posWas) || (posNow >= getMaxPos()))) { - songFinished = true; - } - - posWas = posNow; - } - - private void cleanUp() { - mModname = null; - sRDlock = null; - /* - * Release the audio track resources. - */ - if (mMyTrack != null) - { - mMyTrack.release(); - mMyTrack = null; - } - } - - /** - * Close the native internal tracker library (libmodplug) and - * deallocate any resources. - */ - public void closeLibModPlug() { - ModPlug_JUnload(); - ModPlug_CloseDown(); - } - - /** - * Try to get an Android stereo audio track used by the various - * constructors. - */ - private boolean getAndroidAudioTrack(int desiredRate) { - int rateIndex = 0; - - /* - * Get a stereo audio track from Android. - * - * PACKETSIZE is the amount of data we request from libmodplug, - * minbuffer is the size Android tells us is necessary to play - * smoothly for the rate, configuration we want and is a separate - * buffer the OS handles. - * - * Init the track and player for the desired rate, or if none - * specified, highest possible. - */ - if (desiredRate == 0) { - boolean success = false; - while (!success && (rateIndex < NUM_RATES)) { - try { - mMinbuffer = AudioTrack.getMinBufferSize(try_rates[rateIndex], - AudioFormat.CHANNEL_CONFIGURATION_STEREO, - AudioFormat.ENCODING_PCM_16BIT); - mMyTrack = new AudioTrack(AudioManager.STREAM_MUSIC, - try_rates[rateIndex], - AudioFormat.CHANNEL_CONFIGURATION_STEREO, - AudioFormat.ENCODING_PCM_16BIT, - mMinbuffer, AudioTrack.MODE_STREAM); - /* - * Init the Modplug player for this sample rate. - */ - ModPlug_Init(try_rates[rateIndex]); - success = true; - } catch (IllegalArgumentException e) { - rateIndex++; - } - } - } - else { - mMinbuffer = AudioTrack.getMinBufferSize(desiredRate, - AudioFormat.CHANNEL_CONFIGURATION_STEREO, - AudioFormat.ENCODING_PCM_16BIT); - mMyTrack = new AudioTrack(AudioManager.STREAM_MUSIC, desiredRate, - AudioFormat.CHANNEL_CONFIGURATION_STEREO, - AudioFormat.ENCODING_PCM_16BIT, - mMinbuffer, AudioTrack.MODE_STREAM); - /* - * Init the Modplug player for this sample rate. - */ - ModPlug_Init(desiredRate); - } - - if (desiredRate == 0) { - if (rateIndex < NUM_RATES) { - mRate = try_rates[rateIndex]; - } - else { - mMyTrack = null; - mRate = 0; - } - } - else { - mRate = desiredRate; - } - - if (mMyTrack == null) { - /* - * Couldn't get an audio track so return false to caller. - */ - return false; - } - else { - /* - * An audio track was successfully created, so check if the - * appropriate resources were acquired for audio streaming. If - * not, then attempt to re-create the audio track one more time. - */ - switch(mMyTrack.getState()) { - case AudioTrack.STATE_INITIALIZED: - break; - default: - mMyTrack = new AudioTrack(AudioManager.STREAM_MUSIC, mRate, - AudioFormat.CHANNEL_CONFIGURATION_STEREO, - AudioFormat.ENCODING_PCM_16BIT, - mMinbuffer*2, AudioTrack.MODE_STREAM); - break; - } - } - /* - * Got the audio track! - */ - return true; - } - - /** - * Loads MOD/XM,etc. song data for playback. Call - * pausePlay() if a song is currently playing prior to - * invoking this method. - *

The modData argument is a byte[] array with the MOD containing - * the song file data. - *

Example of loading the data:
- * modfileInStream = getResources().openRawResource(R.raw.coolxmsong); - *
try {
- * modsize = modfileInStream.read(modData,0, - * modfileInStream.available()); - *
} catch (IOException e) { - *
e.printStackTrace(); - *
}
- * @param modData - A byte[] array containing the MOD file data. - */ - public void loadModuleData(byte[] modData) { - unLoadMod(); - - /* - * Load the module file (data) into libmodplug and initialize module - * information variables. - */ - loadModuleInfo(modData); - - /* - * Re-init this flag so that an event will be passed to the - * PlayerListener after the first write() to the AudioTrack - when - * I assume music will actually start playing... - */ - synchronized(this) { - playerStarted = false; - } - } - - /** - * Load the module file (data) into libmodplug. - *

If the module loads successfully, initialize module info (name - * and number of tracks, track playback location, etc.). - */ - private void loadModuleInfo(byte[] modData) { - mLoadOk = ModPlug_JLoad(modData, modData.length); - - if (mLoadOk) { - mModname = ModPlug_JGetName(); - mNumChannels = ModPlug_JNumChannels(); - posWas = 0; - songFinished = false; - songFinishedWas = false; - } - } - - /* - * MOD file info retrieval methods. - */ - - /** - * Get the name of the song. - * @return the name of the song (from the MOD/XM file header) - */ - public String getModName() { - return mModname; - } - - /** - * Get the file size of the MOD/XM song. - * @return the size of the song file - */ - public int getModSize() { - return mModsize; - } - - /** - * Get the number of channels used in the song (MOD/XM songs - * typically use from 4 to 32 channels in a pattern, mixed together - * for awesomeness). - * @return the number of channels the song uses - */ - public int getNumChannels() { - return mNumChannels; - } - - public int getRate() { - return mRate; - } - - /** - * Pauses playback of the current song. - * @param immediate - if true, pause() then - * flush() the audio stream to immediately stop audio - * playback, otherwise simply stop() the audio stream - * which continues playing until the last buffer written has been - * played to completion. - * @return true if the song was successfully paused. - */ - public boolean pausePlay(boolean immediate) { - boolean paused = false; - - /* - * Set the control flags to stop playback and suspend the thread. - */ - mPaused = true; - mPausedWas = true; - - if (mMyTrack != null) - { - /* - * This check is usually not needed before stopping the audio - * track, but we seem to get an uninitialized audio track here - * occasionally, which throws an IllegalStateException. - */ - if (mMyTrack.getState() == AudioTrack.STATE_INITIALIZED) try { - if (immediate) { - mMyTrack.pause(); - if (mMyTrack != null) { - mMyTrack.flush(); - mFlushed = true; - } - } - else { - mMyTrack.stop(); - } - paused = true; - } catch (NullPointerException npe) { - /* - * mMyTrack may be destroyed in a different process, so the - * slim possibility exists that we may invoke it when it has - * been nullified. - */ - } catch (IllegalStateException ise) { - /* - * Nothing to do here, so just try to continue gracefully. - */ - } - } - - return paused; - } - - /** - * The thread's run() call, where the modules are played. - *

Start playing the MOD/XM song (hopefully it's been previously - * loaded using loadModuleData() or - * loadModuleResource() ;) - */ - public void run() { - boolean patternChange = false; - /* - * Set up our audio sample buffer(libmodplug processes the MOD file - * and fills this with sample data). - * - * For proper error checking, this should check that BUFFERSIZE is - * greater than the minbuffer size the audio system reports in the - * contructors... - */ - short[] mBuffer; - try { - mBuffer = new short[BUFFERSIZE]; - } catch (OutOfMemoryError oome) { - // Auto-generated catch block. - oome.printStackTrace(); - mBuffer = null; - } - - if (startPaused) { - mPaused = true; - mPausedWas = true; - } - else { - mPaused = false; - mPausedWas = false; - } - - if ((mMyTrack != null) && (mBuffer != null)) { - boolean startedPlaying = false; - while (mRunning && !startedPlaying) { - try { - mMyTrack.play(); - startedPlaying = true; - } catch (IllegalStateException ise) { - /* - * The audio track isn't initialized yet. Wait a short - * duration, then try again. - */ - startedPlaying = false; - synchronized(this) { - try { - sleep(20); - } catch (InterruptedException ie) { - /* - * This is expected behavior. - */ - } - } - } - } - } - else { - mRunning = false; - } - - /* - * Main play loop. - */ - while (mRunning) { - while (!mPaused) { - /* - * To prevent unwanted playback of prior audio track buffer - * data, only unpause the audio track after sufficient time has - * elapsed to permit the audio stream to flush the previous - * audio stream buffer if the audio track was flushed. Thus - * playback is resumed here where the audio track control timing - * is managed correctly. - */ - if (mRunning && !mPaused && mPausedWas) { - mPausedWas = false; - if (mFlushed) { - try { - sleep(200); - } catch (InterruptedException ie) { - /* - * This is expected behavior. - */ - } - } - mFlushed = false; - unPause(); - } - - /* - * Pre-load another packet. - */ - synchronized(sRDlock) { - if (mRunning && !mPaused && mLoadOk) { - ModPlug_JGetSoundData(mBuffer, BUFFERSIZE); - - if (ModPlug_CheckPatternChange()) { - patternChange = true; - } - - checkSongCompleted(); - } - } - - /* - * Pass a packet of sound sample data to the audio track - * (blocks until audio track can accept the new data). - */ - if (mRunning && !mPaused) { - mMyTrack.write(mBuffer, 0, BUFFERSIZE); - } - - /* - * Send player events. - */ - synchronized(this) { - if (!playerStarted) { - playerStarted = true; - if (mPlayerListener != null) { - mPlayerListener.onPlayerEvent(eventEnum.PLAYER_STARTED); - } - } - - if (patternChange) { - patternChange = false; - if (mPlayerListener != null) { - mPlayerListener.onPlayerEvent(eventEnum.PATTERN_CHANGE); - } - } - - if (songFinished && !songFinishedWas) { - if (mPlayerListener != null) { - mPlayerListener.onPlayerEvent(eventEnum.SONG_COMPLETED); - } - } - songFinishedWas = songFinished; - } - } - - /* - * Wait until notify() is called. - */ - synchronized(this) { - if (mRunning && mPaused) { - try { - wait(); - } catch (InterruptedException ie) { - /* - * This is expected behavior. - */ - } - } - } - } - - cleanUp(); - } - - /** - * Set the file size of the MOD/XM song. - */ - public void setModSize(int modsize) { - mModsize = modsize; - } - - /** - * Sets playback volume for the MOD/XM player. - * @param vol - An integer from 0 (sound off) to 255 (full volume). - */ - public void setVolume(int vol) { - vol = vol>>5; - if (vol>7) vol = 7; - if (vol<0) vol = 0; - mMyTrack.setStereoVolume(sVolume_floats[vol], sVolume_floats[vol]); - } - - /** - * Sets playback volume for the MOD/XM player. - * @param vol - A floating point number from 0.0f (sound off) to 1.0f - * (full volume). - */ - public void setVolume(float vol) { - if (vol>1.0f) vol = 1.0f; - if (vol<0) vol = 0; - mMyTrack.setStereoVolume(vol, vol); - } - - /** - * This method sets the player startup mode. - * @param flag - If this is set to true, then the player will start up - * paused and will have to be unpaused to start playing. If this is - * set to false, then the player will immediately begin playing when - * it is started. - */ - public void startPaused(boolean flag) { - /* - * Set before calling the thread's start() method. This will cause - * it to start in paused mode. - */ - startPaused = flag; - } - - /** - * This stops the current song if it is playing, and stops the thread. - *

Typically the player should then be join()ed to - * completely remove the thread from the application's Android - * process, and also call closeLibModPlug() to close - * the native player library and de-allocate all resources it used. - */ - public void stopThread() { - /* - * Music playback must be paused before stopping the thread. Force - * a flush of the audio data to immediately stop audio playback. - */ - pausePlay(true); - - /* - * Stops the music player thread (see run() above). - */ - mRunning = false; - - /* - * Interrupt the thread if it is sleeping or waiting. - */ - synchronized(this) { - this.interrupt(); - } - } - - /** - * Unload the current MOD from libmodplug, but make sure to wait - * until any GetSoundData() call in the player thread has - * finished.

Unload MOD/XM data previously loaded into the native - * player library. - */ - public void unLoadMod() { - /* - * Since this can/will be called from the UI thread, need to synch - * and not have a call into libmodplug unloading the file, while a - * call to GetModData() is also executing in the player thread (see - * run() above). - */ - synchronized(sRDlock) { - mLoadOk = false; - ModPlug_JUnload(); - } - } - - /** - * Resumes playback of the current song. - * @return true if the song was successfully unpaused. - */ - private boolean unPause() { - boolean unPaused = false; - if (mMyTrack != null) - { - try { - mMyTrack.play(); - unPaused = true; - } catch (IllegalStateException ise) { - /* - * This is a spurious exception, with the only drawback being - * that audio will remain stopped. Nothing to do here but - * continue gracefully and wait for the next attempt. - */ - } - } - return unPaused; - } - - /** - * Resumes playback of the current song. - */ - public void unPausePlay() { - mPaused = false; - - synchronized(this) { - this.notify(); - } - } - - /** - * EXPERIMENTAL: Change patterns in a song (playing in PATTERN LOOP - * mode). Waits for the currently playing pattern to finish. - * @param newpattern - The new song pattern to start playing - * (repeating) in PATTERN LOOP mode. - */ - public void changePattern(int newpattern) { - ModPlug_ChangePattern(newpattern); - } - - /** - * EXPERIMENTAL: Get the current order - * @return the order. - */ - public int getCurrentOrder() { - return ModPlug_GetCurrentOrder(); - } - - /** - * EXPERIMENTAL: Get the current pattern - * @return the pattern. - */ - public int getCurrentPattern() { - return ModPlug_GetCurrentPattern(); - } - - /** - * EXPERIMENTAL: Get the current "position" in song - * @return the position. - */ - public int getCurrentPos() { - return ModPlug_GetCurrentPos(); - } - - /** - * EXPERIMENTAL: Get the current row in the pattern - * @return the row. - */ - public int getCurrentRow() { - return ModPlug_GetCurrentRow(); - } - - /** - * EXPERIMENTAL: Get the maximum "position" in song - * @return the maximum position. - */ - public int getMaxPos() { - return ModPlug_GetMaxPos(); - } - - /** - * EXPERIMENTAL: Get the default tempo from the song's header. - * @return the tempo. - */ - public int getSongDefaultTempo() { - return ModPlug_GetNativeTempo(); - } - - /** - * EXPERIMENTAL: Modify the song's tempo (+ or -) by mt. - * @param mt - Modifier for the song's "native" tempo (positive values - * to increase tempo, negative values to decrease tempo). - */ - public void modifyTempo(int mt) { - ModPlug_ChangeTempo(mt); - } - - /** - * EXPERIMENTAL: Change song to PATTERN LOOP mode, repeating - * pattern. - * @param pattern - The song pattern to start playing(repeating) in - * PATTERN LOOP mode. - */ - public void repeatPattern(int pattern) { - ModPlug_RepeatPattern(pattern); - } - - /** - * EXPERIMENTAL: set the current pattern (pattern is changed but - * plays from current row in pattern). - * @param pattern - The new pattern to start playing immediately. - */ - public void setCurrentPattern(int pattern) { - ModPlug_SetCurrentPattern(pattern); - } - - /** - * EXPERIMENTAL: Set log printing flag. - * @param flag - true to start printing debug information - * to log output, false to stop. - */ - public void setLogOutput(boolean flag) { - ModPlug_LogOutput(flag); - } - - /** - * EXPERIMENTAL method to loop song the specified number of times. - * @param number - The number of times to loop (-1 = forever). - */ - public void setLoopCount(int loopcount) { - ModPlug_SetLoopCount(loopcount); - } - - /** - * EXPERIMENTAL: set the next pattern to play after current pattern - * finishes. - * @param pattern - The new pattern to start playing after the current - * pattern finishes playing. - */ - public void setNextPattern(int pattern) { - ModPlug_SetNextPattern(pattern); - } - - /** - * EXPERIMENTAL method to set song to PATTERN LOOP mode, repeating - * any pattern playing or subsequently set via - * changePattern(). - * @param flag - true to set PATTERN LOOP mode, - * false to turn off PATTERN LOOP mode. - */ - public void setPatternLoopMode(boolean flag) { - ModPlug_SetPatternLoopMode(flag); - } - - /** - * EXPERIMENTAL method to loop song in a group of patterns. - * @param from - Start of pattern range to play in loop. - * @param to - End of pattern range to play in loop. - * @param when - A constant flag (PATTERN_CHANGE_IMMEDIATE, - * PATTERN_CHANGE_AFTER_CURRENT, PATTERN_CHANGE_AFTER_GROUP) to signal - * when the new pattern range should take effect. - */ - public void setPatternLoopRange(int from, int to, int when) { - ModPlug_SetPatternLoopRange(from, to, when); - } - - /** - * EXPERIMENTAL: Set the song's tempo to tempo. - * @param tempo - The tempo for the song (overrides song's "native" - * tempo). - */ - public void setTempo(int tempo) { - ModPlug_SetTempo(tempo); - } - - /* - * Native methods in our JNI libmodplug stub code. - */ - public native boolean ModPlug_CloseDown(); - public native boolean ModPlug_Init(int rate); - public native String ModPlug_JGetName(); - public native int ModPlug_JGetSoundData(short[] sndbuffer, int datasize); - public native boolean ModPlug_JLoad(byte[] buffer, int size); - public native int ModPlug_JNumChannels(); - public native boolean ModPlug_JUnload(); - - /* - * HACKS ;-). - */ - public native void ModPlug_ChangeTempo(int tempotweak); - public native void ModPlug_ChangePattern(int newpattern); - public native void ModPlug_RepeatPattern(int pattern); - public native void ModPlug_SetCurrentPattern(int pattern); - public native void ModPlug_SetLoopCount(int loopcount); - public native void ModPlug_SetNextPattern(int pattern); - public native void ModPlug_SetPatternLoopMode(boolean flag); - public native void ModPlug_SetPatternLoopRange(int from, int to, int when); - public native void ModPlug_SetTempo(int tempo); - - /* - * More info. - */ - public native boolean ModPlug_CheckPatternChange(); - public native int ModPlug_GetCurrentOrder(); - public native int ModPlug_GetCurrentPattern(); - public native int ModPlug_GetCurrentPos(); - public native int ModPlug_GetCurrentRow(); - public native int ModPlug_GetMaxPos(); - public native int ModPlug_GetNativeTempo(); - - /* - * Log output. - */ - public native void ModPlug_LogOutput(boolean flag); -} diff --git a/src/org/gsanson/frozenbubble/CollisionHelper.java b/src/org/gsanson/frozenbubble/CollisionHelper.java deleted file mode 100644 index 6bf91dc..0000000 --- a/src/org/gsanson/frozenbubble/CollisionHelper.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.gsanson.frozenbubble; - -import org.jfedor.frozenbubble.BubbleSprite; -import org.jfedor.frozenbubble.LevelManager; - -public class CollisionHelper { - - private static final int STATE_INTERMEDIATE_CHECK = -2; - private static final int STATE_CHECK_NEXT = -1; - - public static final int STATE_UNDEFINED = 0; - public static final int STATE_POTENTIAL_REMOVE = 1; - public static final int STATE_REMOVE = 2; - public static final int STATE_ATTACHED = 3; - public static final int STATE_POTENTIAL_DETACHED = 4; - public static final int STATE_DETACHED = 5; - - private CollisionHelper() { - } - - /** - * Checks whether a moving ball collides with fixed balls. - * @param x X-coord of the moving ball, relative to the game area. - * @param y Y-coord of the moving ball, relative to the game area - * (right under the compressor). - * @param grid The grid of fixed bubbles. - * @param toCheck The array of bubbles to check. - * @param minCoords The collision distance coordinates. - * @return true if a collision was detected. - */ - public static boolean collide(int x, int y, BubbleSprite[][] grid, - int[][] toCheck, int[] minCoords) { - boolean collision = false; - int minDist = (int)BubbleSprite.minDistance; - minCoords[0] = 0; - minCoords[1] = 0; - toCheck(x, y, toCheck); - - // Check for collision - int i = 0; - while (!collision && i < 4) { - collision = collision(x, y, toCheck[i][0], toCheck[i][1], grid); - i++; - } - - // Check for position - if (collision) { - for (i = 0; i < 4; i++) { - minDist = distance(x, y, toCheck[i][0], toCheck[i][1], minDist, minCoords); - } - } - - return collision; - } - - /** - * Calculates the distance between real position and a specific point - * in the grid. - * @param x real X-coord. - * @param y real Y-coord. - * @param targetX X target point (grid). - * @param targetY Y target point (grid). - * @param minDist current minimum distance. - * @param outCoords the coordinates associated with the minimum distance found. - * @return The real distance or the current minDist if the point is - * out of the grid or empty. - */ - private static int distance(int x, int y, int targetX, int targetY, - int minDist, int[] outCoords) { - int distance = minDist; - - if ((targetX >= 0) && (targetX < LevelManager.NUM_COLS) && - (targetY >= 0) && (targetY < LevelManager.NUM_ROWS)) { - int dx = (targetX << 5) - ((targetY % 2) << 4) - x; - int dy = targetY * 28 - y; - - distance = dx * dx + dy * dy; - if (distance < minDist) { - outCoords[0] = targetX; - outCoords[1] = targetY; - } else { - distance = minDist; - } - } - - return distance; - } - - /** - * Calculates the distance between real position and a specific point - * in the grid. - * @param x real X-coord. - * @param y real Y-coord. - * @param targetX X target point (grid). - * @param targetY Y target point (grid). - * @param grid reference grid. - * @return The real distance or the current minDist if the point is - * out of the grid or empty. - */ - private static boolean collision(int x, int y, int targetX, int targetY, - BubbleSprite[][] grid) { - boolean collision = false; - - if ((targetX >= 0) && (targetX < LevelManager.NUM_COLS) && - (targetY >= 0) && (targetY < LevelManager.NUM_ROWS) && - grid[targetX][targetY] != null) { - int dx = (targetX << 5) - ((targetY % 2) << 4) - x; - int dy = targetY * 28 - y; - - collision = dx * dx + dy * dy < BubbleSprite.minDistance; - } - - return collision; - } - - /** - * Retrieves the set of positions in the grid that are currently under - * the moving ball. - * @param x real X-coord. - * @param y real Y-coord. - */ - private static void toCheck(int x, int y, int[][] toCheck) { - int topY = y / 28; - int topX = (x + ((topY % 2) << 4)) >> 5; - - toCheck[0][0] = topX; - toCheck[0][1] = topY; - toCheck[1][0] = topX + 1; - toCheck[1][1] = topY; - toCheck[2][0] = topX + 1 - (topY % 2); - toCheck[2][1] = topY + 1; - toCheck[3][1] = topY + 1; - if (((x & 16) ^ (((topY & 1) << 4))) == 0) { - toCheck[3][0] = topX - (topY % 2); - } else { - toCheck[3][0] = topX + 2 - (topY % 2); - } - } - - /** - * Check states of all bubbles. - * @param x X-coord of the new bubble. - * @param y Y-Coord of the new bubble. - * @param color Color of new new bubble. - * @param grid Grid of all known bubbles. - * @param outGrid Grid to store all the new states in. If the new - * bubble doesn't change anything, values are only potential. - */ - public static void checkState(int x, int y, int color, BubbleSprite[][] grid, - int[][] outGrid) { - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < LevelManager.NUM_ROWS; j++) { - outGrid[i][j] = STATE_UNDEFINED; - } - } - - outGrid[x][y] = STATE_REMOVE; - checkNeighbors(x, y, grid, outGrid, false); - int nbRemove = 1; - boolean changed = true; - while (changed) { - changed = false; - - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < LevelManager.NUM_ROWS; j++) { - if (outGrid[i][j] == STATE_CHECK_NEXT) { - if (isColor(i, j, color, grid, null)) { - outGrid[i][j] = STATE_REMOVE; - nbRemove++; - changed = true; - checkNeighbors(i, j, grid, outGrid, false); - } else { - outGrid[i][j] = STATE_INTERMEDIATE_CHECK; - } - } - } - } - } - - // Check for positions that are (potentially) not attached anymore - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - if (grid[i][0] != null && (outGrid[i][0] == STATE_UNDEFINED || - outGrid[i][0] == STATE_INTERMEDIATE_CHECK)) { - outGrid[i][0] = STATE_CHECK_NEXT; - } - } - - changed = true; - while (changed) { - changed = false; - - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < LevelManager.NUM_ROWS; j++) { - if (outGrid[i][j] == STATE_CHECK_NEXT) { - outGrid[i][j] = STATE_ATTACHED; - changed = true; - checkNeighbors(i, j, grid, outGrid, true); - } - } - } - } - - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < LevelManager.NUM_ROWS; j++) { - if ((grid[i][j] != null) && - ((outGrid[i][j] == STATE_UNDEFINED) || - (outGrid[i][j] == STATE_INTERMEDIATE_CHECK))) { - if (nbRemove >= 3) { - outGrid[i][j] = STATE_DETACHED; - } else { - outGrid[i][j] = STATE_POTENTIAL_DETACHED; - } - } - - if (outGrid[i][j] == STATE_REMOVE && (nbRemove < 3)) { - outGrid[i][j] = STATE_POTENTIAL_REMOVE; - } - } - } - } - - private static void checkNeighbors(int x, int y, BubbleSprite[][] grid, - int[][] outGrid, boolean ignoreStayState) { - - if (x > 0) { - changeState(x-1, y, grid, outGrid, ignoreStayState); - } - - if (x < (LevelManager.NUM_COLS - 1)) { - changeState(x+1, y, grid, outGrid, ignoreStayState); - } - - if (y > 0) { - changeState(x, y-1, grid, outGrid, ignoreStayState); - if (y % 2 == 0) { - if (x < (LevelManager.NUM_COLS - 1)) { - changeState(x+1, y-1, grid, outGrid, ignoreStayState); - } - } - else { - if (x > 0) { - changeState(x-1, y-1, grid, outGrid, ignoreStayState); - } - } - } - - if (y < (LevelManager.NUM_ROWS - 2)) { - changeState(x, y+1, grid, outGrid, ignoreStayState); - if (y % 2 == 0) { - if (x < (LevelManager.NUM_COLS - 1)) { - changeState(x+1, y+1, grid, outGrid, ignoreStayState); - } - } - else { - if (x > 0) { - changeState(x-1, y+1, grid, outGrid, ignoreStayState); - } - } - } - } - - private static void changeState(int x, int y, BubbleSprite[][] grid, - int[][] outGrid, boolean ignoreStayState) { - if (ignoreStayState) { - if (grid[x][y] != null && (outGrid[x][y] == STATE_UNDEFINED || - outGrid[x][y] == STATE_INTERMEDIATE_CHECK)) { - outGrid[x][y] = STATE_CHECK_NEXT; - } - } else { - if (grid[x][y] != null && outGrid[x][y] == STATE_UNDEFINED) { - outGrid[x][y] = STATE_CHECK_NEXT; - } - } - } - - /** - * Check if a specific position is of a given color - * @param x - * @param y - * @param color - * @param grid - * @param alreadyChecked - * @return - */ - private static boolean isColor(int x, int y, int color, - BubbleSprite[][] grid, - boolean[][] alreadyChecked) { - boolean isColor = false; - boolean checked = false; - - if (alreadyChecked != null) { - checked = alreadyChecked[x][y]; - } - - if (grid != null) { - if (grid[x][y] != null) { - if ((grid[x][y].getColor() == color) && - ((alreadyChecked == null) || !checked)) { - isColor = true; - if (alreadyChecked != null) { - alreadyChecked[x][y] = true; - } - } - } - } - - return isColor; - } -} diff --git a/src/org/gsanson/frozenbubble/Freile.java b/src/org/gsanson/frozenbubble/Freile.java deleted file mode 100644 index d0e53a0..0000000 --- a/src/org/gsanson/frozenbubble/Freile.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.gsanson.frozenbubble; - -import org.jfedor.frozenbubble.BubbleSprite; -import org.jfedor.frozenbubble.LevelManager; - -import android.view.KeyEvent; - -public class Freile implements Opponent, Runnable { - - /* Rotation of the launcher */ - public static final double LAUNCHER_ROTATION = 0.05; - /* Minimum angle for launcher */ - public static final double MIN_LAUNCHER = -Math.PI / 2. + 0.12; - /* Maximum angle for launcher */ - public static final double MAX_LAUNCHER = Math.PI / 2. - 0.12; - /* Ball speed */ - public static final double MOVE_SPEED = 3.; - - private static final int BONUS_POTENTIAL_DETACHED = 2; - private static final int BONUS_POTENTIAL_SAME_COLOR = 3; - private static final int BONUS_SAME_COLOR = 4; - private static final int BONUS_DETACHED = 6; - - /* Default option values */ - private static final int[][] BACKGROUND_GRID = - {{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - - //******************************************************************** - // Listener interface for various opponent events - //******************************************************************** - - /* - * Event types enumeration. - */ - public static enum eventEnum { - DONE_COMPUTING; - } - - /** - * Opponent event listener user set. - * @author Glenn Sanson - * - */ - public interface OpponentListener { - public abstract void onOpponentEvent(eventEnum event); - } - - OpponentListener mOpponentListener; - - public void setOpponentListener (OpponentListener ol) { - mOpponentListener = ol; - } - - /* Reference to the managed game grid */ - private BubbleSprite[][] grid; - /* Current color */ - private int color; - /* Next color */ - private int nextColor; - /* Current compressor level */ - private int compressor; - /* Swap launch bubble with next bubble? */ - private boolean colorSwap; - /* Calculating new position */ - private boolean computing; - /* Thread running flag */ - private boolean running; - /* Best direction */ - private double bestDirection; - /* Best location */ - private int[] bestLocation = {0, 0}; - /* Grid to compute best options */ - private int[][] gridOptions; - /* Grid to compute bubble states */ - private int[][] outGrid; - /* Neighbor bubble locations to check for collision */ - private int[][] toCheck = {{0, 0}, {0, 0}, {0, 0}, {0, 0}}; - - public Freile(BubbleSprite[][] grid) { - this.grid = grid; - gridOptions = new int[LevelManager.NUM_COLS][LevelManager.NUM_ROWS]; - outGrid = new int[LevelManager.NUM_COLS][LevelManager.NUM_ROWS]; - mOpponentListener = null; - running = true; - - new Thread(this).start(); - } - - public void compute(int currentColor, int nextColor, int compressor) { - this.color = currentColor; - this.nextColor = nextColor; - this.compressor = compressor; - computing = true; - - synchronized (this) { - notify(); - } - } - - private int computeOption(int posX, int posY, int color, - int[][] gridOptions, int[][] outGrid) { - if (gridOptions[posX][posY] == 0) { - int option = BACKGROUND_GRID[posX][posY]; - - CollisionHelper.checkState(posX, posY, color, grid, outGrid); - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < (LevelManager.NUM_ROWS - 1); j++) { - if (i != posX || j != posY) { - switch (outGrid[i][j]) { - case CollisionHelper.STATE_REMOVE: - option += BONUS_SAME_COLOR; - break; - case CollisionHelper.STATE_POTENTIAL_REMOVE: - option += BONUS_POTENTIAL_SAME_COLOR; - break; - case CollisionHelper.STATE_DETACHED: - option += BONUS_DETACHED; - break; - case CollisionHelper.STATE_POTENTIAL_DETACHED: - option += BONUS_POTENTIAL_DETACHED; - break; - } - } - } - } - gridOptions[posX][posY] = option; - } - return gridOptions[posX][posY]; - } - - public int getAction(double currentDirection) { - int direction = 0; - - /* - * If the flag is set to swap the current launch bubble with the - * next one, then return the appropriate action. - * - * If the angle error is less than a minimum acceptable threshold, - * cease aiming the launcher and fire the bubble. - * - * Otherwise, rotate the launcher to the appropriate firing angle. - */ - if (colorSwap) { - direction = KeyEvent.KEYCODE_DPAD_DOWN; - colorSwap = false; - } - else if (Math.abs(currentDirection - bestDirection) < 0.04) { - direction = KeyEvent.KEYCODE_DPAD_UP; - } else { - if (currentDirection < bestDirection) { - direction = KeyEvent.KEYCODE_DPAD_RIGHT; - } else { - direction = KeyEvent.KEYCODE_DPAD_LEFT; - } - } - return direction; - } - - public int[] getBubbleDestination() { - return bestLocation; - } - - private boolean getCollision(double direction, int[] position) { - boolean collision = false; - double posX = 112.; - double posY = 350. - compressor * 28.; - double speedX = MOVE_SPEED * Math.cos(direction - Math.PI / 2.); - double speedY = MOVE_SPEED * Math.sin(direction - Math.PI / 2.); - - while (!collision) { - posX += speedX; - posY += speedY; - - if (posX < 0.) { - posX = - posX; - speedX = -speedX; - } else if (posX > 224.) { - posX = 448. - posX; - speedX = -speedX; - } - - /* - * Check top collision. - */ - if (posY < 0.) { - int valX = (int) posX; - - collision = true; - position[0] = valX >> 5; - - if ((valX & 16) > 0) { - position[0]++; - } - - position[1] = 0; - } else { - /* - * Check other collision. - */ - collision = CollisionHelper.collide((int) posX, (int) posY, - grid, toCheck, position); - } - } - return collision; - } - - public double getExactDirection(double currentDirection) { - /* - * currentDirection is not used here. - */ - return bestDirection; - } - - /** - * Checks if work is still in progress. - * @return true if the calculation is not yet finished - */ - public boolean isComputing() { - return computing; - } - - public void run() { - while (running) { - if (computing) { - computing = false; - if (mOpponentListener != null) { - mOpponentListener.onOpponentEvent(eventEnum.DONE_COMPUTING); - } - } - - while (running && !computing) { - try { - synchronized(this) { - wait(1000); - } - } catch (InterruptedException e) { - // TODO - auto-generated exception handler stub. - //e.printStackTrace(); - } - } - - if (running) { - /* - * Initialize grid options. - */ - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < LevelManager.NUM_ROWS; j++) { - gridOptions[i][j] = 0; - } - } - - /* - * Check for best option. - */ - int bestOption = -1; - int newOption; - int[] position = {0, 0}; - - bestDirection = 0.; - bestLocation[0] = 0; - bestLocation[1] = 0; - colorSwap = false; - for (double direction = 0.; - direction < MAX_LAUNCHER; - direction += LAUNCHER_ROTATION) { - getCollision(direction, position); - newOption = computeOption(position[0], position[1], - color, gridOptions, outGrid); - if (newOption > bestOption) { - bestOption = newOption; - bestDirection = direction; - bestLocation[0] = position[0]; - bestLocation[1] = position[1]; - } - } - for (double direction = -LAUNCHER_ROTATION; - direction > MIN_LAUNCHER; - direction -= LAUNCHER_ROTATION) { - getCollision(direction, position); - newOption = computeOption(position[0], position[1], - color, gridOptions, outGrid); - if (newOption > bestOption) { - bestOption = newOption; - bestDirection = direction; - bestLocation[0] = position[0]; - bestLocation[1] = position[1]; - } - } - if (color != nextColor) { - for (double direction = 0.; - direction < MAX_LAUNCHER; - direction += LAUNCHER_ROTATION) { - getCollision(direction, position); - newOption = computeOption(position[0], position[1], - nextColor, gridOptions, outGrid); - if (newOption > bestOption) { - bestOption = newOption; - bestDirection = direction; - bestLocation[0] = position[0]; - bestLocation[1] = position[1]; - colorSwap = true; - } - } - for (double direction = -LAUNCHER_ROTATION; - direction > MIN_LAUNCHER; - direction -= LAUNCHER_ROTATION) { - getCollision(direction, position); - newOption = computeOption(position[0], position[1], - nextColor, gridOptions, outGrid); - if (newOption > bestOption) { - bestOption = newOption; - bestDirection = direction; - bestLocation[0] = position[0]; - bestLocation[1] = position[1]; - colorSwap = true; - } - } - } - } - } - gridOptions = null; - outGrid = null; - } - - /** - * Stop the thread run() execution. - *

This method will call notify() to resume the thread - * if it is suspended via wait(). - */ - public void stopThread() { - running = false; - mOpponentListener = null; - - synchronized(this) { - notify(); - } - } -} diff --git a/src/org/gsanson/frozenbubble/MalusBar.java b/src/org/gsanson/frozenbubble/MalusBar.java deleted file mode 100644 index 9e9a77b..0000000 --- a/src/org/gsanson/frozenbubble/MalusBar.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.gsanson.frozenbubble; - -import org.jfedor.frozenbubble.BmpWrap; -import org.jfedor.frozenbubble.LevelManager; -import org.jfedor.frozenbubble.Sprite; - -import android.graphics.Canvas; -import android.graphics.Rect; -import android.os.Bundle; - -public class MalusBar extends Sprite { - public final static int MAX_ATTACK = LevelManager.NUM_COLS - 1; - - /* X-pos for tomatoes */ - int minX; - /* Max Y-pos for bar */ - int maxY; - /* Number of waiting bubbles */ - int nbMalus; - /* Time to release bubbles */ - public int releaseTime; - /* Banana Image */ - private BmpWrap banana; - /* Tomato Image */ - private BmpWrap tomato; - /* Attack bubble array */ - public byte[] attackBubbles = { -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1 }; - - /** - * Manages a malus bar (bananas & tomatoes). - * @param coordX - X-coord of game facade. - * @param coordY - Y-coord of game facade. - * @param leftSide - if on left side (false => right side). - * @param tomato - image resource for a tomato. - * @param banana - image resource for a banana. - */ - public MalusBar(int coordX, int coordY, BmpWrap banana, BmpWrap tomato) { - super(new Rect(coordX, coordY, coordX + 33, coordY + 354)); - minX = coordX; - maxY = coordY + 354; - releaseTime = 0; - this.banana = banana; - this.tomato = tomato; - } - - @Override - public final void paint(Canvas c, double scale, int dx, int dy) { - int count = nbMalus; - int pos = maxY; - while (count >= MAX_ATTACK) { - pos -= 13; - drawImage(tomato, minX, pos, c, scale, dx, dy); - count -= MAX_ATTACK; - } - while (count > 0) { - pos -= 11; - drawImage(banana, minX + 3, pos, c, scale, dx, dy); - count--; - } - } - - public void addBubbles(int toAdd) { - if ((toAdd > 0) && (nbMalus == 0)) - releaseTime = 0; - nbMalus += toAdd; - } - - /** - * Clear the attack bubbles stored in the attack bubble array. - */ - public void clearAttackBubbles() { - for (int i = 0; i < LevelManager.LANES; i++) - this.attackBubbles[i] = -1; - } - - public int getAttackBarBubbles() { - return nbMalus; - } - - public int getTypeId() { - return Sprite.TYPE_IMAGE; - } - - /** - * The number of attack bubbles will be decremented by the supplied - * number of bubbles, which is the number of attack bubbles that were - * previously launched. - * @param remove - the number of attack bubbles to remove from the - * total number of attack bubbles. - */ - public void removeAttackBubbles(int remove) { - nbMalus -= remove; - - if (nbMalus < 0) - nbMalus = 0; - } - - public int removeLine() { - int nb = Math.min(MAX_ATTACK, nbMalus); - nbMalus -= nb; - return nb; - } - - public void restoreState(Bundle map, int id) { - nbMalus = map.getInt(String.format("%d-nbMalus", id)); - releaseTime = map.getInt(String.format("%d-releaseTime", id)); - } - - public void saveState(Bundle map, int id) { - map.putInt(String.format("%d-nbMalus", id), nbMalus); - map.putInt(String.format("%d-releaseTime", id), releaseTime); - } - - /** - * Set the value of an attack bubble color in the attack bubble array. - * @param bubbleIndex - the update index in the attack bubble array. - * @param bubbleColor - the attack bubble color. - */ - public void setAttackBubble(int bubbleIndex, int bubbleColor) { - this.attackBubbles[bubbleIndex] = (byte) bubbleColor; - } - - /** - * Set the total number of attack bubbles stored in the attack bar, - * as well as the array of current attack bubbles. - * @param numBubbles - the total number of attack bubbles. - * @param attackBubbles - the array of attack bubbles. - */ - public void setAttackBubbles(int numBubbles, byte[] attackBubbles) { - nbMalus = numBubbles; - - if (attackBubbles != null) - for (int i = 0; i < LevelManager.LANES; i++) - this.attackBubbles[i] = attackBubbles[i]; - } -} diff --git a/src/org/gsanson/frozenbubble/Opponent.java b/src/org/gsanson/frozenbubble/Opponent.java deleted file mode 100644 index 4ac35a3..0000000 --- a/src/org/gsanson/frozenbubble/Opponent.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.gsanson.frozenbubble; - -public interface Opponent { - /** - * Make any necessary computation before next turn - * @param currentColor - * @param nextColor - * @param compressor - */ - public void compute(int currentColor, int nextColor, int compressor); - - /** - * Get the action the CPU opponent wants to make (aim left, aim right, - * fire). - * @param currentDirection - * @return The action identifier of the next CPU action. - */ - public int getAction(double currentDirection); - - /** - * Get the final grid location of the next opponent bubble launch. - * @return The final grid location of the next opponent bubble launch. - */ - public int[] getBubbleDestination(); - - /** - * Get the exact direction (radian value) pointer should reach - * @param currentDirection - * @return - */ - public double getExactDirection(double currentDirection); - - /** - * Checks whether opponent has a control command awaiting - * @return - */ - public boolean isComputing(); -} diff --git a/src/org/jfedor/frozenbubble/BmpWrap.java b/src/org/jfedor/frozenbubble/BmpWrap.java deleted file mode 100644 index e60cb31..0000000 --- a/src/org/jfedor/frozenbubble/BmpWrap.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import android.graphics.Bitmap; - -// Various classes take arguments of this type during construction. We need -// one level of indirection in case we want to swap the images from under them -// (e.g., to resize them when the surface resolution changes.) We couldn't -// do it if references to Bitmap were kept directly everywhere since you can't -// overwrite an Android Bitmap in place (or at least I haven't found how to -// do it.) -public class BmpWrap { - BmpWrap(int id) { - this.id = id; - } - - public Bitmap bmp; - // Image id used for saving and restoring the image sprites. - public int id; -} diff --git a/src/org/jfedor/frozenbubble/BubbleFont.java b/src/org/jfedor/frozenbubble/BubbleFont.java deleted file mode 100644 index 05247ed..0000000 --- a/src/org/jfedor/frozenbubble/BubbleFont.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import android.graphics.Canvas; -import android.graphics.Rect; - -public class BubbleFont { - private char[] characters = { - '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', - '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', - '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', - '?', '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', - 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', - 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '|', '{', - '}', '[', ']', '^', '\\', '_', '~'}; - - private int[] position = { - 0, 9, 16, 31, 39, 54, 69, 73, 80, 88, 96, 116, 121, 131, - 137, 154, 165, 175, 187, 198, 210, 223, 234, 246, 259, - 271, 276, 282, 293, 313, 324, 336, 351, 360, 370, 381, - 390, 402, 411, 421, 435, 446, 459, 472, 483, 495, 508, - 517, 527, 538, 552, 565, 578, 589, 602, 616, 631, 645, - 663, 684, 700, 716, 732, 748, 764, 780, 796, 812 }; - - public int SEPARATOR_WIDTH = 1; - public int SPACE_CHAR_WIDTH = 6; - - private BmpWrap fontMap; - private Rect clipRect; - - public BubbleFont(BmpWrap fontMap) { - this.fontMap = fontMap; - clipRect = new Rect(); - } - - public final void print(String s, int x, int y, Canvas canvas, - double scale, int dx, int dy) { - int len = s.length(); - for (int i = 0; i < len; i++) { - char c = s.charAt(i); - x += paintChar(c, x, y, canvas, scale, dx, dy); - } - } - - public final int paintChar(char c, int x, int y, Canvas canvas, - double scale, int dx, int dy) { - if (c == ' ') { - return SPACE_CHAR_WIDTH + SEPARATOR_WIDTH; - } - int index = getCharIndex(c); - if (index == -1) { - return 0; - } - int imageWidth = position[index+1]-position[index]; - - clipRect.left = x; - clipRect.right = x + imageWidth; - clipRect.top = y; - clipRect.bottom = y + 22; - Sprite.drawImageClipped(fontMap, x - position[index], y, clipRect, - canvas, scale, dx, dy); - - return imageWidth + SEPARATOR_WIDTH; - } - - private final int getCharIndex(char c) { - for (int i=0 ; i - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import java.util.Random; - -import android.os.Bundle; - -public class BubbleManager { - int bubblesLeft; - BmpWrap[] bubbles; - int[] countBubbles; - - public BubbleManager(BmpWrap[] bubbles) { - this.bubbles = bubbles; - this.countBubbles = new int[bubbles.length]; - this.bubblesLeft = 0; - } - - public void saveState(Bundle map, int id) { - map.putInt(String.format("%d-BubbleManager-bubblesLeft", id), bubblesLeft); - map.putIntArray(String.format("%d-BubbleManager-countBubbles", id), - countBubbles); - } - - public void restoreState(Bundle map, int id) { - bubblesLeft = - map.getInt(String.format("%d-BubbleManager-bubblesLeft", id)); - countBubbles = - map.getIntArray(String.format("%d-BubbleManager-countBubbles", id)); - } - - public void addBubble(BmpWrap bubble) { - countBubbles[findBubble(bubble)]++; - bubblesLeft++; - } - - public void removeBubble(BmpWrap bubble) { - countBubbles[findBubble(bubble)]--; - bubblesLeft--; - } - - public int countBubbles() { - return bubblesLeft; - } - - public void initialize() { - for (int i=0 ; i - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import java.util.Vector; - -import android.graphics.Canvas; -import android.graphics.Point; -import android.graphics.Rect; -import android.os.Bundle; - -public class BubbleSprite extends Sprite { - public static final int MIN_PIX = 20; - public static final int MAX_PIX = 29; - public static double minDistance = MIN_PIX * MIN_PIX; - - private static final double FALL_SPEED = 1.; - private static final double MAX_BUBBLE_SPEED = 8.; - private static final double GO_UP_SPEED = 20.; - - private int color; - private int fixedAnim; - private BmpWrap bubbleFace; - private BmpWrap bubbleBlindFace; - private BmpWrap frozenFace; - private BmpWrap bubbleBlink; - private BmpWrap[] bubbleFixed; - private FrozenGame frozen; - private BubbleManager bubbleManager; - private SoundManager soundManager; - private double moveX, moveY; - private double realX, realY; - private Point lastOpenPosition; - - private boolean blink; - private boolean checkFall; - private boolean checkJump; - private boolean fixed; - private boolean released; - - /** - * Class constructor used when restoring the game state from a bundle. - */ - public BubbleSprite(Rect area, int color, double moveX, double moveY, - double realX, double realY, boolean fixed, boolean blink, - boolean released, boolean checkJump, boolean checkFall, - int fixedAnim, int scroll, int scrollMax, - BmpWrap bubbleFace, Point lastOpenPosition, - BmpWrap bubbleBlindFace, BmpWrap frozenFace, - BmpWrap[] bubbleFixed, BmpWrap bubbleBlink, - BubbleManager bubbleManager, SoundManager soundManager, - FrozenGame frozen) { - super(area); - - this.color = color; - this.moveX = moveX; - this.moveY = moveY; - this.realX = realX; - this.realY = realY; - this.fixed = fixed; - this.blink = blink; - this.released = released; - this.checkJump = checkJump; - this.checkFall = checkFall; - this.fixedAnim = fixedAnim; - this.bubbleFace = bubbleFace; - this.bubbleBlindFace = bubbleBlindFace; - this.frozenFace = frozenFace; - this.bubbleFixed = bubbleFixed; - this.bubbleBlink = bubbleBlink; - this.bubbleManager = bubbleManager; - this.soundManager = soundManager; - this.frozen = frozen; - this.lastOpenPosition = new Point(lastOpenPosition); - } - - /** - * Class constructor used when creating a launched bubble. - */ - public BubbleSprite(Rect area, double direction, int color, BmpWrap bubbleFace, - BmpWrap bubbleBlindFace, BmpWrap frozenFace, - BmpWrap[] bubbleFixed, BmpWrap bubbleBlink, - BubbleManager bubbleManager, SoundManager soundManager, - FrozenGame frozen) { - super(area); - - this.color = color; - this.bubbleFace = bubbleFace; - this.bubbleBlindFace = bubbleBlindFace; - this.frozenFace = frozenFace; - this.bubbleFixed = bubbleFixed; - this.bubbleBlink = bubbleBlink; - this.bubbleManager = bubbleManager; - this.soundManager = soundManager; - this.frozen = frozen; - this.moveX = MAX_BUBBLE_SPEED * -Math.cos(direction * Math.PI / 40.); - this.moveY = MAX_BUBBLE_SPEED * -Math.sin(direction * Math.PI / 40.); - this.realX = area.left; - this.realY = area.top; - this.lastOpenPosition = currentPosition(); - - fixed = false; - fixedAnim = -1; - } - - /** - * Class constructor used when initializing a new level. - */ - public BubbleSprite(Rect area, int color, BmpWrap bubbleFace, - BmpWrap bubbleBlindFace, BmpWrap frozenFace, - BmpWrap bubbleBlink, BubbleManager bubbleManager, - SoundManager soundManager, FrozenGame frozen) { - super(area); - - this.color = color; - this.bubbleFace = bubbleFace; - this.bubbleBlindFace = bubbleBlindFace; - this.frozenFace = frozenFace; - this.bubbleBlink = bubbleBlink; - this.bubbleManager = bubbleManager; - this.soundManager = soundManager; - this.frozen = frozen; - this.realX = area.left; - this.realY = area.top; - this.lastOpenPosition = currentPosition(); - - fixed = true; - fixedAnim = -1; - addToManager(); - } - - public void addToManager() { - bubbleManager.addBubble(bubbleFace); - } - - public void blink() { - blink = true; - } - - boolean checkCollision(Vector neighbors) { - for (int i=0 ; i v = this.getNeighbors(this.currentPosition()); - - for (int i=0 ; i jump, BmpWrap compare) { - if (checkJump) { - return; - } - - checkJump = true; - - if (this.bubbleFace == compare) { - checkJump(jump, this.getNeighbors(this.currentPosition())); - } - } - - void checkJump(Vector jump, Vector neighbors) { - jump.addElement(this); - - for (int i = 0; i < neighbors.size(); i++) { - BubbleSprite current = (BubbleSprite)neighbors.elementAt(i); - - if (current != null) { - current.checkJump(jump, this.bubbleFace); - } - } - } - - Point currentPosition() { - int rowOffset = frozen.getRowOffset(); - int posY = (int)Math.floor((realY-28.-frozen.getMoveDown())/28.); - int posX = (int)Math.floor((realX-174.)/32. + 0.5*((posY+rowOffset)%2)); - - if (posX > (LevelManager.NUM_COLS - 1)) { - posX = LevelManager.NUM_COLS - 1; - } - - if (posX < 0) { - posX = 0; - } - - if (posY > (LevelManager.NUM_ROWS - 1)) { - posY = LevelManager.NUM_ROWS - 1; - } - - if (posY < 0) { - posY = 0; - } - - return new Point(posX, posY); - } - - public int getColor() { - return this.color; - } - - public boolean fixed() { - return fixed; - } - - public void frozenify() { - changeSpriteArea(new Rect(getSpritePosition().x-1, - getSpritePosition().y-1, 34, 42)); - bubbleFace = frozenFace; - } - - Vector getNeighbors(Point p) { - BubbleSprite[][] grid = frozen.getGrid(); - Vector list = new Vector(); - - int rowOffset = frozen.getRowOffset(); - if (((p.y + rowOffset) % 2) == 0) { - if (p.x > 0) { - list.addElement(grid[p.x-1][p.y]); - } - - if (p.x < (LevelManager.NUM_COLS - 1)) { - list.addElement(grid[p.x+1][p.y]); - - if (p.y > 0) { - list.addElement(grid[p.x][p.y-1]); - list.addElement(grid[p.x+1][p.y-1]); - } - - if (p.y < (LevelManager.NUM_ROWS - 1)) { - list.addElement(grid[p.x][p.y+1]); - list.addElement(grid[p.x+1][p.y+1]); - } - } - else { - if (p.y > 0) { - list.addElement(grid[p.x][p.y-1]); - } - - if (p.y < (LevelManager.NUM_ROWS - 1)) { - list.addElement(grid[p.x][p.y+1]); - } - } - } - else { - if (p.x < (LevelManager.NUM_COLS - 1)) { - list.addElement(grid[p.x+1][p.y]); - } - - if (p.x > 0) { - list.addElement(grid[p.x-1][p.y]); - - if (p.y > 0) { - list.addElement(grid[p.x][p.y-1]); - list.addElement(grid[p.x-1][p.y-1]); - } - - if (p.y < (LevelManager.NUM_ROWS - 1)) { - list.addElement(grid[p.x][p.y+1]); - list.addElement(grid[p.x-1][p.y+1]); - } - } - else { - if (p.y > 0) { - list.addElement(grid[p.x][p.y-1]); - } - - if (p.y < (LevelManager.NUM_ROWS - 1)) { - list.addElement(grid[p.x][p.y+1]); - } - } - } - - return list; - } - - public int getTypeId() { - return Sprite.TYPE_BUBBLE; - } - - public void fall() { - if (fixed) { - moveY = frozen.getRandom().nextDouble()* 5.; - } - - fixed = false; - moveY += FALL_SPEED; - realY += moveY; - - super.absoluteMove(new Point((int)realX, (int)realY)); - - if (realY >= 680.) { - frozen.deleteFallingBubble(this); - } - } - - public void goUp() { - realX += moveX; - - if (realX>=414.) { - moveX = -moveX; - realX += (414. - realX); - } - else if (realX<=190.) { - moveX = -moveX; - realX += (190. - realX); - } - - moveY = -GO_UP_SPEED; - realY += moveY; - Point currentPosition = currentPosition(); - /* - * Only check for collisions if the current position of the attack - * bubble corresponds to a fixed grid location. Otherwise just move - * the bubble. - */ - if ((currentPosition.x >= 0) && - (currentPosition.x < LevelManager.NUM_COLS) && - (currentPosition.y >= 0) && - (currentPosition.y < LevelManager.NUM_ROWS)) { - BubbleSprite[][] grid = frozen.getGrid(); - - if (grid[currentPosition.x][currentPosition.y] == null) - lastOpenPosition = currentPosition; - - Vector neighbors = getNeighbors(lastOpenPosition); - - if (checkCollision(neighbors) || realY < 44.+frozen.getMoveDown()) { - realX = 190.+lastOpenPosition.x*32-(lastOpenPosition.y%2)*16; - realY = 44.+lastOpenPosition.y*28+frozen.getMoveDown(); - fixed = true; - super.absoluteMove(new Point((int)realX, (int)realY)); - - if (!this.register(grid, lastOpenPosition)) { - frozen.removeSprite(this); - frozen.malusBar.addBubbles(1); - } - else { - addToManager(); - moveX = 0.; - moveY = 0.; - fixedAnim = 0; - } - frozen.deleteGoingUpBubble(this); - return; - } - } - - super.absoluteMove(new Point((int)realX, (int)realY)); - } - - public void jump() { - if (fixed) { - moveX = -6. + frozen.getRandom().nextDouble() * 12.; - moveY = -5. - frozen.getRandom().nextDouble() * 10.; - fixed = false; - } - - moveY += FALL_SPEED; - realY += moveY; - realX += moveX; - - super.absoluteMove(new Point((int)realX, (int)realY)); - - if (realY >= 680.) { - frozen.deleteJumpingBubble(this); - } - } - - public void move() { - realX += moveX; - - if (realX>=414.) { - moveX = -moveX; - realX += (414. - realX); - soundManager.playSound(FrozenBubble.SOUND_REBOUND); - } - else if (realX<=190.) { - moveX = -moveX; - realX += (190. - realX); - soundManager.playSound(FrozenBubble.SOUND_REBOUND); - } - - realY += moveY; - Point currentPosition = currentPosition(); - BubbleSprite[][] grid = frozen.getGrid(); - - if (grid[currentPosition.x][currentPosition.y] == null) - lastOpenPosition = currentPosition; - - Vector neighbors = getNeighbors(lastOpenPosition); - - if (checkCollision(neighbors) || realY < 44.+frozen.getMoveDown()) { - int rowOffset = frozen.getRowOffset(); - realX = 190.+lastOpenPosition.x*32-((lastOpenPosition.y+rowOffset)%2)*16; - realY = 44.+lastOpenPosition.y*28+frozen.getMoveDown(); - fixed = true; - - Vector checkJump = new Vector(); - this.checkJump(checkJump, neighbors); - - if (checkJump.size() >= 3) { - released = true; - frozen.addAttackBubbles(checkJump.size() - 3); - - for (int i=0 ; i0) { - current.removeFromManager(); - } - - grid[currentPoint.x][currentPoint.y] = null; - } - - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - if (grid[i][0] != null) { - grid[i][0].checkFall(); - } - } - - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < (LevelManager.NUM_ROWS - 1); j++) { - if (grid[i][j] != null) { - if (!grid[i][j].checked()) { - frozen.addFallingBubble(grid[i][j]); - grid[i][j].removeFromManager(); - grid[i][j] = null; - } - } - } - } - - soundManager.playSound(FrozenBubble.SOUND_DESTROY); - } - else if (!this.register(grid, lastOpenPosition)) { - /* - * If the moving bubble failed to register because the grid - * location it would fill is already occupied, simply remove - * the sprite, but otherwise act like it became affixed. - */ - frozen.removeSprite(this); - soundManager.playSound(FrozenBubble.SOUND_STICK); - return; - } - else { - addToManager(); - moveX = 0.; - moveY = 0.; - fixedAnim = 0; - soundManager.playSound(FrozenBubble.SOUND_STICK); - } - } - - super.absoluteMove(new Point((int)realX, (int)realY)); - } - - public void moveDown() { - if (fixed) { - realY += 28.; - } - - super.absoluteMove(new Point((int)realX, (int)realY)); - } - - public final void paint(Canvas c, double scale, int dx, int dy) { - checkJump = false; - checkFall = false; - Point p = getSpritePosition(); - - if (blink && bubbleFace != frozenFace) { - blink = false; - drawImage(bubbleBlink, p.x, p.y, c, scale, dx, dy); - } - else { - if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL || - bubbleFace == frozenFace) { - drawImage(bubbleFace, p.x, p.y, c, scale, dx, dy); - } - else { - drawImage(bubbleBlindFace, p.x, p.y, c, scale, dx, dy); - } - } - - if (fixedAnim != -1) { - drawImage(bubbleFixed[fixedAnim], p.x, p.y, c, scale, dx, dy); - fixedAnim++; - - if (fixedAnim == 6) { - fixedAnim = -1; - } - } - } - - /** - * Adds a bubble to the fixed grid. - * @param grid - the array of fixed bubbles. - * @param position - the position in the grid to check for occupancy. - * @return true if the bubble becomes registered in the grid (false if - * another bubble already occupies the same position). - */ - public boolean register(BubbleSprite[][] grid, Point position) { - boolean register = grid[position.x][position.y] == null; - - if (register) - grid[position.x][position.y] = this; - - return register; - } - - public boolean released() { - return released; - } - - public void removeFromManager() { - bubbleManager.removeBubble(bubbleFace); - } - - public void saveState(Bundle map, Vector savedSprites, int id) { - if (getSavedId() != -1) { - return; - } - super.saveState(map, savedSprites, id); - map.putInt(String.format("%d-%d-color", id, getSavedId()), color); - map.putDouble(String.format("%d-%d-moveX", id, getSavedId()), moveX); - map.putDouble(String.format("%d-%d-moveY", id, getSavedId()), moveY); - map.putDouble(String.format("%d-%d-realX", id, getSavedId()), realX); - map.putDouble(String.format("%d-%d-realY", id, getSavedId()), realY); - map.putBoolean(String.format("%d-%d-fixed", id, getSavedId()), fixed); - map.putBoolean(String.format("%d-%d-blink", id, getSavedId()), blink); - map.putBoolean(String.format("%d-%d-released", id, getSavedId()), - released); - map.putBoolean(String.format("%d-%d-checkJump", id, getSavedId()), - checkJump); - map.putBoolean(String.format("%d-%d-checkFall", id, getSavedId()), - checkFall); - map.putInt(String.format("%d-%d-fixedAnim", id, getSavedId()), fixedAnim); - map.putBoolean(String.format("%d-%d-frozen", id, getSavedId()), - bubbleFace == frozenFace ? true : false); - map.putInt(String.format("%d-%d-lastOpenPosition.x", id, getSavedId()), - lastOpenPosition.x); - map.putInt(String.format("%d-%d-lastOpenPosition.y", id, getSavedId()), - lastOpenPosition.y); - } - - public void scroll(int moveDown) { - realY += 1.; - super.absoluteMove(new Point((int)realX, (int)realY)); - } - - public static void setCollisionThreshold(int collision) { - minDistance = collision * collision; - } -} diff --git a/src/org/jfedor/frozenbubble/Compressor.java b/src/org/jfedor/frozenbubble/Compressor.java deleted file mode 100644 index 3241679..0000000 --- a/src/org/jfedor/frozenbubble/Compressor.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import android.graphics.Canvas; -import android.os.Bundle; - -public class Compressor { - private static final int SCROLL_START = 6; - - private BmpWrap compressorHead; - private BmpWrap compressor; - private double moveDown; - private int scroll; - private int scrollMax; - private int steps; - - public Compressor(BmpWrap compressorHead, BmpWrap compressor) { - this.compressorHead = compressorHead; - this.compressor = compressor; - init(); - } - - public boolean checkScroll() { - if (scroll++ > scrollMax) { - scroll = 0; - moveDown += 1.; - } - return scroll == 0; - } - - public double getMoveDown() { - return moveDown; - } - - public int getSteps() { - return steps; - } - - public void init() { - moveDown = 0.; - scroll = 0; - scrollMax = SCROLL_START; - steps = 0; - } - - public void moveDown() { - moveDown += 28.; - steps++; - } - - public void moveDownSubtract(double subtract) { - moveDown -= subtract; - } - - public void paint(Canvas c, double scale, int dx, int dy) { - for (int i = 0; i < steps; i++) { - c.drawBitmap(compressor.bmp, - (float)(235 * scale + dx), - (float)((28 * i - 4) * scale + dy), null); - c.drawBitmap(compressor.bmp, - (float)(391 * scale + dx), - (float)((28 * i - 4) * scale + dy), null); - } - c.drawBitmap(compressorHead.bmp, - (float)(160 * scale + dx), - (float)((-7 + 28 * steps) * scale + dy), null); - } - - public void restoreState(Bundle map, int id) { - moveDown = map.getDouble(String.format("%d-compressor-moveDown", id)); - scroll = map.getInt(String.format("%d-compressor-scroll", id)); - scrollMax = map.getInt(String.format("%d-compressor-scrollMax", id)); - steps = map.getInt(String.format("%d-compressor-steps", id)); - } - - public void saveState(Bundle map, int id) { - map.putDouble(String.format("%d-compressor-moveDown", id), moveDown); - map.putInt(String.format("%d-compressor-scroll", id), scroll); - map.putInt(String.format("%d-compressor-scrollMax", id), scrollMax); - map.putInt(String.format("%d-compressor-steps", id), steps); - map.putInt(String.format("%d-compressor-steps", id), steps); - } -}; diff --git a/src/org/jfedor/frozenbubble/FrozenBubble.java b/src/org/jfedor/frozenbubble/FrozenBubble.java deleted file mode 100644 index 5be0c0c..0000000 --- a/src/org/jfedor/frozenbubble/FrozenBubble.java +++ /dev/null @@ -1,1270 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -/* - * This file is derived from the LunarLander.java file which is part of - * the Lunar Lander game included with Android documentation. The - * copyright notice for the Lunar Lander game is reproduced below. - */ - -/* - * Copyright (c) 2007 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jfedor.frozenbubble; - -import java.util.Random; - -import org.jfedor.frozenbubble.GameScreen.eventEnum; -import org.jfedor.frozenbubble.GameScreen.stateEnum; -import org.jfedor.frozenbubble.GameView.GameThread; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.ActivityInfo; -import android.hardware.SensorManager; -import android.media.AudioManager; -import android.net.Uri; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.util.DisplayMetrics; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.OrientationEventListener; -import android.view.Surface; -import android.view.Window; -import android.view.WindowManager; -import android.widget.Button; -import android.widget.Toast; - -import com.efortin.frozenbubble.AccelerometerManager; -import com.efortin.frozenbubble.HomeScreen; -import com.efortin.frozenbubble.ModPlayer; -import com.efortin.frozenbubble.Preferences; -import com.efortin.frozenbubble.PreferencesActivity; -import com.efortin.frozenbubble.ScrollingCredits; -import com.efortin.frozenbubble.VirtualInput; - -public class FrozenBubble extends Activity - implements GameView.GameListener, - AccelerometerManager.AccelerometerListener { - /* - * The following screen orientation definitions were added to - * ActivityInfo in API level 9. - */ - public final static int SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 6; - public final static int SCREEN_ORIENTATION_SENSOR_PORTRAIT = 7; - public final static int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8; - public final static int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9; - - public final static int SOUND_WON = 0; - public final static int SOUND_LOST = 1; - public final static int SOUND_LAUNCH = 2; - public final static int SOUND_DESTROY = 3; - public final static int SOUND_REBOUND = 4; - public final static int SOUND_STICK = 5; - public final static int SOUND_HURRY = 6; - public final static int SOUND_NEWROOT = 7; - public final static int SOUND_NOH = 8; - public final static int SOUND_WHIP = 9; - public final static int NUM_SOUNDS = 10; - - public final static int GAME_NORMAL = 0; - public final static int GAME_COLORBLIND = 1; - - public final static int MENU_COLORBLIND_ON = 1; - public final static int MENU_COLORBLIND_OFF = 2; - public final static int MENU_FULLSCREEN_ON = 3; - public final static int MENU_FULLSCREEN_OFF = 4; - public final static int MENU_SOUND_OPTIONS = 5; - public final static int MENU_DONT_RUSH_ME = 6; - public final static int MENU_RUSH_ME = 7; - public final static int MENU_NEW_GAME = 8; - public final static int MENU_ABOUT = 9; - public final static int MENU_EDITOR = 10; - public final static int MENU_TARGET_MODE = 11; - - public final static int AIM_TO_SHOOT = 0; - public final static int POINT_TO_SHOOT = 1; - public final static int ROTATE_TO_SHOOT = 2; - - public final static int LOCALE_LOCAL = 0; - public final static int LOCALE_WIFI = 1; - public final static int LOCALE_INTERNET = 2; - public final static int LOCALE_BLUETOOTH = 3; - - public final static int CPU = 0; - public final static int HUMAN = 1; - - public static boolean arcadeGame = false; - public static int gameLocale = LOCALE_LOCAL; - public static int myPlayerId = VirtualInput.PLAYER1; - public static int numPlayers = 0; - public static int opponentId = CPU; - - private static Preferences prefs = new Preferences(); - - public final static String PREFS_NAME = "frozenbubble"; - public final static String TAG = "FrozenBubble.java"; - public final static String EDITORACTION = "org.jfedor.frozenbubble.GAME"; - - private boolean activityCustomStarted = false; - private boolean allowUnpause = true; - private int currentOrientation; - private GameThread mGameThread = null; - private GameView mGameView = null; - private ModPlayer myModPlayer = null; - private OrientationEventListener myOrientationEventListener = null; - - private final int[] MODlist = { - R.raw.ambientpower, - R.raw.ambientlight, - R.raw.androidrupture, - R.raw.artificial, - R.raw.aftertherain, - R.raw.bluestars, - R.raw.chungababe, - R.raw.crystalhammer, - R.raw.dreamscope, - R.raw.freefall, - R.raw.gaeasawakening, - R.raw.homesick, - R.raw.ifcrystals, - R.raw.popcorn, - R.raw.stardustmemories, - R.raw.sunshineofthemorningsun, - R.raw.technostyleiii - }; - - /* - * Following are ancestor superclass overrides. - */ - - /* - * (non-Javadoc) - * @see android.app.Activity#onCreate(android.os.Bundle) - * This method is called when the activity is started. The activity - * may have been reconfigured or the system may have killed the - * process, after which it regained focus to invoke this method. - */ - @Override - public void onCreate(Bundle savedInstanceState) { - //if (savedInstanceState != null) - //{ - // Log.i(TAG, "FrozenBubble.onCreate(...)"); - //} - //else - //{ - // Log.i(TAG, "FrozenBubble.onCreate(null)"); - //} - super.onCreate(savedInstanceState); - setVolumeControlStream(AudioManager.STREAM_MUSIC); - requestWindowFeature(Window.FEATURE_NO_TITLE); - - /* - * Allow editor functionalities. - */ - Intent intent = getIntent(); - try { - if ((null == intent) || (null == intent.getExtras()) || - !intent.getExtras().containsKey("levels")) - startDefaultGame(intent, savedInstanceState); - else - startCustomGame(intent); - } catch (NullPointerException npe) { - startDefaultGame(intent, savedInstanceState); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - menu.add(0, MENU_COLORBLIND_ON, 0, R.string.menu_colorblind_on); - menu.add(0, MENU_COLORBLIND_OFF, 0, R.string.menu_colorblind_off); - menu.add(0, MENU_FULLSCREEN_ON, 0, R.string.menu_fullscreen_on); - menu.add(0, MENU_FULLSCREEN_OFF, 0, R.string.menu_fullscreen_off); - menu.add(0, MENU_SOUND_OPTIONS, 0, R.string.menu_sound_options); - menu.add(0, MENU_TARGET_MODE, 0, R.string.menu_target_mode); - menu.add(0, MENU_DONT_RUSH_ME, 0, R.string.menu_dont_rush_me); - menu.add(0, MENU_RUSH_ME, 0, R.string.menu_rush_me); - menu.add(0, MENU_ABOUT, 0, R.string.menu_about); - menu.add(0, MENU_NEW_GAME, 0, R.string.menu_new_game); - menu.add(0, MENU_EDITOR, 0, R.string.menu_editor); - return true; - } - - /** - * Invoked when the Activity is finishing or being destroyed by the - * system. - */ - @Override - protected void onDestroy() { - //Log.i(TAG, "FrozenBubble.onDestroy()"); - super.onDestroy(); - cleanUp(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - boolean handled = false; - if (keyCode == KeyEvent.KEYCODE_BACK) { - /* - * Only show the game exit dialog while a game is in progress, - * otherwise simply exit. - */ - if ((mGameThread != null) && mGameThread.gameInProgress()) { - exitGameDialog(); - } - else { - exit(true); - } - handled = true; - } - return handled || super.onKeyDown(keyCode, event); - } - - /* (non-Javadoc) - * @see android.app.Activity#onNewIntent(android.content.Intent) - */ - @Override - protected void onNewIntent(Intent intent) { - if (null != intent) { - if (EDITORACTION.equals(intent.getAction())) { - cleanUpGameView(); - startCustomGame(intent); - } - else if ((numPlayers != 0) && intent.hasExtra("numPlayers")) { - int newNumPlayers = intent.getIntExtra("numPlayers", 1); - - if (newNumPlayers != numPlayers) { - cleanUpGameView(); - startDefaultGame(intent, null); - } - } - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - boolean prefsUpdated = false; - - switch (item.getItemId()) { - case MENU_NEW_GAME: - newGameDialog(); - return true; - case MENU_COLORBLIND_ON: - prefs.colorMode = true; - prefs.gameMode = GAME_COLORBLIND; - prefsUpdated = true; - break; - case MENU_COLORBLIND_OFF: - prefs.colorMode = false; - prefs.gameMode = GAME_NORMAL; - prefsUpdated = true; - break; - case MENU_FULLSCREEN_ON: - prefs.fullscreen = true; - setFullscreen(); - prefsUpdated = true; - break; - case MENU_FULLSCREEN_OFF: - prefs.fullscreen = false; - setFullscreen(); - prefsUpdated = true; - break; - case MENU_SOUND_OPTIONS: - soundOptionsDialog(); - return true; - case MENU_ABOUT: - if (mGameThread != null) - mGameThread.setState(stateEnum.ABOUT); - return true; - case MENU_TARGET_MODE: - targetOptionsDialog(); - return true; - case MENU_DONT_RUSH_ME: - prefs.dontRushMe = true; - prefsUpdated = true; - break; - case MENU_RUSH_ME: - prefs.dontRushMe = false; - prefsUpdated = true; - break; - case MENU_EDITOR: - startEditor(); - return true; - } - - if (prefsUpdated) { - SharedPreferences sp = - PreferenceManager.getDefaultSharedPreferences(this); - PreferencesActivity.saveDefaultPreferences(prefs, sp); - } - - return prefsUpdated; - } - - @Override - public void onOptionsMenuClosed(Menu menu) { - super.onOptionsMenuClosed(menu); - allowUnpause = true; - } - - /** - * Invoked when the Activity loses user focus. - */ - @Override - protected void onPause() { - //Log.i(TAG, "FrozenBubble.onPause()"); - super.onPause(); - pause(); - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); - allowUnpause = false; - menu.findItem(MENU_COLORBLIND_ON ).setVisible(prefs.gameMode == GAME_NORMAL); - menu.findItem(MENU_COLORBLIND_OFF).setVisible(prefs.gameMode != GAME_NORMAL); - menu.findItem(MENU_FULLSCREEN_ON ).setVisible(!prefs.fullscreen); - menu.findItem(MENU_FULLSCREEN_OFF).setVisible(prefs.fullscreen); - menu.findItem(MENU_SOUND_OPTIONS ).setVisible(true); - menu.findItem(MENU_TARGET_MODE ).setVisible(true); - menu.findItem(MENU_DONT_RUSH_ME ).setVisible(!prefs.dontRushMe); - menu.findItem(MENU_RUSH_ME ).setVisible(prefs.dontRushMe); - return true; - } - - /** - * Notification that something is about to happen, to give the - * Activity a chance to save state. - * @param outState - A Bundle into which this Activity should save its - * state. - */ - @Override - protected void onSaveInstanceState(Bundle outState) { - //Log.i(TAG, "FrozenBubble.onSaveInstanceState()"); - /* - * Just have the View's thread save its state into our Bundle. - */ - super.onSaveInstanceState(outState); - saveState(); - - if (mGameThread != null) - mGameThread.saveState(outState); - } - - @Override - public void onWindowFocusChanged (boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - allowUnpause = hasFocus; - } - - /* - * The following methods are used to retrieve and set the volatile - * memory game options variables. They are all static, so are - * available to all activities within this application while the - * application is running. - */ - - public static boolean getAimThenShoot() { - return (prefs.targetMode == AIM_TO_SHOOT) || (prefs.targetMode == ROTATE_TO_SHOOT); - } - - public static int getBluetooth() { - return prefs.bluetooth; - } - - public static void setBluetooth(int newBluetooth) { - prefs.bluetooth = newBluetooth; - } - - public static int getCollision() { - return prefs.collision; - } - - public static void setCollision(int newCollision) { - prefs.collision = newCollision; - BubbleSprite.setCollisionThreshold(prefs.collision); - } - - public static boolean getCompressor() { - return prefs.compressor; - } - - public static void setCompressor(boolean newCompressor) { - prefs.compressor = newCompressor; - } - - public static int getDifficulty() { - return prefs.difficulty; - } - - public static void setDifficulty(int newDifficulty) { - prefs.difficulty = newDifficulty; - } - - public static boolean getDontRushMe() { - return prefs.dontRushMe; - } - - public static void setDontRushMe(boolean dont) { - prefs.dontRushMe = dont; - } - - public static boolean getFullscreen() { - return prefs.fullscreen; - } - - public static void setFullscreen(boolean newFullscreen) { - prefs.fullscreen = newFullscreen; - } - - public static int getMode() { - return prefs.gameMode; - } - - public static void setMode(int newMode) { - prefs.gameMode = newMode; - } - - public static boolean getMusicOn() { - return prefs.musicOn; - } - - public static void setMusicOn(boolean mo) { - prefs.musicOn = mo; - } - - public static boolean getSoundOn() { - return prefs.soundOn; - } - - public static void setSoundOn(boolean so) { - prefs.soundOn = so; - } - - public static int getTargetMode() { - return prefs.targetMode; - } - - public static void setTargetMode(int tm) { - prefs.targetMode = tm; - } - - /* - * Following are general utility functions. - */ - - /** - * Perform activity cleanup. This must only be called when the - * activity is being destroyed. - */ - public void cleanUp() { - /* - * The current game is being destroyed, so reset the static game - * state variables. - */ - arcadeGame = false; - gameLocale = LOCALE_LOCAL; - myPlayerId = VirtualInput.PLAYER1; - numPlayers = 0; - opponentId = CPU; - - if (AccelerometerManager.isListening()) - AccelerometerManager.stopListening(); - - if (myOrientationEventListener != null) { - myOrientationEventListener.disable(); - } - myOrientationEventListener = null; - - cleanUpGameView(); - - if (myModPlayer != null) { - myModPlayer.destroyMusicPlayer(); - } - myModPlayer = null; - } - - private void cleanUpGameView() { - mGameThread = null; - if (mGameView != null) { - mGameView.cleanUp(); - } - mGameView = null; - } - - private void exit(boolean goToHomeScreen) { - /* - * Preserve game information and perform activity cleanup. - */ - pause(); - if (mGameThread != null) - mGameThread.setRunning(false); - cleanUp(); - /* - * Clear the flag indicating that the system passed us a bundle to - * save the game state. - */ - SharedPreferences.Editor editor = - PreferenceManager.getDefaultSharedPreferences(this).edit(); - editor.putBoolean("systemSave", false); - editor.commit(); - /* - * Create an intent to launch the home screen. - */ - if (goToHomeScreen) { - Intent intent = new Intent(this, HomeScreen.class); - intent.putExtra("startHomeScreen", true); - startActivity(intent); - } - /* - * Finish the current activity. - */ - finish(); - } - - private void exitGameDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(FrozenBubble.this); - /* - * Set the dialog title. - */ - builder.setTitle(R.string.exit) - /* - * Set the action buttons. - */ - .setPositiveButton(R.string.exit, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - // User clicked OK. Quit. - exit(true); - } - }) - .setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - // User canceled. Do nothing. - if (mGameThread != null) { - mGameThread.resumeGame(); - } - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - // User clicked Cancel. Do nothing. - if (mGameThread != null) { - mGameThread.resumeGame(); - } - } - }); - AlertDialog alert = builder.create(); - alert.show(); - Button btn1 = alert.getButton(DialogInterface.BUTTON_NEGATIVE); - btn1.setTextSize(18); - Button btn2 = alert.getButton(DialogInterface.BUTTON_NEUTRAL); - btn2.setTextSize(18); - Button btn3 = alert.getButton(DialogInterface.BUTTON_POSITIVE); - btn3.setTextSize(18); - } - - /** - * Obtain the screen orientation. - * @param windowManager - used to get a reference to the display to - * obtain display information. - * @return The screen orientation, which can be among the following - * values:
- * ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
- * ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
- * FrozenBubble.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
- * FrozenBubble.SCREEN_ORIENTATION_REVERSE_PORTRAIT
- */ - public static int getScreenOrientation(WindowManager windowManager) { - /* - * The method getOrientation() was deprecated in API level 8. - * - * For API level 8 or greater, use getRotation(). - */ - int rotation = windowManager.getDefaultDisplay().getOrientation(); - DisplayMetrics dm = new DisplayMetrics(); - windowManager.getDefaultDisplay().getMetrics(dm); - int width = dm.widthPixels; - int height = dm.heightPixels; - int orientation; - /* - * The orientation determination is based on the natural orienation - * mode of the device, which can be either portrait, landscape, or - * square. - * - * After the natural orientation is determined, convert the device - * rotation into a fully qualified orientation. - */ - if ((((rotation == Surface.ROTATION_0 ) || - (rotation == Surface.ROTATION_180)) && (height > width)) || - (((rotation == Surface.ROTATION_90 ) || - (rotation == Surface.ROTATION_270)) && (width > height))) { - /* - * Natural orientation is portrait. - */ - switch(rotation) { - case Surface.ROTATION_0: - orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; - break; - case Surface.ROTATION_90: - orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; - break; - case Surface.ROTATION_180: - orientation = SCREEN_ORIENTATION_REVERSE_PORTRAIT; - break; - case Surface.ROTATION_270: - orientation = SCREEN_ORIENTATION_REVERSE_LANDSCAPE; - break; - default: - orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; - break; - } - } - else { - /* - * Natural orientation is landscape or square. - */ - switch(rotation) { - case Surface.ROTATION_0: - orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; - break; - case Surface.ROTATION_90: - orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; - break; - case Surface.ROTATION_180: - orientation = SCREEN_ORIENTATION_REVERSE_LANDSCAPE; - break; - case Surface.ROTATION_270: - orientation = SCREEN_ORIENTATION_REVERSE_PORTRAIT; - break; - default: - orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; - break; - } - } - - return orientation; - } - - /** - * Restore the game options from the saved preferences, and register - * the device orientation listener to detect orientation changes. - */ - private void initGameOptions() { - restoreGamePrefs(); - - currentOrientation = getScreenOrientation(getWindowManager()); - myOrientationEventListener = - new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) { - @Override - public void onOrientationChanged(int arg0) { - currentOrientation = getScreenOrientation(getWindowManager()); - } - }; - if (myOrientationEventListener.canDetectOrientation()) - myOrientationEventListener.enable(); - } - - /** - * Start a new game and music player. - */ - public void newGame() { - if (mGameThread != null) { - mGameThread.newGame(true); - } - - playMusic(false); - } - - private void newGameDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(FrozenBubble.this); - /* - * Set the dialog title. - */ - builder.setTitle(R.string.menu_new_game) - /* - * Set the action buttons. - */ - .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - // User clicked OK. Start a new game. - newGame(); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - // User clicked Cancel. Do nothing. - } - }); - builder.create(); - builder.show(); - } - - public void onAccelerationChanged(float x, float y, float z) { - if (mGameThread != null) { - if (numPlayers > 1) { - if (currentOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) - x = -y; - else if (currentOrientation == SCREEN_ORIENTATION_REVERSE_LANDSCAPE) - x = y; - else if (currentOrientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT) - x = -x; - } - else if (currentOrientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT) { - x = -x; - } - mGameThread.setPosition(20.0f+x*2.0f); - } - } - - public void onGameEvent(eventEnum event) { - switch (event) { - case GAME_WON: - break; - - case GAME_LOST: - break; - - case GAME_PAUSED: - saveState(); - - if (myModPlayer != null) - myModPlayer.pausePlay(); - break; - - case GAME_RESUME: - if (myModPlayer == null) - playMusic(true); - else if (allowUnpause) - myModPlayer.unPausePlay(); - break; - - case LEVEL_START: - if (!arcadeGame && (mGameView != null) && (mGameThread != null) && - (numPlayers == 1)) { - if (mGameThread.getCurrentLevelIndex() == 0) { - /* - * Destroy the current music player, which will free audio - * stream resources and allow the system to use them. - */ - if (myModPlayer != null) - myModPlayer.destroyMusicPlayer(); - myModPlayer = null; - /* - * Clear the game screen and suspend input processing for - * three seconds. - * - * Afterwards, the "About" screen will be displayed as a - * backup just in case anything goes awry with displaying - * the end-of-game credits. It will be displayed after the - * user touches the screen when the credits are finished. - */ - mGameView.clearGameScreen(true, 3000); - /* - * Create an intent to launch the activity to display the - * credits screen. - */ - Intent intent = new Intent(this, ScrollingCredits.class); - startActivity(intent); - break; - } - } - playMusic(true); - break; - - default: - break; - } - } - - /** - * Pause the game. - */ - private void pause() { - if (mGameThread != null) - mGameThread.pause(); - - /* - * Pause the MOD player. - */ - if (myModPlayer != null) - myModPlayer.pausePlay(); - } - - /** - * This function determines whether a music player instance needs to - * be created or if one already exists. Then, based on the current - * level, the song to play is calculated and loaded. If desired, the - * song will start playing immediately, or it can remain paused. - * @param startPlaying - If true, the song starts playing - * immediately. Otherwise it is paused and must be unpaused to start - * playing. - */ - private void playMusic(boolean startPlaying) - { - int modNow; - /* - * Ascertain which song to play. For a single player game, the song - * is based on the current level. For an arcade game, a two player - * game, or if the game thread has been destroyed, the song is - * selected at random. - */ - if (!arcadeGame && (mGameThread != null) && (numPlayers == 1)) { - modNow = mGameThread.getCurrentLevelIndex() % MODlist.length; - } - else - { - Random rand = new Random(); - modNow = rand.nextInt(MODlist.length - 1); - } - /* - * Determine whether to create a music player or load the song. - */ - if (myModPlayer == null) { - myModPlayer = new ModPlayer(this, MODlist[modNow], - getMusicOn(), !startPlaying); - } - else { - myModPlayer.loadNewSong(MODlist[modNow], startPlaying); - } - allowUnpause = true; - } - - /** - * Load the game options from the saved shared preferences. - */ - private void restoreGamePrefs() { - SharedPreferences sp = - PreferenceManager.getDefaultSharedPreferences(this); - prefs = PreferencesActivity.getDefaultPrefs(sp); - - /* - * Some game options require additional handling to fully implement - * changes to game play. - */ - BubbleSprite.setCollisionThreshold(prefs.collision); - setTargetModeOrientation(); - } - - /** - * Save critically important game information. - */ - public void saveState() { - if (!arcadeGame && (mGameThread != null) && (numPlayers == 1)) { - /* - * Allow level editor functionalities. - */ - SharedPreferences sp = getSharedPreferences(PREFS_NAME, - Context.MODE_PRIVATE); - SharedPreferences.Editor editor = sp.edit(); - /* - * If the game wasn't launched from the level editor, save the - * last level played. - */ - Intent i = getIntent(); - if ((null == i) || !activityCustomStarted) { - editor.putInt("level", mGameThread.getCurrentLevelIndex()); - } - else { - /* - * The level editor's intent is running. - */ - editor.putInt("levelCustom", mGameThread.getCurrentLevelIndex()); - } - editor.commit(); - } - } - - private void setFullscreen() { - final int flagFs = WindowManager.LayoutParams.FLAG_FULLSCREEN; - final int flagNoFs = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN; - - if (prefs.fullscreen) { - getWindow().addFlags(flagFs); - getWindow().clearFlags(flagNoFs); - } - else { - getWindow().clearFlags(flagFs); - getWindow().addFlags(flagNoFs); - } - - if (mGameView != null) - mGameView.requestLayout(); - } - - private void setTargetModeOrientation() { - if ((prefs.targetMode == ROTATE_TO_SHOOT) && - AccelerometerManager.isSupported(getApplicationContext())) { - AccelerometerManager.startListening(getApplicationContext(),this); - /* - * In API level 9, SCREEN_ORIENTATION_SENSOR_PORTRAIT and - * SCREEN_ORIENTATION_SENSOR_LANDSCAPE were added to ActivityInfo. - * This application is developed in API level 4, but using these - * values will be supported correctly in devices with a native API - * level that implements this functionality. - * - * These modes allow the device to display the screen in either - * normal or reverse portrait mode based on the device orientation - * reported by the accelerometer hardware. - * - * For multiplayer games using rotate to shoot, set the - * orientation to sensor landscape, and for single player games, - * set the orientation to sensor portrait. - */ - if (numPlayers > 1) { - setRequestedOrientation(SCREEN_ORIENTATION_SENSOR_LANDSCAPE); - } - else { - setRequestedOrientation(SCREEN_ORIENTATION_SENSOR_PORTRAIT); - } - } - - if ((prefs.targetMode != ROTATE_TO_SHOOT) && - AccelerometerManager.isListening()) { - AccelerometerManager.stopListening(); - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); - } - } - - private void soundOptionsDialog() { - boolean isCheckedItem[] = {getSoundOn(), getMusicOn()}; - - AlertDialog.Builder builder = new AlertDialog.Builder(FrozenBubble.this); - /* - * Set the dialog title. - */ - builder.setTitle(R.string.menu_sound_options) - /* - * Specify the list array, the items to be selected by default (null - * for none), and the listener through which to receive callbacks - * when items are selected. - */ - .setMultiChoiceItems(R.array.sound_options_array, isCheckedItem, - new DialogInterface.OnMultiChoiceClickListener() { - @Override - public void onClick(DialogInterface dialog, int which, boolean isChecked) { - boolean prefsUpdated = false; - - switch (which) { - case 0: - setSoundOn(isChecked); - prefsUpdated = true; - break; - case 1: - setMusicOn(isChecked); - if (myModPlayer != null) { - myModPlayer.setMusicOn(isChecked); - } - prefsUpdated = true; - break; - } - - if (prefsUpdated) { - SharedPreferences sp = - PreferenceManager.getDefaultSharedPreferences(getApplication()); - PreferencesActivity.saveDefaultPreferences(prefs, sp); - } - } - }) - /* - * Set the action buttons. - */ - .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - // User clicked OK. - } - }); - builder.create(); - builder.show(); - } - - /** - * Update the game preferences to the desired values. - * @param prefs - the desired game preferences. - */ - public static void setPrefs(Preferences prefs) { - FrozenBubble.setBluetooth (prefs.bluetooth ); - FrozenBubble.setCollision (prefs.collision ); - FrozenBubble.setMode (prefs.gameMode ); - FrozenBubble.setCompressor(prefs.compressor); - FrozenBubble.setDifficulty(prefs.difficulty); - FrozenBubble.setDontRushMe(prefs.dontRushMe); - FrozenBubble.setFullscreen(prefs.fullscreen); - FrozenBubble.setMusicOn (prefs.musicOn ); - FrozenBubble.setSoundOn (prefs.soundOn ); - FrozenBubble.setTargetMode(prefs.targetMode); - } - - /** - * Method to start a game using levels from the level editor. - *

If the level isn't specified from the editor, then the player - * selected the option to continue playing from the last level - * played, so use the last level played instead. - * @param intent - The intent from the level editor used to start this - * activity, which contains the custom level data. - */ - private void startCustomGame(Intent intent) { - activityCustomStarted = true; - numPlayers = 1; - initGameOptions(); - /* - * Get custom level last played. - */ - SharedPreferences sp = getSharedPreferences(PREFS_NAME, - Context.MODE_PRIVATE); - int startingLevel = sp .getInt ("levelCustom", 0); - int startingLevelIntent = intent.getIntExtra("startingLevel", -2); - startingLevel = - (startingLevelIntent == -2) ? startingLevel : startingLevelIntent; - mGameView = new GameView(this, - intent.getExtras().getByteArray("levels"), - startingLevel); - setContentView(mGameView); - mGameView.setGameListener(this); - mGameThread = mGameView.getThread(); - mGameView.requestFocus(); - setFullscreen(); - playMusic(false); - } - - /** - * Method to start a game using default levels, if single player game - * mode was selected. - *

This method is also used to start a multiplayer game. - * @param intent - The intent used to start this activity. - * @param savedInstanceState - the bundle of saved state information. - */ - private void startDefaultGame(Intent intent, Bundle savedInstanceState) { - /* - * Initialize the flag to denote this game uses default levels. - */ - activityCustomStarted = false; - /* - * Check if this is a single player or multiplayer game. - */ - arcadeGame = false; - gameLocale = LOCALE_LOCAL; - myPlayerId = VirtualInput.PLAYER1; - numPlayers = 1; - opponentId = CPU; - if (intent != null) { - if (intent.hasExtra("myPlayerId")) - myPlayerId = intent.getIntExtra("myPlayerId", VirtualInput.PLAYER1); - if (intent.hasExtra("numPlayers")) - numPlayers = intent.getIntExtra("numPlayers", 1); - if (intent.hasExtra("opponentId")) - opponentId = intent.getIntExtra("opponentId", CPU); - if (intent.hasExtra("gameLocale")) - gameLocale = intent.getIntExtra("gameLocale", LOCALE_LOCAL); - if (intent.hasExtra("arcadeGame")) - arcadeGame = intent.getBooleanExtra("arcadeGame", false); - } - initGameOptions(); - /* - * If there is more than one player, launch a multiplayer game. - * Otherwise start a single player game. - */ - if (numPlayers > 1) { - mGameView = new GameView(this, - numPlayers, - myPlayerId, - opponentId, - gameLocale, - arcadeGame); - setContentView(mGameView); - mGameView.setGameListener(this); - mGameThread = mGameView.getThread(); - /* - * Only restore the bundle for a multiplayer game if it was local. - */ - if ((savedInstanceState != null) && (gameLocale == LOCALE_LOCAL)) { - int savedPlayers = savedInstanceState.getInt("numPlayers"); - if (savedPlayers == 2) { - mGameThread.restoreState(savedInstanceState); - } - } - mGameView.requestFocus(); - } - else { - setContentView(R.layout.activity_frozen_bubble); - mGameView = (GameView)findViewById(R.id.game); - mGameView.setGameListener(this); - mGameThread = mGameView.getThread(); - if (savedInstanceState != null) { - int savedPlayers = savedInstanceState.getInt("numPlayers"); - if (savedPlayers == 1) - mGameThread.restoreState(savedInstanceState); - } - mGameView.requestFocus(); - } - setFullscreen(); - playMusic(false); - } - - /** - * Starts editor / market with editor's download. - */ - private void startEditor() { - Intent i = new Intent(); - /* - * First try to run the plus version of the level editor. - */ - i.setClassName("sk.halmi.fbeditplus", - "sk.halmi.fbeditplus.EditorActivity"); - try { - startActivity(i); - finish(); - } catch (ActivityNotFoundException e) { - /* - * If not found, try to run the normal version. - */ - i.setClassName("sk.halmi.fbedit", - "sk.halmi.fbedit.EditorActivity"); - try { - startActivity(i); - finish(); - } catch (ActivityNotFoundException ex) { - /* - * If the user doesn't have the Frozen Bubble Level Editor, take - * him to the application market. - */ - try { - Toast.makeText(getApplicationContext(), - R.string.install_editor, Toast.LENGTH_SHORT).show(); - i = new Intent(Intent.ACTION_VIEW, - Uri.parse( - "market://search?q=frozen bubble level editor")); - startActivity(i); - } catch (Exception exc) { - /* - * Damn, you don't have market? - */ - Toast.makeText(getApplicationContext(), - R.string.market_missing, Toast.LENGTH_SHORT).show(); - } - } - } - } - - private void targetOptionsDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(FrozenBubble.this); - /* - * Set the dialog title. - */ - builder.setTitle(R.string.menu_target_mode) - /* - * Specify the list array, the item to be selected by default, and - * the listener through which to receive callbacks when the item is - * selected. - */ - .setSingleChoiceItems(R.array.shoot_mode_array, prefs.targetMode, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface builder, int which) { - switch (which) { - case 0: - setTargetMode(AIM_TO_SHOOT); - break; - case 1: - setTargetMode(POINT_TO_SHOOT); - break; - case 2: - setTargetMode(ROTATE_TO_SHOOT); - break; - } - setTargetModeOrientation(); - } - }) - /* - * Set the action buttons. - */ - .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface builder, int id) { - // User clicked OK. - SharedPreferences sp = - PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - PreferencesActivity.saveDefaultPreferences(prefs, sp); - } - }); - - builder.create(); - builder.show(); - } -} diff --git a/src/org/jfedor/frozenbubble/FrozenGame.java b/src/org/jfedor/frozenbubble/FrozenGame.java deleted file mode 100644 index 6131b76..0000000 --- a/src/org/jfedor/frozenbubble/FrozenGame.java +++ /dev/null @@ -1,1565 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import java.util.Random; -import java.util.Vector; - -import org.gsanson.frozenbubble.MalusBar; - -import android.graphics.Canvas; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.util.Log; - -import com.efortin.frozenbubble.CRC16; -import com.efortin.frozenbubble.HighscoreManager; -import com.efortin.frozenbubble.NetworkManager; -import com.efortin.frozenbubble.VirtualInput; - -public class FrozenGame extends GameScreen { - private final int[] columnX = {190, 206, 222, 238, 254, - 270, 286, 302, 318, 334, - 350, 366, 382, 398, 414}; - - public final static int HORIZONTAL_MOVE = 0; - public final static int FIRE = 1; - - public final static double MIN_LAUNCH_DIRECTION = 1.0; - public final static double START_LAUNCH_DIRECTION = 20.0; - public final static double MAX_LAUNCH_DIRECTION = 39.0; - - public final static int KEY_UP = 38; - public final static int KEY_LEFT = 37; - public final static int KEY_RIGHT = 39; - public final static int KEY_SHIFT = 16; - - public static final int HURRY_ME_TIME = 480; - public static final int RELEASE_TIME = 300; - - BmpWrap background; - BmpWrap[] bubbles; - BmpWrap[] bubblesBlind; - BmpWrap[] frozenBubbles; - BmpWrap[] targetedBubbles; - Random random; - - LaunchBubbleSprite launchBubble; - double launchBubblePosition; - - PenguinSprite penguin; - Compressor compressor; - - ImageSprite nextBubble; - int currentColor, nextColor, newNextColor; - - BubbleSprite movingBubble; - BubbleManager bubbleManager; - LevelManager levelManager; - MalusBar malusBar; - HighscoreManager highscoreManager; - NetworkManager networkManager; - - Vector falling; - Vector goingUp; - Vector jumping; - - BubbleSprite[][] bubblePlay; - BubbleSprite[] scrolling; - - BmpWrap gameWon, gameLost; - - BmpWrap bubbleBlink; - int blinkDelay; - - ImageSprite hurrySprite; - int hurryTime; - - ImageSprite pauseButtonSprite; - ImageSprite playButtonSprite; - ImageSprite pausedSprite; - - SoundManager soundManager; - - boolean endOfGame; - boolean frozenify; - boolean isArcade; - boolean isRemote; - boolean readyToFire; - boolean swapPressed; - gameEnum playResult; - short gridChecksum; - int fixedBubbles; - int frozenifyX, frozenifyY; - int nbBubbles; - int player; - int sendToOpponent; - - Drawable launcher; - BmpWrap penguins; - - public FrozenGame(BmpWrap background_arg, - BmpWrap[] bubbles_arg, - BmpWrap[] bubblesBlind_arg, - BmpWrap[] frozenBubbles_arg, - BmpWrap[] targetedBubbles_arg, - BmpWrap bubbleBlink_arg, - BmpWrap gameWon_arg, - BmpWrap gameLost_arg, - BmpWrap gamePaused_arg, - BmpWrap hurry_arg, - BmpWrap pauseButton_arg, - BmpWrap playButton_arg, - BmpWrap penguins_arg, - BmpWrap compressorHead_arg, - BmpWrap compressor_arg, - MalusBar malusBar_arg, - Drawable launcher_arg, - SoundManager soundManager_arg, - LevelManager levelManager_arg, - HighscoreManager highscoreManager_arg, - NetworkManager networkManager_arg, - VirtualInput input_arg) { - random = new Random(System.currentTimeMillis()); - launcher = launcher_arg; - penguins = penguins_arg; - background = background_arg; - bubbles = bubbles_arg; - bubblesBlind = bubblesBlind_arg; - frozenBubbles = frozenBubbles_arg; - targetedBubbles = targetedBubbles_arg; - bubbleBlink = bubbleBlink_arg; - gameWon = gameWon_arg; - gameLost = gameLost_arg; - soundManager = soundManager_arg; - levelManager = levelManager_arg; - highscoreManager = highscoreManager_arg; - networkManager = networkManager_arg; - malusBar = malusBar_arg; - playResult = gameEnum.PLAYING; - launchBubblePosition = START_LAUNCH_DIRECTION; - readyToFire = false; - swapPressed = false; - - /* - * Initialize game modifier variables. - */ - if (input_arg != null) { - player = input_arg.playerID; - isRemote = input_arg.isRemote; - } - else { - player = VirtualInput.PLAYER1; - isRemote = false; - } - - isArcade = FrozenBubble.arcadeGame; - - /* - * Create objects for all the game graphics. - */ - if ((pauseButton_arg != null) && (playButton_arg != null)) { - pauseButtonSprite = new ImageSprite(new Rect(167, 444, 32, 32), - pauseButton_arg); - playButtonSprite = new ImageSprite(new Rect(167, 444, 32, 32), - playButton_arg); - this.addSprite(pauseButtonSprite); - } - else { - pauseButtonSprite = null; - playButtonSprite = null; - } - - penguin = new PenguinSprite(getPenguinRect(player), penguins_arg, random); - this.addSprite(penguin); - - compressor = new Compressor(compressorHead_arg, compressor_arg); - hurrySprite = new ImageSprite(new Rect(203, 265, 203 + 240, 265 + 90), - hurry_arg); - pausedSprite = new ImageSprite(new Rect(152, 190, 337, 116), - gamePaused_arg); - - if (malusBar != null) - this.addSprite(malusBar); - - falling = new Vector(); - goingUp = new Vector(); - jumping = new Vector(); - - bubblePlay = new BubbleSprite[LevelManager.NUM_COLS] - [LevelManager.NUM_ROWS]; - scrolling = new BubbleSprite[LevelManager.NUM_COLS]; - bubbleManager = new BubbleManager(bubbles); - - /* - * Load the current level to the bubble play grid. - */ - byte[][] currentLevel = levelManager.getCurrentLevel(); - if (currentLevel == null) { - //Log.i("frozen-bubble", "Level not available."); - return; - } - - for (int j = 0; j < (LevelManager.NUM_ROWS - 1); j++) { - for (int i = j%2; i < LevelManager.NUM_COLS; i++) { - if (currentLevel[i][j] != -1) { - BubbleSprite newOne = new BubbleSprite( - new Rect(190+i*32-(j%2)*16, 44+j*28, 32, 32), - currentLevel[i][j], - bubbles[currentLevel[i][j]], bubblesBlind[currentLevel[i][j]], - frozenBubbles[currentLevel[i][j]], bubbleBlink, bubbleManager, - soundManager, this); - bubblePlay[i][j] = newOne; - this.addSprite(newOne); - } - } - } - - if (isArcade) { - addScrollRow(); - } - - /* - * Initialize the launch bubbles. - */ - currentColor = bubbleManager.nextBubbleIndex(random); - nextColor = bubbleManager.nextBubbleIndex(random); - - if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL) { - nextBubble = new ImageSprite(new Rect(302, 440, 302 + 32, 440 + 32), - bubbles[nextColor]); - } - else { - nextBubble = new ImageSprite(new Rect(302, 440, 302 + 32, 440 + 32), - bubblesBlind[nextColor]); - } - - this.addSprite(nextBubble); - launchBubble = new LaunchBubbleSprite(currentColor, - launchBubblePosition, - launcher, bubbles, bubblesBlind); - this.spriteToBack(launchBubble); - - /* - * Initialize game metrics. - */ - nbBubbles = 0; - sendToOpponent = 0; - } - - public FrozenGame(BmpWrap background_arg, - BmpWrap[] bubbles_arg, - BmpWrap[] bubblesBlind_arg, - BmpWrap[] frozenBubbles_arg, - BmpWrap[] targetedBubbles_arg, - BmpWrap bubbleBlink_arg, - BmpWrap gameWon_arg, - BmpWrap gameLost_arg, - BmpWrap gamePaused_arg, - BmpWrap hurry_arg, - BmpWrap penguins_arg, - BmpWrap compressorHead_arg, - BmpWrap compressor_arg, - Drawable launcher_arg, - SoundManager soundManager_arg, - LevelManager levelManager_arg, - HighscoreManager highscoreManager_arg) { - this(background_arg, bubbles_arg, bubblesBlind_arg, frozenBubbles_arg, - targetedBubbles_arg, bubbleBlink_arg, gameWon_arg, gameLost_arg, - gamePaused_arg, hurry_arg, null, null, penguins_arg, compressorHead_arg, - compressor_arg, null, launcher_arg, soundManager_arg, - levelManager_arg, highscoreManager_arg, null, null); - } - - public void addAttackBubbles(int attackBubbles) { - sendToOpponent += attackBubbles; - } - - public void addFallingBubble(BubbleSprite sprite) { - if (malusBar != null) - malusBar.releaseTime = 0; - sendToOpponent++; - spriteToFront(sprite); - falling.addElement(sprite); - } - - public void addJumpingBubble(BubbleSprite sprite) { - spriteToFront(sprite); - jumping.addElement(sprite); - } - - private void addScrollRow() { - byte[] newRow = levelManager.getNewRow(bubblePlay); - int colIdx = (levelManager.getRowOffset() + 1) % 2; - int rowMove = (int) compressor.getMoveDown(); - for (int column = 0; column < LevelManager.NUM_COLS; column++) { - scrolling[column] = null; - } - for (int column = colIdx; column < LevelManager.NUM_COLS; column++) { - if (newRow[column] != -1) { - int color = newRow[column]; - BubbleSprite tempBubble = new BubbleSprite( - new Rect(columnX[colIdx], 44 - 28 + rowMove, 32, 32), - color, bubbles[color], bubblesBlind[color], frozenBubbles[color], - bubbleBlink, bubbleManager, soundManager, this); - scrolling[column] = tempBubble; - this.addSprite(tempBubble); - this.spriteToBack(tempBubble); - } - colIdx += 2; - } - } - - private void blinkLine(int number) { - int move = number%2; - int column = (number+1) >> 1; - - for (int i = move; i < LevelManager.NUM_ROWS; i++) { - if (bubblePlay[column][i] != null) { - bubblePlay[column][i].blink(); - } - } - } - - public void calculateGridChecksum() { - CRC16 gridCRC = new CRC16(0); - - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < (LevelManager.NUM_ROWS - 1); j++) { - if (bubblePlay[i][j] != null) { - gridCRC.update(bubblePlay[i][j].getColor()); - } - } - } - - gridChecksum = (short) gridCRC.getValue(); - } - - private boolean checkLost() { - boolean lost = false; - - if (!endOfGame) { - if (movingBubble != null) { - if (movingBubble.fixed() && !movingBubble.released() && - (movingBubble.getSpritePosition().y >= 380)) { - lost = true; - } - } - - int steps = compressor.getSteps(); - - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - if (bubblePlay[i][(LevelManager.NUM_ROWS - 1) - steps] != null) { - lost = true; - break; - } - } - - if (lost) { - penguin.updateState(PenguinSprite.STATE_GAME_LOST); - if (highscoreManager != null) { - if (isArcade) { - highscoreManager.endLevel(nbBubbles); - } - else { - highscoreManager.lostLevel(); - } - } - playResult = gameEnum.LOST; - endOfGame = true; - initFrozenify(); - soundManager.playSound(FrozenBubble.SOUND_LOST); - } - } - - return playResult == gameEnum.LOST; - } - - public void clampLaunchPosition() { - if (launchBubblePosition < MIN_LAUNCH_DIRECTION) { - launchBubblePosition = MIN_LAUNCH_DIRECTION; - } - if (launchBubblePosition > MAX_LAUNCH_DIRECTION) { - launchBubblePosition = MAX_LAUNCH_DIRECTION; - } - } - - public void deleteFallingBubble(BubbleSprite sprite) { - removeSprite(sprite); - falling.removeElement(sprite); - } - - /** - * Remove the designated goingUp bubble sprite from the vector of - * attack bubbles because it is now inserted into the game grid. The - * sprite is not removed from the vector of all sprites in the game - * because it has been added to the play field. - * @param sprite - the attack bubble inserted into the game grid. - */ - public void deleteGoingUpBubble(BubbleSprite sprite) { - goingUp.removeElement(sprite); - } - - public void deleteJumpingBubble(BubbleSprite sprite) { - removeSprite(sprite); - jumping.removeElement(sprite); - } - - private void finishFrozenify() { - if (isArcade) { - for (int column = 0; column < LevelManager.NUM_COLS; column++) { - if (scrolling[column] != null) { - this.spriteToBack(scrolling[column]); - scrolling[column].frozenify(); - } - } - } - frozenify = false; - this.addSprite(new ImageSprite(new Rect(152, 190, 337, 116), - gameLost)); - soundManager.playSound(FrozenBubble.SOUND_NOH); - } - - private void frozenify() { - frozenifyX--; - if (frozenifyX < 0) { - frozenifyX = LevelManager.NUM_COLS - 1; - frozenifyY--; - - if (frozenifyY < 0) { - finishFrozenify(); - return; - } - } - - while ((bubblePlay[frozenifyX][frozenifyY] == null) && (frozenifyY >= 0)) { - frozenifyX--; - if (frozenifyX < 0) { - frozenifyX = LevelManager.NUM_COLS - 1; - frozenifyY--; - - if (frozenifyY < 0) { - finishFrozenify(); - return; - } - } - } - - this.spriteToBack(bubblePlay[frozenifyX][frozenifyY]); - bubblePlay[frozenifyX][frozenifyY].frozenify(); - - this.spriteToBack(launchBubble); - } - - public int getAttackBarBubbles() { - return malusBar.getAttackBarBubbles(); - } - - public int getCompressorSteps() { - return compressor.getSteps(); - } - - public int getCurrentColor() { - return currentColor; - } - - public gameEnum getGameResult() { - return playResult; - } - - public BubbleSprite[][] getGrid() { - return bubblePlay; - } - - public double getMoveDown() { - return compressor.getMoveDown(); - } - - public int getNewNextColor() { - return newNextColor; - } - - public int getNextColor() { - return nextColor; - } - - public boolean getOkToFire() { - return (movingBubble == null) && (playResult == gameEnum.PLAYING) && - ((goingUp.size() == 0) || (networkManager == null)) && readyToFire; - } - - private Rect getPenguinRect(int player) { - if (player == 1) - return new Rect(361, 436, 361 + PenguinSprite.PENGUIN_WIDTH - 2, - 436 + PenguinSprite.PENGUIN_HEIGHT - 2); - else - return new Rect(221, 436, 221 + PenguinSprite.PENGUIN_WIDTH - 2, - 436 + PenguinSprite.PENGUIN_HEIGHT - 2); - } - - public double getPosition() { - return launchBubblePosition; - } - - public Random getRandom() { - return random; - } - - public int getRowOffset() { - return levelManager.getRowOffset(); - } - - /** - * Obtain this player's sendToOpponent value, which is - * the number of attack bubbles to add to the opponent's attack bar. - * @return The number of attack bubbles to add to the opponent's - * attack bar. - */ - public int getSendToOpponent() { - return sendToOpponent; - } - - private void initFrozenify() { - ImageSprite freezeLaunchBubble = - new ImageSprite(new Rect(301, 389, 34, 42), frozenBubbles[currentColor]); - ImageSprite freezeNextBubble = - new ImageSprite(new Rect(301, 439, 34, 42), frozenBubbles[nextColor]); - - this.addSprite(freezeLaunchBubble); - this.addSprite(freezeNextBubble); - - frozenifyX = LevelManager.NUM_COLS; - frozenifyY = LevelManager.NUM_ROWS - 1; - frozenify = true; - } - - /** - * Lower the bubbles in play and drop the compressor a step. - * @param playSound - true to play the compression sound. - */ - public void lowerCompressor(boolean playSound) { - fixedBubbles = 0; - - if (isArcade) { - return; - } - - if (playSound) { - soundManager.playSound(FrozenBubble.SOUND_NEWROOT); - } - - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < (LevelManager.NUM_ROWS - 1); j++) { - if (bubblePlay[i][j] != null) { - bubblePlay[i][j].moveDown(); - - if ((bubblePlay[i][j].getSpritePosition().y >= 380) && !endOfGame) { - penguin.updateState(PenguinSprite.STATE_GAME_LOST); - if (highscoreManager != null) - highscoreManager.lostLevel(); - playResult = gameEnum.LOST; - endOfGame = true; - initFrozenify(); - soundManager.playSound(FrozenBubble.SOUND_LOST); - } - } - } - } - - compressor.moveDown(); - } - - /** - * Move the launched bubble. - * @return true if the compressor was lowered. - */ - public boolean manageMovingBubble() { - boolean compressed = false; - - if (movingBubble != null) { - movingBubble.move(); - if (movingBubble.fixed()) { - if (!checkLost() && !isArcade) { - /* - * If there are no bubbles in the bubble manager, then the - * player has won the game. The bubble manager counts bubbles - * that are fixed in position on the bubble grid. Thus if - * there are attack bubbles in motion when the bubble manager - * is cleared, then the attack bubbles will be added to the - * bubble manager when they stick to the bubble grid after the - * player has already won the game. This may need to change. - */ - if (bubbleManager.countBubbles() == 0) { - penguin.updateState(PenguinSprite.STATE_GAME_WON); - this.addSprite(new ImageSprite(new Rect(152, 190, - 152 + 337, - 190 + 116), gameWon)); - if (highscoreManager != null) - highscoreManager.endLevel(nbBubbles); - playResult = gameEnum.WON; - endOfGame = true; - soundManager.playSound(FrozenBubble.SOUND_WON); - } - else if ((malusBar == null) || FrozenBubble.getCompressor()) { - fixedBubbles++; - blinkDelay = 0; - - if ((fixedBubbles == 8) && !isRemote) { - lowerCompressor(true); - compressed = true; - } - } - } - movingBubble = null; - } - } - return compressed; - } - - public void paint(Canvas c, double scale, int dx, int dy) { - if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL) { - nextBubble.changeImage(bubbles[nextColor]); - } - else { - nextBubble.changeImage(bubblesBlind[nextColor]); - } - super.paint(c, scale, dx, dy); - compressor.paint(c, scale, dx, dy); - } - - public void pause() { - this.removeSprite(pausedSprite); - this.addSprite(pausedSprite); - } - - public void pauseButtonPressed(boolean paused) { - if (paused) { - if (pauseButtonSprite != null) { - this.removeSprite(pauseButtonSprite); - } - if (playButtonSprite != null) { - this.removeSprite(playButtonSprite); - this.addSprite(playButtonSprite); - } - } - else { - if (playButtonSprite != null) { - this.removeSprite(playButtonSprite); - } - if (pauseButtonSprite != null) { - this.removeSprite(pauseButtonSprite); - this.addSprite(pauseButtonSprite); - } - } - } - - public gameEnum play(boolean key_left, boolean key_right, - boolean key_fire, boolean key_swap, - double trackball_dx, - boolean touch_fire, double touch_x, double touch_y, - boolean ats_touch_fire, double ats_touch_dx) { - boolean ats = FrozenBubble.getAimThenShoot(); - boolean bubbleLaunched = false; - boolean compressed = false; - int[] move = new int[2]; - int attackBarBubbles = 0; - int currentColorWas = currentColor; - int nextColorWas = nextColor; - int numAttackBubbles = 0; - - if (malusBar != null) { - sendToOpponent = 0; - attackBarBubbles = malusBar.getAttackBarBubbles(); - } - - if ((ats && ats_touch_fire) || ((!ats || isRemote) && touch_fire)) { - key_fire = true; - } - - if (key_left && !key_right) { - move[HORIZONTAL_MOVE] = KEY_LEFT; - } - else if (key_right && !key_left) { - move[HORIZONTAL_MOVE] = KEY_RIGHT; - } - else { - move[HORIZONTAL_MOVE] = 0; - } - - if (key_fire) { - move[FIRE] = KEY_UP; - } - else { - move[FIRE] = 0; - } - - if (key_swap) { - if (!swapPressed) { - swapNextLaunchBubble(); - swapPressed = true; - } - } - else { - swapPressed = false; - } - - if (!ats && touch_fire && !isRemote && (movingBubble == null)) { - double xx = touch_x - 318; - double yy = 406 - touch_y; - launchBubblePosition = (Math.PI - Math.atan2(yy, xx)) * 40.0 / Math.PI; - clampLaunchPosition(); - } - - if ((move[FIRE] == 0) || touch_fire) { - readyToFire = true; - } - - /* - * If the option to rush the player is disabled or this game - * represents the remote player in a network game, initialize - * hurryTime to disable automatic bubbles launches. - */ - if (FrozenBubble.getDontRushMe() || isRemote) { - hurryTime = 1; - } - - if (endOfGame && readyToFire) { - if (move[FIRE] == KEY_UP) { - if (playResult == gameEnum.WON) { - playResult = gameEnum.NEXT_WON; - } - else { - playResult = gameEnum.NEXT_LOST; - } - return playResult; - } - else { - penguin.updateState(PenguinSprite.STATE_VOID); - - /* - * If the game is over because of bubble overflow, wait until - * all the bubbles have stopped moving to freeze them. - */ - if (frozenify && (goingUp.size() == 0) && (movingBubble == null)) { - frozenify(); - } - } - } - else { - if ((move[FIRE] == KEY_UP) || (hurryTime > HURRY_ME_TIME)) { - if (getOkToFire()) { - nbBubbles++; - movingBubble = new BubbleSprite(new Rect(302, 390, 32, 32), - launchBubblePosition, - currentColor, - bubbles[currentColor], - bubblesBlind[currentColor], - frozenBubbles[currentColor], - targetedBubbles, bubbleBlink, - bubbleManager, soundManager, this); - this.addSprite(movingBubble); - bubbleLaunched = true; - currentColor = nextColor; - - if (isRemote) { - nextColor = newNextColor; - } - else { - nextColor = bubbleManager.nextBubbleIndex(random); - } - - if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL) { - nextBubble.changeImage(bubbles[nextColor]); - } - else { - nextBubble.changeImage(bubblesBlind[nextColor]); - } - - launchBubble.changeColor(currentColor); - penguin.updateState(PenguinSprite.STATE_FIRE); - soundManager.playSound(FrozenBubble.SOUND_LAUNCH); - readyToFire = false; - hurryTime = 0; - - if (malusBar != null) { - malusBar.releaseTime = RELEASE_TIME; - } - - removeSprite(hurrySprite); - } - else { - penguin.updateState(PenguinSprite.STATE_VOID); - } - } - else { - double dx = 0; - if (move[HORIZONTAL_MOVE] == KEY_LEFT) { - dx -= 1; - } - if (move[HORIZONTAL_MOVE] == KEY_RIGHT) { - dx += 1; - } - dx += trackball_dx; - if (ats) { - dx += ats_touch_dx; - } - launchBubblePosition += dx; - clampLaunchPosition(); - launchBubble.changeDirection(launchBubblePosition); - updatePenguinState(dx); - } - } - - /* - * The moving bubble is moved twice, which produces smoother - * animation. Thus the moving bubble effectively moves at twice the - * animation speed with respect to other bubbles that are only - * moved once per iteration. - */ - compressed = manageMovingBubble(); - compressed |= manageMovingBubble(); - - if ((movingBubble == null) && !endOfGame) { - hurryTime++; - if (malusBar != null) - malusBar.releaseTime++; - /* - * If hurryTime == 2 (1 + 1) we could be in the "Don't rush me" - * mode. Remove the sprite just in case the user switched - * to this mode when the "Hurry" sprite was shown, to make it - * disappear. - */ - if (hurryTime == 2) { - removeSprite(hurrySprite); - } - if (hurryTime >= 240) { - if (hurryTime%40 == 10) { - addSprite(hurrySprite); - soundManager.playSound(FrozenBubble.SOUND_HURRY); - } - else if (hurryTime%40 == 35) { - removeSprite(hurrySprite); - } - } - if (malusBar != null) { - if (getOkToFire() && (attackBarBubbles > 0) && - ((malusBar.releaseTime > RELEASE_TIME) || isRemote)) { - numAttackBubbles = releaseBubbles(); - malusBar.releaseTime = 0; - } - } - } - - if (!isArcade && ((malusBar == null) || FrozenBubble.getCompressor())) { - if (fixedBubbles == 6) { - if (blinkDelay < 15) { - blinkLine(blinkDelay); - } - blinkDelay++; - if (blinkDelay == 40) { - blinkDelay = 0; - } - } - else if (fixedBubbles == 7) { - if (blinkDelay < 15) { - blinkLine(blinkDelay); - } - blinkDelay++; - if (blinkDelay == 25) { - blinkDelay = 0; - } - } - } - - if (!endOfGame && isArcade) { - scrollBubbles(); - } - - for (int i = 0; i < falling.size(); i++) { - ((BubbleSprite)falling.elementAt(i)).fall(); - } - - for (int i = 0; i < goingUp.size(); i++) { - ((BubbleSprite)goingUp.elementAt(i)).goUp(); - } - - for (int i = 0; i < jumping.size(); i++) { - ((BubbleSprite)jumping.elementAt(i)).jump(); - } - - /* - * Perform game synchronization tasks. - */ - if (!endOfGame && movingBubble == null) { - synchronizeBubbleManager(); - } - - /* - * In an arcade or multiplayer game, check if the player lost due to - * scrolling or attack bubbles overflowing the play area. - */ - if ((malusBar != null) || isArcade) { - checkLost(); - } - - /* - * If this player is the local player and is participating in a - * network game, transmit the local player action to the remote - * player if an action occurred. - */ - if ((networkManager != null) && (malusBar != null)) { - if (bubbleLaunched || compressed || swapPressed || - (numAttackBubbles > 0)) { - if (bubbleLaunched || (numAttackBubbles > 0)) { - gridChecksum = 0; - } - if (!isRemote) { - networkManager.sendLocalPlayerAction(player, - compressed, - bubbleLaunched, - swapPressed, - 0, - currentColorWas, - nextColorWas, - nextColor, - attackBarBubbles, - malusBar.attackBubbles, - launchBubblePosition); - } - } - else if ((gridChecksum == 0) && getOkToFire()) { - calculateGridChecksum(); - } - } - - if (malusBar != null) { - malusBar.clearAttackBubbles(); - } - - return gameEnum.PLAYING; - } - - /** - * Populate random columns in a row of attack bubbles to launch onto - * the game field. - *

In an actual play field, the rows alternate between a maximum 7 - * and 8 bubbles per row. Thus 7 bubbles are sent up as that is the - * maximum number of bubbles that can fit in each alternating row. - *

There are 15 distinct positions ("lanes") for bubbles to occupy - * between two consecutive rows. Thus we send up a maximum 7 bubbles - * in randomly selected "lanes" from the 15 available. - * @return The number of attack bubbles launched. - */ - private int releaseBubbles() { - if (malusBar == null) { - return 0; - } - - int numBubblesLaunched = 0; - - /* - * If this game represents a remote player, the the attack bubbles - * are calculated on the remote machine and sent over the network. - * Simply use the supplied attack bubble buffer to initiate attack - * bubble launches. - */ - if (isRemote) { - for (int i = 0; i < LevelManager.LANES; i++) { - if (malusBar.attackBubbles[i] >= 0) { - numBubblesLaunched++; - int color = malusBar.attackBubbles[i]; - BubbleSprite malusBubble = new BubbleSprite( - new Rect(columnX[i], 44+(LevelManager.MAX_ROWS*28), 32, 32), - START_LAUNCH_DIRECTION, - color, bubbles[color], bubblesBlind[color], - frozenBubbles[color], targetedBubbles, bubbleBlink, - bubbleManager, soundManager, this); - goingUp.add(malusBubble); - this.addSprite(malusBubble); - } - } - malusBar.removeAttackBubbles(numBubblesLaunched); - } - else if (malusBar.getAttackBarBubbles() > 0) { - boolean[] lanes = new boolean[LevelManager.LANES]; - int malusBalls = malusBar.removeLine(); - int pos; - - while (malusBalls > 0) { - pos = random.nextInt(LevelManager.LANES); - if (!lanes[pos]) { - lanes[pos] = true; - malusBalls--; - } - } - - for (int i = 0; i < LevelManager.LANES; i++) { - if (lanes[i]) { - numBubblesLaunched++; - int color = random.nextInt(FrozenBubble.getDifficulty()); - malusBar.setAttackBubble(i, color); - BubbleSprite malusBubble = new BubbleSprite( - new Rect(columnX[i], 44+(LevelManager.MAX_ROWS*28), 32, 32), - START_LAUNCH_DIRECTION, - color, bubbles[color], bubblesBlind[color], - frozenBubbles[color], targetedBubbles, bubbleBlink, - bubbleManager, soundManager, this); - goingUp.add(malusBubble); - this.addSprite(malusBubble); - } - } - } - - return numBubblesLaunched; - } - - private Sprite restoreSprite(Bundle map, Vector imageList, int i) { - int left = map.getInt(String.format("%d-%d-left", player, i)); - int right = map.getInt(String.format("%d-%d-right", player, i)); - int top = map.getInt(String.format("%d-%d-top", player, i)); - int bottom = map.getInt(String.format("%d-%d-bottom", player, i)); - int type = map.getInt(String.format("%d-%d-type", player, i)); - if (type == Sprite.TYPE_BUBBLE) { - int color = map.getInt(String.format("%d-%d-color", player, i)); - double moveX = map.getDouble(String.format("%d-%d-moveX", player, i)); - double moveY = map.getDouble(String.format("%d-%d-moveY", player, i)); - double realX = map.getDouble(String.format("%d-%d-realX", player, i)); - double realY = map.getDouble(String.format("%d-%d-realY", player, i)); - boolean fixed = map.getBoolean(String.format("%d-%d-fixed", player, i)); - boolean blink = map.getBoolean(String.format("%d-%d-blink", player, i)); - boolean released = - map.getBoolean(String.format("%d-%d-released", player, i)); - boolean checkJump = - map.getBoolean(String.format("%d-%d-checkJump", player, i)); - boolean checkFall = - map.getBoolean(String.format("%d-%d-checkFall", player, i)); - int fixedAnim = map.getInt(String.format("%d-%d-fixedAnim", player, i)); - boolean frozen = - map.getBoolean(String.format("%d-%d-frozen", player, i)); - Point lastOpenPosition = new Point( - map.getInt(String.format("%d-%d-lastOpenPosition.x", player, i)), - map.getInt(String.format("%d-%d-lastOpenPosition.y", player, i))); - int scroll = map.getInt(String.format("%d-%d-scroll", player, i)); - int scrollMax = map.getInt(String.format("%d-%d-scrollMax", player, i)); - return new BubbleSprite(new Rect(left, top, right, bottom), - color, moveX, moveY, realX, realY, - fixed, blink, released, checkJump, checkFall, - fixedAnim, scroll, scrollMax, - (frozen ? frozenBubbles[color] : bubbles[color]), - lastOpenPosition, - bubblesBlind[color], - frozenBubbles[color], - targetedBubbles, bubbleBlink, - bubbleManager, soundManager, this); - } - else if (type == Sprite.TYPE_IMAGE) { - int imageId = map.getInt(String.format("%d-%d-imageId", player, i)); - return new ImageSprite(new Rect(left, top, right, bottom), - (BmpWrap)imageList.elementAt(imageId)); - } - else if (type == Sprite.TYPE_LAUNCH_BUBBLE) { - int currentColor = - map.getInt(String.format("%d-%d-currentColor", player, i)); - double currentDirection = - map.getDouble(String.format("%d-%d-currentDirection", player, i)); - return new LaunchBubbleSprite(currentColor, currentDirection, - launcher, bubbles, bubblesBlind); - } - else if (type == Sprite.TYPE_PENGUIN) { - int currentPenguin = - map.getInt(String.format("%d-%d-currentPenguin", player, i)); - int count = map.getInt(String.format("%d-%d-count", player, i)); - int finalState = - map.getInt(String.format("%d-%d-finalState", player, i)); - int nextPosition = - map.getInt(String.format("%d-%d-nextPosition", player, i)); - - return new PenguinSprite(getPenguinRect(player), penguins, random, - currentPenguin, count, finalState, - nextPosition); - } - else { - Log.e("frozen-bubble", "Unrecognized sprite type: " + type); - return null; - } - } - - public void restoreState(Bundle map, Vector imageList) { - Vector savedSprites = new Vector(); - int numSavedSprites = - map.getInt(String.format("%d-numSavedSprites", player)); - for (int i = 0; i < numSavedSprites; i++) { - savedSprites.addElement(restoreSprite(map, imageList, i)); - } - - restoreSprites(map, savedSprites, player); - - if (jumping == null) { - jumping = new Vector(); - } - int numJumpingSprites = - map.getInt(String.format("%d-numJumpingSprites", player)); - for (int i = 0; i < numJumpingSprites; i++) { - int spriteIdx = map.getInt(String.format("%d-jumping-%d", player, i)); - jumping.addElement(savedSprites.elementAt(spriteIdx)); - } - if (goingUp == null) { - goingUp = new Vector(); - } - int numGoingUpSprites = - map.getInt(String.format("%d-numGoingUpSprites", player)); - for (int i = 0; i < numGoingUpSprites; i++) { - int spriteIdx = map.getInt(String.format("%d-goingUp-%d", player, i)); - goingUp.addElement(savedSprites.elementAt(spriteIdx)); - } - if (falling == null) { - falling = new Vector(); - } - int numFallingSprites = - map.getInt(String.format("%d-numFallingSprites", player)); - for (int i = 0; i < numFallingSprites; i++) { - int spriteIdx = map.getInt(String.format("%d-falling-%d", player, i)); - falling.addElement(savedSprites.elementAt(spriteIdx)); - } - if (bubblePlay == null) { - bubblePlay = new BubbleSprite[LevelManager.NUM_COLS] - [LevelManager.NUM_ROWS]; - } - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < LevelManager.NUM_ROWS; j++) { - int spriteIdx = - map.getInt(String.format("%d-play-%d-%d", player, i, j)); - if (spriteIdx != -1) { - bubblePlay[i][j] = (BubbleSprite)savedSprites.elementAt(spriteIdx); - } - else { - bubblePlay[i][j] = null; - } - } - } - if (isArcade) { - if (scrolling == null) { - scrolling = new BubbleSprite[LevelManager.NUM_COLS]; - } - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - int spriteIdx = - map.getInt(String.format("%d-scrolling-%d", player, i)); - if (spriteIdx != -1) { - scrolling[i] = (BubbleSprite)savedSprites.elementAt(spriteIdx); - } - else { - scrolling[i] = null; - } - } - } - int launchBubbleId = - map.getInt(String.format("%d-launchBubbleId", player)); - launchBubble = (LaunchBubbleSprite)savedSprites.elementAt(launchBubbleId); - launchBubblePosition = - map.getDouble(String.format("%d-launchBubblePosition", player)); - if (malusBar != null) { - malusBar.restoreState(map, player); - this.addSprite(malusBar); - } - int penguinId = map.getInt(String.format("%d-penguinId", player)); - penguin = (PenguinSprite)savedSprites.elementAt(penguinId); - compressor.restoreState(map, player); - int nextBubbleId = map.getInt(String.format("%d-nextBubbleId", player)); - nextBubble = (ImageSprite)savedSprites.elementAt(nextBubbleId); - currentColor = map.getInt(String.format("%d-currentColor", player)); - nextColor = map.getInt(String.format("%d-nextColor", player)); - int movingBubbleId = - map.getInt(String.format("%d-movingBubbleId", player)); - if (movingBubbleId == -1) { - movingBubble = null; - } - else { - movingBubble = (BubbleSprite)savedSprites.elementAt(movingBubbleId); - } - bubbleManager.restoreState(map, player); - fixedBubbles = map.getInt(String.format("%d-fixedBubbles", player)); - nbBubbles = map.getInt(String.format("%d-nbBubbles", player)); - sendToOpponent = map.getInt(String.format("%d-sendToOpponent", player)); - blinkDelay = map.getInt(String.format("%d-blinkDelay", player)); - int hurryId = map.getInt(String.format("%d-hurryId", player)); - hurrySprite = (ImageSprite)savedSprites.elementAt(hurryId); - hurryTime = map.getInt(String.format("%d-hurryTime", player)); - int pausedId = map.getInt(String.format("%d-pausedId", player)); - pausedSprite = (ImageSprite)savedSprites.elementAt(pausedId); - readyToFire = map.getBoolean(String.format("%d-readyToFire", player)); - endOfGame = map.getBoolean(String.format("%d-endOfGame", player)); - frozenify = map.getBoolean(String.format("%d-frozenify", player)); - frozenifyX = map.getInt(String.format("%d-frozenifyX", player)); - frozenifyY = map.getInt(String.format("%d-frozenifyY", player)); - } - - public void resume() { - this.removeSprite(pausedSprite); - } - - public void saveState(Bundle map) { - Vector savedSprites = new Vector(); - - saveSprites(map, savedSprites, player); - - for (int i = 0; i < jumping.size(); i++) { - ((Sprite)jumping.elementAt(i)).saveState(map, savedSprites, player); - map.putInt(String.format("%d-jumping-%d", player, i), - ((Sprite)jumping.elementAt(i)).getSavedId()); - } - map.putInt(String.format("%d-numJumpingSprites", player), jumping.size()); - for (int i = 0; i < goingUp.size(); i++) { - ((Sprite)goingUp.elementAt(i)).saveState(map, savedSprites, player); - map.putInt(String.format("%d-goingUp-%d", player, i), - ((Sprite)goingUp.elementAt(i)).getSavedId()); - } - map.putInt(String.format("%d-numGoingUpSprites", player), goingUp.size()); - for (int i = 0; i < falling.size(); i++) { - ((Sprite)falling.elementAt(i)).saveState(map, savedSprites, player); - map.putInt(String.format("%d-falling-%d", player, i), - ((Sprite)falling.elementAt(i)).getSavedId()); - } - map.putInt(String.format("%d-numFallingSprites", player), falling.size()); - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < LevelManager.NUM_ROWS; j++) { - if (bubblePlay[i][j] != null) { - bubblePlay[i][j].saveState(map, savedSprites, player); - map.putInt(String.format("%d-play-%d-%d", player, i, j), - bubblePlay[i][j].getSavedId()); - } - else { - map.putInt(String.format("%d-play-%d-%d", player, i, j), -1); - } - } - } - if (isArcade) { - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - if (scrolling[i] != null) { - scrolling[i].saveState(map, savedSprites, player); - map.putInt(String.format("%d-scrolling-%d", player, i), - scrolling[i].getSavedId()); - } - else { - map.putInt(String.format("%d-scrolling-%d", player, i), -1); - } - } - } - launchBubble.saveState(map, savedSprites, player); - map.putInt(String.format("%d-launchBubbleId", player), - launchBubble.getSavedId()); - map.putDouble(String.format("%d-launchBubblePosition", player), - launchBubblePosition); - if (malusBar != null) { - malusBar.saveState(map, player); - } - penguin.saveState(map, savedSprites, player); - compressor.saveState(map, player); - map.putInt(String.format("%d-penguinId", player), penguin.getSavedId()); - nextBubble.saveState(map, savedSprites, player); - map.putInt(String.format("%d-nextBubbleId", player), - nextBubble.getSavedId()); - map.putInt(String.format("%d-currentColor", player), currentColor); - map.putInt(String.format("%d-nextColor", player), nextColor); - if (movingBubble != null) { - movingBubble.saveState(map, savedSprites, player); - map.putInt(String.format("%d-movingBubbleId", player), - movingBubble.getSavedId()); - } - else { - map.putInt(String.format("%d-movingBubbleId", player), -1); - } - bubbleManager.saveState(map, player); - map.putInt(String.format("%d-fixedBubbles", player), fixedBubbles); - map.putInt(String.format("%d-nbBubbles", player), nbBubbles); - map.putInt(String.format("%d-sendToOpponent", player), sendToOpponent); - map.putInt(String.format("%d-blinkDelay", player), blinkDelay); - hurrySprite.saveState(map, savedSprites, player); - map.putInt(String.format("%d-hurryId", player), hurrySprite.getSavedId()); - map.putInt(String.format("%d-hurryTime", player), hurryTime); - pausedSprite.saveState(map, savedSprites, player); - map.putInt(String.format("%d-pausedId", player), pausedSprite.getSavedId()); - map.putBoolean(String.format("%d-readyToFire", player), readyToFire); - map.putBoolean(String.format("%d-endOfGame", player), endOfGame); - map.putBoolean(String.format("%d-frozenify", player), frozenify); - map.putInt(String.format("%d-frozenifyX", player), frozenifyX); - map.putInt(String.format("%d-frozenifyY", player), frozenifyY); - map.putInt(String.format("%d-numSavedSprites", player), - savedSprites.size()); - for (int i = 0; i < savedSprites.size(); i++) { - ((Sprite)savedSprites.elementAt(i)).clearSavedId(); - } - } - - void scrollBubbles() { - boolean scroll = compressor.checkScroll(); - int moveDown = (int) compressor.getMoveDown(); - if (scroll) { - for (int row = LevelManager.NUM_ROWS - 1; row >= 0; row--) { - for (int column = 0; column < LevelManager.NUM_COLS; column++) { - if (bubblePlay[column][row] != null) { - bubblePlay[column][row].scroll(moveDown); - } - } - } - for (int column = 0; column < LevelManager.NUM_COLS; column++) { - if (scrolling[column] != null) { - scrolling[column].scroll(moveDown); - } - } - } - if ((movingBubble == null) && (moveDown >= 28.)) { - compressor.moveDownSubtract(28.); - for (int row = LevelManager.NUM_ROWS - 1; row > 0; row--) { - for (int column = 0; column < LevelManager.NUM_COLS; column++) { - bubblePlay[column][row ] = bubblePlay[column][row - 1]; - bubblePlay[column][row - 1] = null; - } - } - for (int column = 0; column < LevelManager.NUM_COLS; column++) { - bubblePlay[column][0] = scrolling[column]; - } - addScrollRow(); - } - } - - /** - * Set the game result associated with this player. - * @param result - GAME_WON if this player won the game, GAME_LOST if - * this player lost the game. - */ - public void setGameResult(gameEnum result) { - if (!endOfGame) { - playResult = result; - if (result == gameEnum.WON) - { - penguin.updateState(PenguinSprite.STATE_GAME_WON); - this.addSprite(new ImageSprite(new Rect(152, 190, - 152 + 337, - 190 + 116), gameWon)); - } - else if (result == gameEnum.LOST) - { - penguin.updateState(PenguinSprite.STATE_GAME_LOST); - this.addSprite(new ImageSprite(new Rect(152, 190, - 152 + 337, - 190 + 116), gameLost)); - } - endOfGame = true; - } - } - - /** - * Perform bubble grid and compressor synchronization. - *

To prevent the appearance of glitches, the game field should not - * be synchronized while bubbles are in motion. - * @param newGrid - the new bubble grid to apply to the game field. - * @param newSteps - the number of compressor steps to lower to. - */ - public void setGrid(byte[][] newGrid, byte newSteps) { - if (newGrid != null) { - compressor.init(); - falling.clear(); - goingUp.clear(); - jumping.clear(); - bubbleManager.initialize(); - removeAllBubbleSprites(); - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < LevelManager.NUM_ROWS; j++) { - bubblePlay[i][j] = null; - if (newGrid[i][j] != -1) { - bubblePlay[i][j] = new BubbleSprite( - new Rect(190+i*32-(j%2)*16, 44+j*28, 32, 32), - newGrid[i][j], - bubbles[newGrid[i][j]], bubblesBlind[newGrid[i][j]], - frozenBubbles[newGrid[i][j]], bubbleBlink, bubbleManager, - soundManager, this); - this.addSprite(bubblePlay[i][j]); - } - } - } - } - for (int index = 0; index < newSteps; index++) { - lowerCompressor(false); - } - } - - public void setLaunchBubbleColors(int current, int next, int newNext) { - currentColor = current; - nextColor = next; - newNextColor = newNext; - launchBubble.changeColor(currentColor); - - if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL) - nextBubble.changeImage(bubbles[nextColor]); - else - nextBubble.changeImage(bubblesBlind[nextColor]); - } - - public void setPosition(double value) { - if (!endOfGame) { - double dx = value - launchBubblePosition; - /* - * For small position changes, don't update the penguin state. - */ - if ((dx < 0.25) && (dx > -0.25)) - dx = 0; - launchBubblePosition = value; - clampLaunchPosition(); - launchBubble.changeDirection(launchBubblePosition); - updatePenguinState(dx); - } - } - - public void swapNextLaunchBubble() { - if (currentColor != nextColor) { - int tempColor = currentColor; - currentColor = nextColor; - nextColor = tempColor; - launchBubble.changeColor(currentColor); - - if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL) - nextBubble.changeImage(bubbles[nextColor]); - else - nextBubble.changeImage(bubblesBlind[nextColor]); - - soundManager.playSound(FrozenBubble.SOUND_WHIP); - } - } - - /** - * This function is an unfortunate patch that is necessitated due to - * the fact that there is as of yet an unfixed bug in the BubbleSprite - * management code. - *

Somewhere amongst goUp() and move() in BubbleSprite.java, a flaw - * exists whereby a bubble is added to the bubble manager, and the - * bubble sprite is added to the game screen, but the entry in the - * bubblePlay grid was either rendered null or a bubble superposition - * in the grid occurred. The former is suspected, because ensuring - * the grid location is null before assigning a bubble sprite to it is - * very rigorously enforced. - *

TODO - fix the grid entry bug. - */ - public void synchronizeBubbleManager() { - int numBubblesManager = bubbleManager.countBubbles(); - int numBubblesPlay = 0; - /* - * Check the bubble sprite grid for occupied locations. - */ - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < LevelManager.NUM_ROWS; j++) { - if (bubblePlay[i][j] != null ) { - numBubblesPlay++; - } - } - } - if (isArcade) { - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - if (scrolling[i] != null) { - numBubblesPlay++; - } - } - } - /* - * If the number of bubble sprite grid entries does not match the - * number of bubbles in the bubble manager, then we need to re- - * initialize the bubble manager, and re-initialize all the bubble - * sprites on the game screen. You would be unable to win prior to - * the addition of this synchronization code due to the number of - * bubbles in the bubble manager never reaching zero, and the excess - * sprite or sprites would remain stuck on the screen. - */ - if (numBubblesManager != numBubblesPlay) { - bubbleManager.initialize(); - removeAllBubbleSprites(); - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - for (int j = 0; j < LevelManager.NUM_ROWS; j++) { - if (bubblePlay[i][j] != null ) { - bubblePlay[i][j].addToManager(); - this.addSprite(bubblePlay[i][j]); - } - } - } - if (isArcade) { - for (int i = 0; i < LevelManager.NUM_COLS; i++) { - if (scrolling[i] != null) { - scrolling[i].addToManager(); - this.addSprite(scrolling[i]); - } - } - } - for (int i = 0; i < falling.size(); i++) { - this.addSprite(falling.elementAt(i)); - } - for (int i = 0; i < goingUp.size(); i++) { - this.addSprite(goingUp.elementAt(i)); - } - for (int i = 0; i < jumping.size(); i++) { - this.addSprite(jumping.elementAt(i)); - } - } - } - - public void updatePenguinState(double dx) { - if (dx < 0) { - penguin.updateState(PenguinSprite.STATE_TURN_LEFT); - } - else if (dx > 0) { - penguin.updateState(PenguinSprite.STATE_TURN_RIGHT); - } - else { - penguin.updateState(PenguinSprite.STATE_VOID); - } - } -} diff --git a/src/org/jfedor/frozenbubble/GameScreen.java b/src/org/jfedor/frozenbubble/GameScreen.java deleted file mode 100644 index c299e6d..0000000 --- a/src/org/jfedor/frozenbubble/GameScreen.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import java.util.Vector; - -import android.graphics.Canvas; -import android.os.Bundle; - -public abstract class GameScreen { - - public static enum eventEnum { - GAME_WON, - GAME_LOST, - GAME_PAUSED, - GAME_RESUME, - LEVEL_START; - } - - public static enum gameEnum { - PLAYING, - LOST, - WON, - NEXT_LOST, - NEXT_WON; - } - - public static enum stateEnum { - RUNNING, - PAUSED, - ABOUT; - } - - private Vector sprites; - - public final void saveSprites(Bundle map, Vector savedSprites, - int id) { - for (int i = 0; i < sprites.size(); i++) { - ((Sprite)sprites.elementAt(i)).saveState(map, savedSprites, id); - map.putInt(String.format("%d-game-%d", id, i), - ((Sprite)sprites.elementAt(i)).getSavedId()); - } - map.putInt(String.format("%d-numGameSprites", id), sprites.size()); - } - - public final void restoreSprites(Bundle map, Vector savedSprites, - int id) { - sprites = new Vector(); - int numSprites = map.getInt(String.format("%d-numGameSprites", id)); - for (int i = 0; i < numSprites; i++) { - int spriteIdx = map.getInt(String.format("%d-game-%d", id, i)); - sprites.addElement(savedSprites.elementAt(spriteIdx)); - } - } - - public GameScreen() { - sprites = new Vector(); - } - - public final void addSprite(Sprite sprite) { - sprites.removeElement(sprite); - sprites.addElement(sprite); - } - - public final void removeAllBubbleSprites() { - int i = 0; - while ((sprites.size() > 0) && (i < sprites.size())) { - if(((Sprite)sprites.elementAt(i)).getTypeId() == Sprite.TYPE_BUBBLE) { - removeSprite((Sprite)sprites.elementAt(i)); - } - else - i++; - } - } - - public final void removeSprite(Sprite sprite) { - sprites.removeElement(sprite); - } - - public final void spriteToBack(Sprite sprite) { - sprites.removeElement(sprite); - sprites.insertElementAt(sprite,0); - } - - public final void spriteToFront(Sprite sprite) { - sprites.removeElement(sprite); - sprites.addElement(sprite); - } - - public void paint(Canvas c, double scale, int dx, int dy) { - for (int i = 0; i < sprites.size(); i++) { - ((Sprite)sprites.elementAt(i)).paint(c, scale, dx, dy); - } - } - - public abstract gameEnum play(boolean key_left, boolean key_right, - boolean key_fire, boolean key_swap, - double trackball_dx, - boolean touch_fire, - double touch_x, double touch_y, - boolean ats_touch_fire, double ats_touch_dx); -} diff --git a/src/org/jfedor/frozenbubble/GameView.java b/src/org/jfedor/frozenbubble/GameView.java deleted file mode 100644 index 4c98f04..0000000 --- a/src/org/jfedor/frozenbubble/GameView.java +++ /dev/null @@ -1,2866 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -/* This file is derived from the LunarView.java file which is part of - * the Lunar Lander game included with Android documentation. The - * copyright notice for the Lunar Lander is reproduced below. - */ - -/* - * Copyright (c) 2007 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. See the License for the specific language governing - * permissions and limitations under the License. - * - */ - -package org.jfedor.frozenbubble; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; -import java.util.Vector; - -import org.gsanson.frozenbubble.MalusBar; -import org.jfedor.frozenbubble.GameScreen.eventEnum; -import org.jfedor.frozenbubble.GameScreen.gameEnum; -import org.jfedor.frozenbubble.GameScreen.stateEnum; -import org.jfedor.frozenbubble.GameView.NetGameInterface.NetworkStatus; -import org.jfedor.frozenbubble.GameView.NetGameInterface.RemoteInterface; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.pm.ActivityInfo; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.util.AttributeSet; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.SurfaceView; - -import com.efortin.frozenbubble.ComputerAI; -import com.efortin.frozenbubble.HighscoreDO; -import com.efortin.frozenbubble.HighscoreManager; -import com.efortin.frozenbubble.NetworkManager; -import com.efortin.frozenbubble.NetworkManager.GameFieldData; -import com.efortin.frozenbubble.NetworkManager.PlayerAction; -import com.efortin.frozenbubble.NetworkManager.connectEnum; -import com.efortin.frozenbubble.VirtualInput; - -public class GameView extends SurfaceView - implements SurfaceHolder.Callback { - - public static final int GAMEFIELD_WIDTH = 320; - public static final int GAMEFIELD_HEIGHT = 480; - public static final int EXTENDED_GAMEFIELD_WIDTH = 640; - - private boolean mBlankScreen = false; - private boolean muteKeyToggle = false; - private boolean pauseKeyToggle = false; - private int gameLocale; - private int numPlayers; - private int numPlayer1GamesWon; - private int numPlayer2GamesWon; - private Context mContext; - private gameEnum game1Status; - private GameThread mGameThread; - private NetworkManager mNetworkManager; - private RemoteInterface remoteInterface; - private ComputerAI mOpponent; - private VirtualInput mLocalInput; - private VirtualInput mRemoteInput; - private PlayerInput mPlayer1; - private PlayerInput mPlayer2; - - //******************************************************************** - // Listener interface for various events - //******************************************************************** - - /** - * Game event listener user set. - * @author Eric Fortin - * - */ - public interface GameListener { - public abstract void onGameEvent(eventEnum event); - } - - GameListener mGameListener; - - public void setGameListener(GameListener gl) { - mGameListener = gl; - } - - /** - * Network game interface. This interface declares methods that must - * be implemented by the network management class to implement a - * distributed network multiplayer game. - * @author Eric Fortin - * - */ - public interface NetGameInterface { - /** - * A class to encapsulate all network status variables used in - * drawing the network status screen. - * @author efortin - * - */ - public class NetworkStatus { - public int localPlayerId; - public int remotePlayerId; - public boolean isConnected; - public boolean playerJoined; - public boolean gotFieldData; - public boolean gotPrefsData; - public boolean readyToPlay; - public String localIpAddress; - public String remoteIpAddress; - - public NetworkStatus() { - isConnected = false; - playerJoined = false; - gotFieldData = false; - gotPrefsData = false; - readyToPlay = false; - localIpAddress = null; - remoteIpAddress = null; - } - }; - - /** - * This class encapsulates player action and game field storage for - * use by the game thread to determine when to process remote player - * actions and game field bubble grid synchronization tasks. - * @author Eric Fortin - * - */ - public class RemoteInterface { - public boolean gotAction; - public boolean gotFieldData; - public boolean gotPrefsData; - public PlayerAction playerAction; - public GameFieldData gameFieldData; - - public RemoteInterface(PlayerAction action, GameFieldData fieldData) { - gotAction = false; - gotFieldData = false; - gotPrefsData = false; - playerAction = action; - gameFieldData = fieldData; - } - - public void cleanUp() { - gotAction = false; - gotFieldData = false; - gotPrefsData = false; - playerAction = null; - gameFieldData = null; - } - }; - - /* - * Force the implementer to supply the following methods. - */ - public abstract void checkRemoteChecksum(); - public abstract void cleanUp(); - public abstract boolean gameIsReadyForAction(); - public abstract boolean getGameIsFinished(); - public abstract short getLatestRemoteActionId(); - public abstract boolean getRemoteAction(); - public abstract PlayerAction getRemoteActionPreview(); - public abstract RemoteInterface getRemoteInterface(); - public abstract void newGame(); - public abstract void pause(); - public abstract void sendLocalPlayerAction(int playerId, - boolean compress, - boolean launch, - boolean swap, - int keyCode, - int launchColor, - int nextColor, - int newNextColor, - int attackBarBubbles, - byte attackBubbles[], - double aimPosition); - public abstract void setGameIsFinished(); - public abstract void setLocalChecksum(short checksum); - public abstract void setRemoteChecksum(short checksum); - public abstract void unPause(); - public abstract void updateNetworkStatus(NetworkStatus status); - } - - /** - * This class encapsulates player input action variables and methods. - *

This is to provide a common interface to the game independent - * of the input source. - * @author Eric Fortin - * - */ - class PlayerInput extends VirtualInput { - private boolean mCenter = false; - private boolean mDown = false; - private boolean mLeft = false; - private boolean mRight = false; - private boolean mUp = false; - private double mTrackballDx = 0; - private boolean mTouchSwap = false; - private double mTouchX; - private double mTouchY; - private boolean mTouchFireATS = false; - private double mTouchDxATS = 0; - private double mTouchLastX = 0; - - /** - * Construct and configure this player input instance. - * @param id - the player ID, e.g., - * VirtualInput.PLAYER1. - * @param type - true if the player is a simulation. - * @param remote - true if this player is playing on a - * remote machine, false if this player is local. - * @see VirtualInput - */ - public PlayerInput(int id, boolean type, boolean remote) { - init(); - configure(id, type, remote); - } - - /** - * Check if a center button press action is active. - * @return True if the player pressed the center button. - */ - public boolean actionCenter() { - boolean tempCenter = mWasCenter; - mWasCenter = false; - return tempCenter; - } - - /** - * Check if a bubble launch action is active. - * @return True if the player is launching a bubble. - */ - public boolean actionUp() { - boolean tempFire = mWasCenter || mWasUp; - mWasCenter = false; - mWasUp = false; - return mCenter || mUp || tempFire; - } - - /** - * Check if a move left action is active. - * @return True if the player is moving left. - */ - public boolean actionLeft() { - boolean tempLeft = mWasLeft; - mWasLeft = false; - return mLeft || tempLeft; - } - - /** - * Check if a move right action is active. - * @return True if the player is moving right. - */ - public boolean actionRight() { - boolean tempRight = mWasRight; - mWasRight = false; - return mRight || tempRight; - } - - /** - * Check if a bubble swap action is active. - * @return True if the player is swapping the launch bubble. - */ - public boolean actionDown() { - boolean tempSwap = mWasDown || mTouchSwap; - mWasDown = false; - mTouchSwap = false; - return mDown || tempSwap; - } - - /** - * Check if a touchscreen initiated bubble launch is active. - * @return True if the player is launching a bubble. - */ - public boolean actionTouchFire() { - boolean tempFire = mTouchFire; - mTouchFire = false; - return tempFire; - } - - /** - * Check if an ATS (aim-then-shoot) touchscreen initiated bubble - * launch is active. - * @return True if the player is launching a bubble. - */ - public boolean actionTouchFireATS() { - boolean tempFire = mTouchFireATS; - mTouchFireATS = false; - return tempFire; - } - - /** - * Based on the provided keypress, check if it corresponds to a new - * player action. - * @param keyCode - * @return True if the current keypress indicates a new player action. - */ - public boolean checkNewActionKeyPress(int keyCode) { - return (!mLeft && !mRight && !mCenter && !mUp && !mDown) && - ((keyCode == KeyEvent.KEYCODE_DPAD_LEFT) || - (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) || - (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) || - (keyCode == KeyEvent.KEYCODE_DPAD_UP) || - (keyCode == KeyEvent.KEYCODE_DPAD_DOWN)); - } - - /** - * Obtain the ATS (aim-then-shoot) touch horizontal position change. - * @return The horizontal touch change in position. - */ - public double getTouchDxATS() { - double tempDx = mTouchDxATS; - mTouchDxATS = 0; - return tempDx; - } - - /** - * Obtain the horizontal touch position. - * @return The horizontal touch position. - */ - public double getTouchX() { - return mTouchX; - } - - /** - * Obtain the vertical touch position. - * @return The vertical touch position. - */ - public double getTouchY() { - return mTouchY; - } - - /** - * Obtain the trackball position change. - * @return The trackball position change. - */ - public double getTrackBallDx() { - double tempDx = mTrackballDx; - mTrackballDx = 0; - return tempDx; - } - - public void init() { - this.init_vars(); - mTrackballDx = 0; - mTouchFire = false; - mTouchSwap = false; - mTouchFireATS = false; - mTouchDxATS = 0; - } - - /** - * Process key presses. - * @param keyCode - * @return True if the key press was processed, false if not. - */ - public boolean setKeyDown(int keyCode) { - boolean handled = false; - switch(keyCode) { - case KeyEvent.KEYCODE_DPAD_LEFT: - mLeft = true; - mWasLeft = true; - handled = true; - break; - case KeyEvent.KEYCODE_DPAD_RIGHT: - mRight = true; - mWasRight = true; - handled = true; - break; - case KeyEvent.KEYCODE_DPAD_CENTER: - mCenter = true; - mWasCenter = true; - handled = true; - break; - case KeyEvent.KEYCODE_DPAD_UP: - mUp = true; - mWasUp = true; - handled = true; - break; - case KeyEvent.KEYCODE_DPAD_DOWN: - mDown = true; - mWasDown = true; - handled = true; - break; - default: - break; - } - return handled; - } - - /** - * Process key releases. - * @param keyCode - * @return True if the key release was processed, false if not. - */ - public boolean setKeyUp(int keyCode) { - boolean handled = false; - switch(keyCode) { - case KeyEvent.KEYCODE_DPAD_LEFT: - mLeft = false; - handled = true; - break; - case KeyEvent.KEYCODE_DPAD_RIGHT: - mRight = false; - handled = true; - break; - case KeyEvent.KEYCODE_DPAD_CENTER: - mCenter = false; - handled = true; - break; - case KeyEvent.KEYCODE_DPAD_UP: - mUp = false; - handled = true; - break; - case KeyEvent.KEYCODE_DPAD_DOWN: - mDown = false; - handled = true; - break; - default: - break; - } - return handled; - } - - public boolean setTouchEvent(int event, double x, double y) { - boolean handled = false; - if (mGameThread.mMode == stateEnum.RUNNING) { - // Set the values used when Point To Shoot is on. - if (event == MotionEvent.ACTION_DOWN) { - if (y < GameThread.TOUCH_FIRE_Y_THRESHOLD) { - mTouchFire = true; - mTouchX = x; - mTouchY = y; - } - else if (Math.abs(x - 318) <= GameThread.TOUCH_SWAP_X_THRESHOLD) { - mTouchSwap = true; - } - } - - // Set the values used when Aim Then Shoot is on. - if (event == MotionEvent.ACTION_DOWN) { - if (y < GameThread.ATS_TOUCH_FIRE_Y_THRESHOLD) { - mTouchFireATS = true; - } - mTouchLastX = x; - } - else if (event == MotionEvent.ACTION_MOVE) { - if (y >= GameThread.ATS_TOUCH_FIRE_Y_THRESHOLD) { - mTouchDxATS = (x - mTouchLastX) * GameThread.ATS_TOUCH_COEFFICIENT; - } - mTouchLastX = x; - } - handled = true; - } - return handled; - } - - /** - * Accumulate the change in trackball horizontal position. - * @param trackBallDX - */ - public void setTrackBallDx(double trackBallDX) { - mTrackballDx += trackBallDX; - } - } - - class GameThread extends Thread { - - private static final int FRAME_DELAY = 40; - - public static final double TRACKBALL_COEFFICIENT = 5; - public static final double TOUCH_BUTTON_THRESHOLD = 16; - public static final double TOUCH_FIRE_Y_THRESHOLD = 380; - public static final double TOUCH_SWAP_X_THRESHOLD = 14; - public static final double ATS_TOUCH_COEFFICIENT = 0.2; - public static final double ATS_TOUCH_FIRE_Y_THRESHOLD = 350; - - private boolean mImagesReady = false; - private boolean mRun = false; - private boolean mShowNetwork = false; - private boolean mShowScores = false; - private boolean mSurfaceOK = false; - - private int mDisplayDX; - private int mDisplayDY; - private double mDisplayScale; - private long mLastTime; - private int mPlayer1DX; - private int mPlayer2DX; - - private stateEnum mMode; - private stateEnum mModeWas; - - private Bitmap mBackgroundOrig; - private Bitmap[] mBubblesOrig; - private Bitmap[] mBubblesBlindOrig; - private Bitmap[] mFrozenBubblesOrig; - private Bitmap[] mTargetedBubblesOrig; - private Bitmap mBubbleBlinkOrig; - private Bitmap mGameWonOrig; - private Bitmap mGameLostOrig; - private Bitmap mGamePausedOrig; - private Bitmap mHurryOrig; - private Bitmap mPauseButtonOrig; - private Bitmap mPlayButtonOrig; - private Bitmap mPenguinsOrig; - private Bitmap mPenguins2Orig; - private Bitmap mCompressorHeadOrig; - private Bitmap mCompressorOrig; - private Bitmap mLifeOrig; - private Bitmap mFontImageOrig; - private Bitmap mBananaOrig; - private Bitmap mTomatoOrig; - private BmpWrap mBackground; - private BmpWrap[] mBubbles; - private BmpWrap[] mBubblesBlind; - private BmpWrap[] mFrozenBubbles; - private BmpWrap[] mTargetedBubbles; - private BmpWrap mBubbleBlink; - private BmpWrap mGameWon; - private BmpWrap mGameLost; - private BmpWrap mGamePaused; - private BmpWrap mHurry; - private BmpWrap mPauseButton; - private BmpWrap mPlayButton; - private BmpWrap mPenguins; - private BmpWrap mPenguins2; - private BmpWrap mCompressorHead; - private BmpWrap mCompressor; - private BmpWrap mLife; - private BmpWrap mFontImage; - private BmpWrap mBanana; - private BmpWrap mTomato; - - private BubbleFont mFont; - private Drawable mLauncher; // drawable because we rotate it - private FrozenGame mFrozenGame1; - private FrozenGame mFrozenGame2; - private LevelManager mLevelManager; - private MalusBar malusBar1; - private MalusBar malusBar2; - private SoundManager mSoundManager; - private SurfaceHolder mSurfaceHolder; - - private final HighscoreManager mHighScoreManager; - - Vector mImageList; - - public GameThread(SurfaceHolder surfaceHolder) { - //Log.i("frozen-bubble", "GameThread()"); - mSurfaceHolder = surfaceHolder; - Resources res = mContext.getResources(); - setState(stateEnum.PAUSED); - - BitmapFactory.Options options = new BitmapFactory.Options(); - - /* - * The Options.inScaled field is only available starting at API 4. - */ - try { - Field f = options.getClass().getField("inScaled"); - f.set(options, Boolean.FALSE); - } catch (Exception ignore) {} - - mBackgroundOrig = BitmapFactory.decodeResource( - res, R.drawable.background2, options); - mBubblesOrig = new Bitmap[8]; - mBubblesOrig[0] = BitmapFactory.decodeResource( - res, R.drawable.bubble_1, options); - mBubblesOrig[1] = BitmapFactory.decodeResource( - res, R.drawable.bubble_2, options); - mBubblesOrig[2] = BitmapFactory.decodeResource( - res, R.drawable.bubble_3, options); - mBubblesOrig[3] = BitmapFactory.decodeResource( - res, R.drawable.bubble_4, options); - mBubblesOrig[4] = BitmapFactory.decodeResource( - res, R.drawable.bubble_5, options); - mBubblesOrig[5] = BitmapFactory.decodeResource( - res, R.drawable.bubble_6, options); - mBubblesOrig[6] = BitmapFactory.decodeResource( - res, R.drawable.bubble_7, options); - mBubblesOrig[7] = BitmapFactory.decodeResource( - res, R.drawable.bubble_8, options); - mBubblesBlindOrig = new Bitmap[8]; - mBubblesBlindOrig[0] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_1, options); - mBubblesBlindOrig[1] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_2, options); - mBubblesBlindOrig[2] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_3, options); - mBubblesBlindOrig[3] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_4, options); - mBubblesBlindOrig[4] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_5, options); - mBubblesBlindOrig[5] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_6, options); - mBubblesBlindOrig[6] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_7, options); - mBubblesBlindOrig[7] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_8, options); - mFrozenBubblesOrig = new Bitmap[8]; - mFrozenBubblesOrig[0] = BitmapFactory.decodeResource( - res, R.drawable.frozen_1, options); - mFrozenBubblesOrig[1] = BitmapFactory.decodeResource( - res, R.drawable.frozen_2, options); - mFrozenBubblesOrig[2] = BitmapFactory.decodeResource( - res, R.drawable.frozen_3, options); - mFrozenBubblesOrig[3] = BitmapFactory.decodeResource( - res, R.drawable.frozen_4, options); - mFrozenBubblesOrig[4] = BitmapFactory.decodeResource( - res, R.drawable.frozen_5, options); - mFrozenBubblesOrig[5] = BitmapFactory.decodeResource( - res, R.drawable.frozen_6, options); - mFrozenBubblesOrig[6] = BitmapFactory.decodeResource( - res, R.drawable.frozen_7, options); - mFrozenBubblesOrig[7] = BitmapFactory.decodeResource( - res, R.drawable.frozen_8, options); - mTargetedBubblesOrig = new Bitmap[6]; - mTargetedBubblesOrig[0] = BitmapFactory.decodeResource( - res, R.drawable.fixed_1, options); - mTargetedBubblesOrig[1] = BitmapFactory.decodeResource( - res, R.drawable.fixed_2, options); - mTargetedBubblesOrig[2] = BitmapFactory.decodeResource( - res, R.drawable.fixed_3, options); - mTargetedBubblesOrig[3] = BitmapFactory.decodeResource( - res, R.drawable.fixed_4, options); - mTargetedBubblesOrig[4] = BitmapFactory.decodeResource( - res, R.drawable.fixed_5, options); - mTargetedBubblesOrig[5] = BitmapFactory.decodeResource( - res, R.drawable.fixed_6, options); - mBubbleBlinkOrig = BitmapFactory.decodeResource( - res, R.drawable.bubble_blink, options); - mGameWonOrig = BitmapFactory.decodeResource( - res, R.drawable.win_panel, options); - mGameLostOrig = BitmapFactory.decodeResource( - res, R.drawable.lose_panel, options); - mGamePausedOrig = BitmapFactory.decodeResource( - res, R.drawable.pause_panel, options); - mHurryOrig = BitmapFactory.decodeResource( - res, R.drawable.hurry, options); - mPauseButtonOrig = BitmapFactory.decodeResource( - res, R.drawable.pause_button, options); - mPlayButtonOrig = BitmapFactory.decodeResource( - res, R.drawable.play_button, options); - mPenguinsOrig = BitmapFactory.decodeResource( - res, R.drawable.penguins, options); - mPenguins2Orig = BitmapFactory.decodeResource( - res, R.drawable.penguins2, options); - mCompressorHeadOrig = BitmapFactory.decodeResource( - res, R.drawable.compressor, options); - mCompressorOrig = BitmapFactory.decodeResource( - res, R.drawable.compressor_body, options); - mLifeOrig = BitmapFactory.decodeResource( - res, R.drawable.life, options); - mFontImageOrig = BitmapFactory.decodeResource( - res, R.drawable.bubble_font, options); - mBananaOrig = BitmapFactory.decodeResource( - res, R.drawable.banana, options); - mTomatoOrig = BitmapFactory.decodeResource( - res, R.drawable.tomato, options); - - mImageList = new Vector(); - - mBubbles = new BmpWrap[8]; - for (int i = 0; i < mBubbles.length; i++) { - mBubbles[i] = NewBmpWrap(); - } - - mBubblesBlind = new BmpWrap[8]; - for (int i = 0; i < mBubblesBlind.length; i++) { - mBubblesBlind[i] = NewBmpWrap(); - } - - mFrozenBubbles = new BmpWrap[8]; - for (int i = 0; i < mFrozenBubbles.length; i++) { - mFrozenBubbles[i] = NewBmpWrap(); - } - - mTargetedBubbles = new BmpWrap[6]; - for (int i = 0; i < mTargetedBubbles.length; i++) { - mTargetedBubbles[i] = NewBmpWrap(); - } - - mBackground = NewBmpWrap(); - mBubbleBlink = NewBmpWrap(); - mGameWon = NewBmpWrap(); - mGameLost = NewBmpWrap(); - mGamePaused = NewBmpWrap(); - mHurry = NewBmpWrap(); - mPauseButton = NewBmpWrap(); - mPlayButton = NewBmpWrap(); - mPenguins = NewBmpWrap(); - mPenguins2 = NewBmpWrap(); - mCompressorHead = NewBmpWrap(); - mCompressor = NewBmpWrap(); - mLife = NewBmpWrap(); - mFontImage = NewBmpWrap(); - mBanana = NewBmpWrap(); - mTomato = NewBmpWrap(); - - mFont = new BubbleFont(mFontImage); - mLauncher = res.getDrawable(R.drawable.launcher); - mSoundManager = new SoundManager(mContext); - - /* - * Only keep a high score database when the opponent is the CPU. - */ - if (mRemoteInput.isCPU) { - mHighScoreManager = new HighscoreManager(getContext(), - HighscoreManager. - MULTIPLAYER_DATABASE_NAME); - } - else { - mHighScoreManager = null; - } - - mLevelManager = new LevelManager(0, FrozenBubble.getDifficulty()); - newGame(false); - } - - public GameThread(SurfaceHolder surfaceHolder, byte[] customLevels, - int startingLevel, boolean arcadeGame) { - //Log.i("frozen-bubble", "GameThread()"); - mSurfaceHolder = surfaceHolder; - Resources res = mContext.getResources(); - setState(stateEnum.PAUSED); - - BitmapFactory.Options options = new BitmapFactory.Options(); - - /* - * The Options.inScaled field is only available starting at API 4. - */ - try { - Field f = options.getClass().getField("inScaled"); - f.set(options, Boolean.FALSE); - } catch (Exception ignore) {} - - mBackgroundOrig = BitmapFactory.decodeResource( - res, R.drawable.background, options); - mBubblesOrig = new Bitmap[8]; - mBubblesOrig[0] = BitmapFactory.decodeResource( - res, R.drawable.bubble_1, options); - mBubblesOrig[1] = BitmapFactory.decodeResource( - res, R.drawable.bubble_2, options); - mBubblesOrig[2] = BitmapFactory.decodeResource( - res, R.drawable.bubble_3, options); - mBubblesOrig[3] = BitmapFactory.decodeResource( - res, R.drawable.bubble_4, options); - mBubblesOrig[4] = BitmapFactory.decodeResource( - res, R.drawable.bubble_5, options); - mBubblesOrig[5] = BitmapFactory.decodeResource( - res, R.drawable.bubble_6, options); - mBubblesOrig[6] = BitmapFactory.decodeResource( - res, R.drawable.bubble_7, options); - mBubblesOrig[7] = BitmapFactory.decodeResource( - res, R.drawable.bubble_8, options); - mBubblesBlindOrig = new Bitmap[8]; - mBubblesBlindOrig[0] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_1, options); - mBubblesBlindOrig[1] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_2, options); - mBubblesBlindOrig[2] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_3, options); - mBubblesBlindOrig[3] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_4, options); - mBubblesBlindOrig[4] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_5, options); - mBubblesBlindOrig[5] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_6, options); - mBubblesBlindOrig[6] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_7, options); - mBubblesBlindOrig[7] = BitmapFactory.decodeResource( - res, R.drawable.bubble_colourblind_8, options); - mFrozenBubblesOrig = new Bitmap[8]; - mFrozenBubblesOrig[0] = BitmapFactory.decodeResource( - res, R.drawable.frozen_1, options); - mFrozenBubblesOrig[1] = BitmapFactory.decodeResource( - res, R.drawable.frozen_2, options); - mFrozenBubblesOrig[2] = BitmapFactory.decodeResource( - res, R.drawable.frozen_3, options); - mFrozenBubblesOrig[3] = BitmapFactory.decodeResource( - res, R.drawable.frozen_4, options); - mFrozenBubblesOrig[4] = BitmapFactory.decodeResource( - res, R.drawable.frozen_5, options); - mFrozenBubblesOrig[5] = BitmapFactory.decodeResource( - res, R.drawable.frozen_6, options); - mFrozenBubblesOrig[6] = BitmapFactory.decodeResource( - res, R.drawable.frozen_7, options); - mFrozenBubblesOrig[7] = BitmapFactory.decodeResource( - res, R.drawable.frozen_8, options); - mTargetedBubblesOrig = new Bitmap[6]; - mTargetedBubblesOrig[0] = BitmapFactory.decodeResource( - res, R.drawable.fixed_1, options); - mTargetedBubblesOrig[1] = BitmapFactory.decodeResource( - res, R.drawable.fixed_2, options); - mTargetedBubblesOrig[2] = BitmapFactory.decodeResource( - res, R.drawable.fixed_3, options); - mTargetedBubblesOrig[3] = BitmapFactory.decodeResource( - res, R.drawable.fixed_4, options); - mTargetedBubblesOrig[4] = BitmapFactory.decodeResource( - res, R.drawable.fixed_5, options); - mTargetedBubblesOrig[5] = BitmapFactory.decodeResource( - res, R.drawable.fixed_6, options); - mBubbleBlinkOrig = BitmapFactory.decodeResource( - res, R.drawable.bubble_blink, options); - mGameWonOrig = BitmapFactory.decodeResource( - res, R.drawable.win_panel, options); - mGameLostOrig = BitmapFactory.decodeResource( - res, R.drawable.lose_panel, options); - mGamePausedOrig = BitmapFactory.decodeResource( - res, R.drawable.pause_panel, options); - mHurryOrig = BitmapFactory.decodeResource( - res, R.drawable.hurry, options); - mPauseButtonOrig = null; - mPlayButtonOrig = null; - mPenguinsOrig = BitmapFactory.decodeResource( - res, R.drawable.penguins, options); - mPenguins2Orig = null; - mCompressorHeadOrig = BitmapFactory.decodeResource( - res, R.drawable.compressor, options); - mCompressorOrig = BitmapFactory.decodeResource( - res, R.drawable.compressor_body, options); - mLifeOrig = BitmapFactory.decodeResource( - res, R.drawable.life, options); - mFontImageOrig = BitmapFactory.decodeResource( - res, R.drawable.bubble_font, options); - mBananaOrig = null; - mTomatoOrig = null; - - mImageList = new Vector(); - - mBubbles = new BmpWrap[8]; - for (int i = 0; i < mBubbles.length; i++) { - mBubbles[i] = NewBmpWrap(); - } - - mBubblesBlind = new BmpWrap[8]; - for (int i = 0; i < mBubblesBlind.length; i++) { - mBubblesBlind[i] = NewBmpWrap(); - } - - mFrozenBubbles = new BmpWrap[8]; - for (int i = 0; i < mFrozenBubbles.length; i++) { - mFrozenBubbles[i] = NewBmpWrap(); - } - - mTargetedBubbles = new BmpWrap[6]; - for (int i = 0; i < mTargetedBubbles.length; i++) { - mTargetedBubbles[i] = NewBmpWrap(); - } - - mBackground = NewBmpWrap(); - mBubbleBlink = NewBmpWrap(); - mGameWon = NewBmpWrap(); - mGameLost = NewBmpWrap(); - mGamePaused = NewBmpWrap(); - mHurry = NewBmpWrap(); - mPauseButton = null; - mPlayButton = null; - mPenguins = NewBmpWrap(); - mPenguins2 = null; - mCompressorHead = NewBmpWrap(); - mCompressor = NewBmpWrap(); - mLife = NewBmpWrap(); - mFontImage = NewBmpWrap(); - mBanana = null; - mTomato = null; - - mFont = new BubbleFont(mFontImage); - mLauncher = res.getDrawable(R.drawable.launcher); - mSoundManager = new SoundManager(mContext); - - if (arcadeGame) { - mHighScoreManager = - new HighscoreManager(getContext(), - HighscoreManager.ARCADE_DATABASE_NAME); - mLevelManager = new LevelManager(System.currentTimeMillis(), - FrozenBubble.getDifficulty()); - } - else { - mHighScoreManager = - new HighscoreManager(getContext(), - HighscoreManager.PUZZLE_DATABASE_NAME); - if (null == customLevels) { - try { - InputStream is = mContext.getAssets().open("levels.txt"); - int size = is.available(); - byte[] levels = new byte[size]; - is.read(levels); - is.close(); - SharedPreferences sp = mContext.getSharedPreferences( - FrozenBubble.PREFS_NAME, Context.MODE_PRIVATE); - startingLevel = sp.getInt("level", 0); - mLevelManager = new LevelManager(levels, startingLevel); - } catch (IOException e) { - /* - * Should never happen. - */ - throw new RuntimeException(e); - } - } - else { - /* - * We were launched by the level editor. - */ - mLevelManager = new LevelManager(customLevels, startingLevel); - } - } - - newGame(false); - } - - public void cleanUp() { - synchronized(mSurfaceHolder) { - /* - * I don't really understand why all this is necessary. - * I used to get a crash (an out-of-memory error) once every six or - * seven times I started the game. I googled the error and someone - * said you have to call recycle() on all the bitmaps and set - * the pointers to null to facilitate garbage collection. So I did - * and the crashes went away. - */ - mImagesReady = false; - mFrozenGame1 = null; - mFrozenGame2 = null; - - mBackgroundOrig.recycle(); - mBackgroundOrig = null; - - for (int i = 0; i < mBubblesOrig.length; i++) { - mBubblesOrig[i].recycle(); - mBubblesOrig[i] = null; - } - mBubblesOrig = null; - - for (int i = 0; i < mBubblesBlindOrig.length; i++) { - mBubblesBlindOrig[i].recycle(); - mBubblesBlindOrig[i] = null; - } - mBubblesBlindOrig = null; - - for (int i = 0; i < mFrozenBubblesOrig.length; i++) { - mFrozenBubblesOrig[i].recycle(); - mFrozenBubblesOrig[i] = null; - } - mFrozenBubblesOrig = null; - - for (int i = 0; i < mTargetedBubblesOrig.length; i++) { - mTargetedBubblesOrig[i].recycle(); - mTargetedBubblesOrig[i] = null; - } - mTargetedBubblesOrig = null; - - mBubbleBlinkOrig.recycle(); - mBubbleBlinkOrig = null; - mGameWonOrig.recycle(); - mGameWonOrig = null; - mGameLostOrig.recycle(); - mGameLostOrig = null; - mGamePausedOrig.recycle(); - mGamePausedOrig = null; - mHurryOrig.recycle(); - mHurryOrig = null; - if (mPauseButtonOrig != null) { - mPauseButtonOrig.recycle(); - } - mPauseButtonOrig = null; - if (mPlayButtonOrig != null) { - mPlayButtonOrig.recycle(); - } - mPlayButtonOrig = null; - mPenguinsOrig.recycle(); - mPenguinsOrig = null; - if (mPenguins2Orig != null) { - mPenguins2Orig.recycle(); - } - mPenguins2Orig = null; - mCompressorHeadOrig.recycle(); - mCompressorHeadOrig = null; - mCompressorOrig.recycle(); - mCompressorOrig = null; - mLifeOrig.recycle(); - mLifeOrig = null; - mFontImageOrig.recycle(); - mFontImageOrig = null; - if (mBananaOrig != null) { - mBananaOrig.recycle(); - } - mBananaOrig = null; - if (mTomatoOrig != null) { - mTomatoOrig.recycle(); - } - mTomatoOrig = null; - - /* - * All the scalable bitmaps are located within the image list, - * so recycling all the bitmaps in this list ensures they are - * all recycled. - */ - int size = mImageList.size(); - while (size > 0) { - BmpWrap bmpWrap = mImageList.elementAt(--size); - /* - * If the bitmaps were not scaled, then they will already have - * been recycled. - */ - if (bmpWrap.bmp != null) { - bmpWrap.bmp.recycle(); - } - bmpWrap.bmp = null; - } - mImageList.clear(); - mImageList = null; - - mBackground = null; - - for (int i = 0; i < mBubbles.length; i++) { - mBubbles[i] = null; - } - mBubbles = null; - - for (int i = 0; i < mBubblesBlind.length; i++) { - mBubblesBlind[i] = null; - } - mBubblesBlind = null; - - for (int i = 0; i < mFrozenBubbles.length; i++) { - mFrozenBubbles[i] = null; - } - mFrozenBubbles = null; - - for (int i = 0; i < mTargetedBubbles.length; i++) { - mTargetedBubbles[i] = null; - } - mTargetedBubbles = null; - - mBubbleBlink = null; - mGameWon = null; - mGameLost = null; - mGamePaused = null; - mHurry = null; - mPauseButton = null; - mPlayButton = null; - mPenguins = null; - mPenguins2 = null; - mCompressorHead = null; - mCompressor = null; - mLife = null; - mFontImage = null; - mBanana = null; - mTomato = null; - - mSoundManager.cleanUp(); - mSoundManager = null; - mLevelManager = null; - - if (mHighScoreManager != null) { - mHighScoreManager.close(); - } - } - } - - private void doDraw(Canvas canvas) { - //Log.i("frozen-bubble", "doDraw()"); - if (!mImagesReady) { - //Log.i("frozen-bubble", "!mImagesReady, returning"); - return; - } - if ((mDisplayDX > 0) || (mDisplayDY > 0)) { - //Log.i("frozen-bubble", "Drawing black background."); - canvas.drawRGB(0, 0, 0); - } - drawBackground(canvas); - if (mFrozenGame1 != null) { - mFrozenGame1.paint(canvas, mDisplayScale, mPlayer1DX, mDisplayDY); - } - if (FrozenBubble.arcadeGame) { - drawDifficulty(canvas); - } - else if (numPlayers > 1) { - if (mFrozenGame2 != null) { - mFrozenGame2.paint(canvas, mDisplayScale, mPlayer2DX, mDisplayDY); - } - drawWinTotals(canvas); - } - else { - drawLevelNumber(canvas); - } - } - - /** - * Process key presses. This must be allowed to run regardless of - * the game state to correctly handle initial game conditions. - * @param keyCode - the static KeyEvent key identifier. - * @param msg - the key action message. - * @return - true if the key action is processed. - * @see android.view.View#onKeyDown(int, android.view.KeyEvent) - */ - boolean doKeyDown(int keyCode, KeyEvent msg) { - boolean handled = false; - /* - * Only update the game state if this is a fresh key press. - */ - if (mLocalInput.checkNewActionKeyPress(keyCode)) - updateStateOnEvent(null); - - /* - * Process the key press if it is a function key. - */ - toggleKeyPress(keyCode, true, true); - - /* - * Process the key press if it is a game input key. - */ - synchronized(mSurfaceHolder) { - handled = mLocalInput.setKeyDown(keyCode); - } - return handled; - } - /** - * Process key releases. This must be allowed to run regardless of - * the game state in order to properly clear key presses. - * @param keyCode - the static KeyEvent key identifier. - * @param msg - the key action message. - * @return - true if the key action is processed. - * @see android.view.View#onKeyUp(int, android.view.KeyEvent) - */ - boolean doKeyUp(int keyCode, KeyEvent msg) { - boolean handled = false; - /* - * Process the key release if it is a game input key. - */ - synchronized(mSurfaceHolder) { - handled = mLocalInput.setKeyUp(keyCode); - } - return handled; - } - - /** - * This method handles screen touch motion events. - *

This method will be called three times in succession for each - * touch, to process ACTION_DOWN, - * ACTION_UP, and ACTION_MOVE. - * @param event - the motion event. - * @return true if the event was handled. - */ - boolean doTouchEvent(MotionEvent event) { - boolean handled = false; - double x_offset; - double x = xFromScr(event.getX()); - double y = yFromScr(event.getY()); - - if (mLocalInput.playerID == VirtualInput.PLAYER2) { - x_offset = -318; - } - else { - x_offset = 0; - } - /* - * Check for a pause button sprite press. This will toggle the - * pause button sprite between pause and play. If the game was - * previously paused by the pause button, ignore screen touches - * that aren't on the pause button sprite. - */ - if (event.getAction() == MotionEvent.ACTION_DOWN) { - if ((Math.abs(x - 183) <= TOUCH_BUTTON_THRESHOLD) && - (Math.abs(y - 460) <= TOUCH_BUTTON_THRESHOLD)) { - toggleKeyPress(KeyEvent.KEYCODE_P, false, true); - } - else if (toggleKeyState(KeyEvent.KEYCODE_P)) { - return false; - } - } - - /* - * Update the game state (paused, running, etc.) if necessary. - */ - if(updateStateOnEvent(event)) { - return true; - } - - /* - * If the game is running and the pause button sprite was pressed, - * pause the game. - */ - if ((mMode == stateEnum.RUNNING) && - (toggleKeyState(KeyEvent.KEYCODE_P))) { - pause(); - } - - /* - * Process the screen touch event. - */ - synchronized(mSurfaceHolder) { - handled = mLocalInput.setTouchEvent(event.getAction(), x + x_offset, y); - } - return handled; - } - - /** - * Process trackball motion events. - *

This method only processes trackball motion for the purpose of - * aiming the launcher. The trackball has no effect on the game - * state, much like moving a mouse cursor over a screen does not - * perform any intrinsic actions in most applications. - * @param event - the motion event associated with the trackball. - * @return This function returns true if the trackball - * motion was processed, which notifies the caller that this method - * handled the motion event and no other handling is necessary. - */ - boolean doTrackballEvent(MotionEvent event) { - boolean handled = false; - if (mMode == stateEnum.RUNNING) { - if (event.getAction() == MotionEvent.ACTION_MOVE) { - synchronized(mSurfaceHolder) { - mLocalInput.setTrackBallDx(event.getX() * TRACKBALL_COEFFICIENT); - } - handled = true; - } - } - return handled; - } - - private void drawAboutScreen(Canvas canvas) { - canvas.drawRGB(0, 0, 0); - if (!mBlankScreen) { - int x = drawTextOffsetX(); - int y = 20; - int ysp = 26; - int indent = 10; - mFont.print("original frozen bubble:", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - mFont.print("guillaume cottenceau", x + indent, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - mFont.print("alexis younes", x + indent, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - mFont.print("amaury amblard-ladurantie", x + indent, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - mFont.print("matthias le bidan", x + indent, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - y += ysp; - mFont.print("java version:", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - mFont.print("glenn sanson", x + indent, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - y += ysp; - mFont.print("android port:", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - mFont.print("aleksander fedorynski", x + indent, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - mFont.print("eric fortin", x + indent, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += 2 * ysp; - mFont.print("android port source code", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - mFont.print("is available at:", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - mFont.print("http://code.google.com", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - mFont.print("/p/frozenbubbleandroid", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - } - - private void drawBackground(Canvas c) { - Sprite.drawImage(mBackground, 0, 0, c, mDisplayScale, - mDisplayDX, mDisplayDY); - } - - private void drawDifficulty(Canvas canvas) { - int y = 433; - int x = 159; - int level = mLevelManager.getLevelIndex(); - mFont.print(LevelManager.DifficultyStrings[level], x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - - /** - * Draw the high score screen for puzzle game mode. - *

The objective of puzzle game mode is efficiency - fire as few - * bubbles as possible as quickly as possible. Thus the high score - * will exhibit the fewest shots fired the quickest. - * @param canvas - the drawing canvas to display the scores on. - * @param level - the level index. - */ - private void drawHighScoreScreen(Canvas canvas, int level) { - if (mHighScoreManager == null) { - mShowScores = false; - return; - } - - canvas.drawRGB(0, 0, 0); - int x = drawTextOffsetX(); - int y = 20; - int ysp = 26; - int indent = 10; - - mFont.print("highscore for level " + (level + 1), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += 2 * ysp; - - List hlist = mHighScoreManager.getHighScore(level, 15); - long lastScoreId = mHighScoreManager.getLastScoreId(); - int i = 1; - for (HighscoreDO hdo : hlist) { - String you = ""; - if (lastScoreId == hdo.getId()) { - you = "|"; - } - // TODO: Add player name support. - // mFont.print(you + i++ + " - " + hdo.getName().toLowerCase() - // + " - " - // + hdo.getShots() - // + " - " + (hdo.getTime() / 1000) - // + " sec", x + indent, - // y, canvas, - // mDisplayScale, mDisplayDX, mDisplayDY); - mFont.print(you + i++ + " - " - + hdo.getShots() - + " shots - " - + (hdo.getTime() / 1000) - + " sec", x + indent, - y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - } - } - - private void drawLevelNumber(Canvas canvas) { - int y = 433; - int x; - int level = mLevelManager.getLevelIndex() + 1; - if (level < 10) { - x = 185; - mFont.paintChar(Character.forDigit(level, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - else if (level < 100) { - x = 178; - x += mFont.paintChar(Character.forDigit(level / 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - mFont.paintChar(Character.forDigit(level % 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - else { - x = 173; - x += mFont.paintChar(Character.forDigit(level / 100, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - level -= 100 * (level / 100); - x += mFont.paintChar(Character.forDigit(level / 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - mFont.paintChar(Character.forDigit(level % 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - } - - /** - * Draw the low score screen for arcade and multiplayer game modes. - *

The objective of arcade and multiplayer games is endurance - - * fire as many bubbles as possible for as long as possible. Thus - * the low score will exhibit the most shots fired during the - * longest game. - * @param canvas - the drawing canvas to display the scores on. - * @param level - the level difficulty index. - */ - private void drawLowScoreScreen(Canvas canvas, int level) { - if (mHighScoreManager == null) { - mShowScores = false; - return; - } - - canvas.drawRGB(0, 0, 0); - int x = drawTextOffsetX(); - int y = 20; - int ysp = 26; - int indent = 10; - - mFont.print("highscore for " + - LevelManager.DifficultyStrings[mHighScoreManager.getLevel()], - x, y, canvas, mDisplayScale, mDisplayDX, mDisplayDY); - y += 2 * ysp; - - List hlist = mHighScoreManager.getLowScore(level, 15); - long lastScoreId = mHighScoreManager.getLastScoreId(); - int i = 1; - for (HighscoreDO hdo : hlist) { - String you = ""; - if (lastScoreId == hdo.getId()) { - you = "|"; - } - // TODO: Add player name support. - // mFont.print(you + i++ + " - " + hdo.getName().toLowerCase() - // + " - " - // + hdo.getShots() - // + " - " + (hdo.getTime() / 1000) - // + " sec", x + indent, - // y, canvas, - // mDisplayScale, mDisplayDX, mDisplayDY); - mFont.print(you + i++ + " - " - + hdo.getShots() - + " shots - " - + (hdo.getTime() / 1000) - + " sec", x + indent, - y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - } - } - - private void drawNetworkScreen(Canvas canvas) { - if (mNetworkManager == null) { - mShowNetwork = false; - return; - } - - canvas.drawRGB(0, 0, 0); - int x = drawTextOffsetX(); - int y = 20; - int ysp = 26; - - NetworkStatus status = new NetworkStatus(); - mNetworkManager.updateNetworkStatus(status); - - if (gameLocale == FrozenBubble.LOCALE_WIFI) { - if (status.isConnected) { - mFont.print("wifi status: ]", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - } - else { - mFont.print("wifi status: _", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - } - } - else if (gameLocale == FrozenBubble.LOCALE_BLUETOOTH) { - if (status.isConnected) { - mFont.print("bluetooth status: ]", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - } - else { - mFont.print("bluetooth status: _", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - } - } - - mFont.print("my address: " + status.localIpAddress, x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - - mFont.print("connect to: " + status.remoteIpAddress, x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - - if (status.playerJoined) { - mFont.print("waiting for player " + status.remotePlayerId + "...|", - x, y, canvas, mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - } - else { - mFont.print("waiting for player " + status.remotePlayerId + "...", - x, y, canvas, mDisplayScale, mDisplayDX, mDisplayDY); - return; - } - - if (status.localPlayerId == VirtualInput.PLAYER2) { - if (status.gotPrefsData || status.readyToPlay) { - mFont.print("getting preferences...|", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - } - else { - mFont.print("getting preferences...", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - return; - } - } - - if (status.gotFieldData || status.readyToPlay) { - mFont.print("getting data...|", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - } - else { - mFont.print("getting data...", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - return; - } - - if (status.readyToPlay) { - mFont.print("waiting for game start...|", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - y += ysp; - } - else { - mFont.print("waiting for game start...", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - return; - } - - mFont.print("tap to begin playing!", x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - - /** - * Obtain the horizontal offset to approximately center a line of - * 20 characters in the screen for the current device orientation. - * @return The horizontal offset. - */ - private int drawTextOffsetX() { - int x = (int) (GAMEFIELD_WIDTH * 0.55f); - int orientation = getScreenOrientation(); - - if (numPlayers == 2) { - if ((orientation == FrozenBubble.SCREEN_ORIENTATION_REVERSE_PORTRAIT) || - (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)) { - if (mLocalInput.playerID == VirtualInput.PLAYER2) { - x = (int) -((float) mDisplayDX / mDisplayScale) + 5; - } - else { - x = mDisplayDX + 5; - } - } - } - - return x; - } - - private void drawWinTotals(Canvas canvas) { - int y = 433; - int x = GAMEFIELD_WIDTH - 40; - int gamesWon1 = numPlayer1GamesWon; - int gamesWon2 = numPlayer2GamesWon; - - if (numPlayer1GamesWon < 10) { - x += 12; - x += mFont.paintChar(Character.forDigit(gamesWon1, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - else if (numPlayer1GamesWon < 100) { - x += 5; - x += mFont.paintChar(Character.forDigit(gamesWon1 / 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - x += mFont.paintChar(Character.forDigit(gamesWon1 % 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - else { - x += mFont.paintChar(Character.forDigit(gamesWon1 / 100, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - gamesWon1 -= 100 * (gamesWon1 / 100); - x += mFont.paintChar(Character.forDigit(gamesWon1 / 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - x += mFont.paintChar(Character.forDigit(gamesWon1 % 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - x += 7; - x += mFont.paintChar('-', x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - x += 7; - if (numPlayer2GamesWon < 10) { - x += mFont.paintChar(Character.forDigit(gamesWon2, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - else if (numPlayer2GamesWon < 100) { - x += mFont.paintChar(Character.forDigit(gamesWon2 / 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - x += mFont.paintChar(Character.forDigit(gamesWon2 % 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - else { - x += mFont.paintChar(Character.forDigit(gamesWon2 / 100, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - gamesWon1 -= 100 * (gamesWon2 / 100); - x += mFont.paintChar(Character.forDigit(gamesWon2 / 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - x += mFont.paintChar(Character.forDigit(gamesWon2 % 10, 10), x, y, canvas, - mDisplayScale, mDisplayDX, mDisplayDY); - } - } - - public boolean gameInProgress() { - return !mShowNetwork; - } - - public int getCurrentLevelIndex() { - return mLevelManager.getLevelIndex(); - } - - private int getScreenOrientation() { - return FrozenBubble.getScreenOrientation(((Activity) mContext). - getWindowManager()); - } - - private BmpWrap NewBmpWrap() { - int new_img_id = mImageList.size(); - BmpWrap new_img = new BmpWrap(new_img_id); - mImageList.addElement(new_img); - return new_img; - } - - /** - * Start a new game. - * @param firstLevel if true, start a new game in - * puzzle mode beginning at the first level. - */ - public void newGame(boolean firstLevel) { - game1Status = gameEnum.PLAYING; - synchronized(mSurfaceHolder) { - if (numPlayers > 1) { - malusBar1 = new MalusBar(GameView.GAMEFIELD_WIDTH - 164, 40, - mBanana, mTomato); - malusBar2 = new MalusBar(GameView.GAMEFIELD_WIDTH + 134, 40, - mBanana, mTomato); - } - else { - malusBar1 = null; - malusBar2 = null; - if (!FrozenBubble.arcadeGame && firstLevel && (numPlayers == 1)) { - mLevelManager.goToFirstLevel(); - } - } - - mImagesReady = false; - mPlayer1.setGameRef(null); - mFrozenGame1 = new FrozenGame(mBackground, mBubbles, mBubblesBlind, - mFrozenBubbles, mTargetedBubbles, - mBubbleBlink, mGameWon, mGameLost, - mGamePaused, mHurry, - mPauseButton, mPlayButton, mPenguins, - mCompressorHead, mCompressor, - malusBar2, mLauncher, - mSoundManager, mLevelManager, - mHighScoreManager, mNetworkManager, - mPlayer1); - mPlayer1.setGameRef(mFrozenGame1); - - if (numPlayers > 1) { - mPlayer2.setGameRef(null); - mFrozenGame2 = new FrozenGame(mBackground, mBubbles, mBubblesBlind, - mFrozenBubbles, mTargetedBubbles, - mBubbleBlink, mGameWon, mGameLost, - mGamePaused, mHurry, - null, null, mPenguins2, - mCompressorHead, mCompressor, - malusBar1, mLauncher, - mSoundManager, mLevelManager, - null, mNetworkManager, - mPlayer2); - mPlayer2.setGameRef(mFrozenGame2); - - if (mNetworkManager != null) { - mNetworkManager.newGame(); - mShowNetwork = true; - } - } - - mImagesReady = true; - } - - if (mHighScoreManager != null) { - mHighScoreManager.startLevel(mLevelManager.getLevelIndex()); - } - - startOpponent(); - } - - private void nextLevel() { - mLevelManager.goToNextLevel(); - newGame(false); - } - - public void pause() { - synchronized(mSurfaceHolder) { - if (mMode == stateEnum.RUNNING) { - setState(stateEnum.PAUSED); - - if (mGameListener != null) - mGameListener.onGameEvent(eventEnum.GAME_PAUSED); - if (mFrozenGame1 != null) - mFrozenGame1.pause(); - if (mFrozenGame2 != null) - mFrozenGame2.pause(); - if (mHighScoreManager != null) - mHighScoreManager.pauseLevel(); - } - } - } - - public void pauseButtonPressed(boolean pauseKeyPressed) { - if (mFrozenGame1 != null) { - mFrozenGame1.pauseButtonPressed(pauseKeyPressed); - } - } - - private void resizeBitmaps() { - //Log.i("frozen-bubble", "resizeBitmaps()"); - scaleFrom(mBackground, mBackgroundOrig); - for (int i = 0; i < mBubblesOrig.length; i++) { - scaleFrom(mBubbles[i], mBubblesOrig[i]); - } - for (int i = 0; i < mBubblesBlind.length; i++) { - scaleFrom(mBubblesBlind[i], mBubblesBlindOrig[i]); - } - for (int i = 0; i < mFrozenBubbles.length; i++) { - scaleFrom(mFrozenBubbles[i], mFrozenBubblesOrig[i]); - } - for (int i = 0; i < mTargetedBubbles.length; i++) { - scaleFrom(mTargetedBubbles[i], mTargetedBubblesOrig[i]); - } - scaleFrom(mBubbleBlink, mBubbleBlinkOrig); - scaleFrom(mGameWon, mGameWonOrig); - scaleFrom(mGameLost, mGameLostOrig); - scaleFrom(mGamePaused, mGamePausedOrig); - scaleFrom(mHurry, mHurryOrig); - if ((mPauseButton != null) && (mPauseButtonOrig != null)) { - scaleFrom(mPauseButton, mPauseButtonOrig); - } - if ((mPlayButton != null) && (mPlayButtonOrig != null)) { - scaleFrom(mPlayButton, mPlayButtonOrig); - } - scaleFrom(mPenguins, mPenguinsOrig); - if ((mPenguins2 != null) && (mPenguins2Orig != null)) { - scaleFrom(mPenguins2, mPenguins2Orig); - } - scaleFrom(mCompressorHead, mCompressorHeadOrig); - scaleFrom(mCompressor, mCompressorOrig); - scaleFrom(mLife, mLifeOrig); - scaleFrom(mFontImage, mFontImageOrig); - if ((mBanana != null) && (mBananaOrig != null)) { - scaleFrom(mBanana, mBananaOrig); - } - if ((mTomato != null) && (mTomatoOrig != null)) { - scaleFrom(mTomato, mTomatoOrig); - } - //Log.i("frozen-bubble", "resizeBitmaps done."); - mImagesReady = true; - } - - /** - * Restores game state from the indicated Bundle. Typically called - * when the Activity is being restored after having been previously - * destroyed. - * @param savedState - Bundle containing the game state. - */ - public void restoreState(Bundle map) { - synchronized(mSurfaceHolder) { - setState(stateEnum.PAUSED); - if (mFrozenGame1 != null) { - mFrozenGame1.restoreState(map, mImageList); - } - if (numPlayers > 1) { - numPlayer1GamesWon = map.getInt("numPlayer1GamesWon", 0); - numPlayer2GamesWon = map.getInt("numPlayer2GamesWon", 0); - if (mFrozenGame2 != null) { - mFrozenGame2.restoreState(map, mImageList); - startOpponent(); - } - } - if (mLevelManager != null) { - mLevelManager.restoreState(map); - } - if (mHighScoreManager != null) { - mHighScoreManager.restoreState(map); - } - } - } - - public void resumeGame() { - synchronized(mSurfaceHolder) { - if (mMode == stateEnum.RUNNING) { - if (mFrozenGame1 != null) { - mFrozenGame1.resume(); - } - if ((numPlayers > 1) && (mFrozenGame2 != null)) { - mFrozenGame2.resume(); - } - if (mHighScoreManager != null) { - mHighScoreManager.resumeLevel(); - } - } - } - } - - @Override - public void run() { - while (mRun) { - long now = System.currentTimeMillis(); - long delay = FRAME_DELAY + mLastTime - now; - if (delay > 0) try { - sleep(delay); - } catch (InterruptedException e) {} - mLastTime = now; - Canvas c = null; - try { - if (surfaceOK()) { - c = mSurfaceHolder.lockCanvas(null); - if (c != null) { - synchronized(mSurfaceHolder) { - if (mRun) { - monitorRemotePlayer(); - if (mMode == stateEnum.ABOUT) { - drawAboutScreen(c); - } - else if (mMode == stateEnum.PAUSED) { - if (mNetworkManager != null) { - if (mShowNetwork) { - drawNetworkScreen(c); - } - else { - doDraw(c); - } - } - else if ((mHighScoreManager != null) && mShowScores) { - if (FrozenBubble.arcadeGame || (numPlayers > 1)) { - drawLowScoreScreen(c, mHighScoreManager.getLevel()); - } - else { - drawHighScoreScreen(c, mHighScoreManager.getLevel()); - } - } - else { - doDraw(c); - } - } - else { - if (mMode == stateEnum.RUNNING) { - if (mModeWas != stateEnum.RUNNING) { - if (mGameListener != null) { - mGameListener.onGameEvent(eventEnum.GAME_RESUME); - } - mModeWas = stateEnum.RUNNING; - resumeGame(); - } - updateGameState(); - } - doDraw(c); - } - } - } - } - } - } finally { - /* - * Do this in a finally so that if an exception is thrown - * during the above, we don't leave the Surface in an - * inconsistent state. - */ - if (c != null) { - try { - mSurfaceHolder.unlockCanvasAndPost(c); - } catch (IllegalStateException ise) { - /* - * Surface has already been released. - */ - } - } - } - } - } - - /** - * Dump game state to the provided Bundle. Typically called when the - * Activity is being suspended. - * @return Bundle with this view's state - */ - public Bundle saveState(Bundle map) { - synchronized(mSurfaceHolder) { - if (map != null) { - if (mFrozenGame1 != null) { - mFrozenGame1.saveState(map); - } - if (numPlayers > 1) { - map.putInt("numPlayers", 2); - map.putInt("numPlayer1GamesWon", numPlayer1GamesWon); - map.putInt("numPlayer2GamesWon", numPlayer2GamesWon); - if (mFrozenGame2 != null) { - mFrozenGame2.saveState(map); - } - } - else { - map.putInt("numPlayers", 1); - } - if (mLevelManager != null) { - mLevelManager.saveState(map); - } - if (mHighScoreManager != null) { - mHighScoreManager.saveState(map); - } - } - } - return map; - } - - private void scaleFrom(BmpWrap image, Bitmap bmp) { - if ((image.bmp != null) && (image.bmp != bmp)) { - image.bmp.recycle(); - } - - if ((mDisplayScale > 0.99999) && (mDisplayScale < 1.00001)) { - image.bmp = bmp; - return; - } - - int dstWidth = (int)(bmp.getWidth() * mDisplayScale); - int dstHeight = (int)(bmp.getHeight() * mDisplayScale); - image.bmp = Bitmap.createScaledBitmap(bmp, dstWidth, dstHeight, true); - } - - /** - * Set the player action for a remote player - as in a person playing - * via a client device over a network. - * @param newAction - the object containing the remote input info. - */ - public void setPlayerAction(PlayerAction newAction) { - VirtualInput playerRef; - FrozenGame gameRef; - - if (newAction.playerID == VirtualInput.PLAYER1) { - playerRef = mPlayer1; - } - else if (newAction.playerID == VirtualInput.PLAYER2) { - playerRef = mPlayer2; - } - else { - return; - } - - if (playerRef.mGameRef != null) { - gameRef = playerRef.mGameRef; - } - else { - return; - } - - if (mGameThread != null) - mGameThread.updateStateOnEvent(null); - - synchronized(mSurfaceHolder) { - /* - * Set the launcher bubble colors. - */ - if ((newAction.launchBubbleColor > -1) && - (newAction.launchBubbleColor < 8) && - (newAction.nextBubbleColor > -1) && - (newAction.nextBubbleColor < 8) && - (newAction.newNextBubbleColor > -1) && - (newAction.newNextBubbleColor < 8)) { - gameRef.setLaunchBubbleColors(newAction.launchBubbleColor, - newAction.nextBubbleColor, - newAction.newNextBubbleColor); - } - - /* - * Set the launcher aim position. - */ - gameRef.setPosition(newAction.aimPosition); - - /* - * Process a compressor lower request. - */ - if (newAction.compress) { - gameRef.lowerCompressor(true); - } - - /* - * Process a bubble launch request. - */ - if (newAction.launchBubble) { - playerRef.setAction(KeyEvent.KEYCODE_DPAD_UP, true); - } - - /* - * Process a bubble swap request. - */ - if (newAction.swapBubble) { - playerRef.setAction(KeyEvent.KEYCODE_DPAD_DOWN, false); - } - - /* - * Process a pause/play button toggle request. - */ - if (newAction.keyCode == (byte) KeyEvent.KEYCODE_P) { - if (mGameThread != null) { - mGameThread.toggleKeyPress(KeyEvent.KEYCODE_P, true, false); - } - } - - /* - * Set the current value of the attack bar. - */ - if (newAction.attackBarBubbles > -1) { - gameRef.malusBar.setAttackBubbles(newAction.attackBarBubbles, - newAction.attackBubbles); - } - } - } - - public void setPosition(double value) { - if (mLocalInput.mGameRef != null) { - mLocalInput.mGameRef.setPosition(value); - } - } - - public void setRunning(boolean b) { - mRun = b; - } - - public void setState(stateEnum newMode) { - synchronized(mSurfaceHolder) { - /* - * Only update the previous mode storage if the new mode is - * different from the current mode, in case the same mode is - * being set multiple times. - * - * The transition from state to state must be preserved in case - * a separate execution thread that checks for state transitions - * does not get a chance to run between calls to this method. - */ - if (newMode != mMode) - mModeWas = mMode; - - mMode = newMode; - } - } - - public void setSurfaceOK(boolean ok) { - synchronized(mSurfaceHolder) { - mSurfaceOK = ok; - } - } - - public void setSurfaceSize(int width, int height) { - float newHeight = height; - float newWidth = width; - float gameHeight = GAMEFIELD_HEIGHT; - float gameWidth = GAMEFIELD_WIDTH; - float extGameWidth = EXTENDED_GAMEFIELD_WIDTH; - synchronized(mSurfaceHolder) { - if ((newWidth / newHeight) >= (gameWidth / gameHeight)) { - mDisplayScale = (1.0 * newHeight) / gameHeight; - mDisplayDX = (int)((newWidth - (mDisplayScale * extGameWidth)) / 2); - mDisplayDY = 0; - } - else { - mDisplayScale = (1.0 * newWidth) / gameWidth; - mDisplayDX = (int)(mDisplayScale * (gameWidth - extGameWidth) / 2); - mDisplayDY = (int)((newHeight - (mDisplayScale * gameHeight)) / 2); - } - if (numPlayers > 1) { - /* - * When rotate to shoot targeting mode is selected during a - * multiplayer game, then the screen orientation is forced - * to landscape. - * - * In portrait mode during a multiplayer game, display just - * one game field. Depending on which player is the local - * player, display the game field for just that player. This - * is useful for devices with small screens. - */ - if (FrozenBubble.getTargetMode() == FrozenBubble.ROTATE_TO_SHOOT) { - mDisplayDX = 0; - } - else { - int orientation = getScreenOrientation(); - if ((orientation == FrozenBubble.SCREEN_ORIENTATION_REVERSE_PORTRAIT) || - (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)) { - if (mLocalInput.playerID == VirtualInput.PLAYER2) { - mDisplayDX = (int)(-mDisplayScale * gameWidth); - } - else { - mDisplayDX = 0; - } - } - } - } - if (numPlayers > 1) { - mPlayer1DX = (int)(mDisplayDX - (mDisplayScale * (gameWidth / 2))); - } - else { - mPlayer1DX = mDisplayDX; - } - mPlayer2DX = (int)(mDisplayDX + (mDisplayScale * (gameWidth / 2))); - resizeBitmaps(); - } - } - - /** - * Create a CPU opponent object (if necessary) and start the thread. - */ - private void startOpponent() { - if (mOpponent != null) { - mOpponent.stopThread(); - mOpponent = null; - } - if ((numPlayers > 1) && mRemoteInput.isCPU) { - if (mRemoteInput.playerID == VirtualInput.PLAYER2) - mOpponent = new ComputerAI(mFrozenGame2, mRemoteInput); - else - mOpponent = new ComputerAI(mFrozenGame1, mRemoteInput); - mOpponent.start(); - } - } - - public boolean surfaceOK() { - synchronized(mSurfaceHolder) { - return mSurfaceOK; - } - } - - /** - * Process function key presses. Function keys toggle features on - * and off (e.g., game paused on/off, sound on/off, etc.). - * @param keyCode - the key code to process. - * @param updateNow - if true, apply state changes. - * @param transmit - if true and this is a network game, send the - * key code over the network. - */ - public void toggleKeyPress(int keyCode, - boolean updateNow, - boolean transmit) { - if (keyCode == KeyEvent.KEYCODE_M) - muteKeyToggle = !muteKeyToggle; - else if (keyCode == KeyEvent.KEYCODE_P) { - if (transmit && (mNetworkManager != null)) { - mNetworkManager.sendLocalPlayerAction(mLocalInput.playerID, - false, false, false, keyCode, -1, -1, -1, -1, null, - mLocalInput.mGameRef.launchBubblePosition); - } - pauseKeyToggle = !pauseKeyToggle; - mGameThread.pauseButtonPressed(pauseKeyToggle); - if (updateNow) { - updateStateOnEvent(null); - /* - * If the game is running and the pause button was pressed, - * pause the game. - */ - if (pauseKeyToggle && (mMode == stateEnum.RUNNING)) { - pause(); - } - } - } - } - - /** - * Obtain the current state of a feature toggle key. - * @param keyCode - * @return The state of the desired feature toggle key flag. - */ - public boolean toggleKeyState(int keyCode) { - if (keyCode == KeyEvent.KEYCODE_M) { - return muteKeyToggle; - } - else if (keyCode == KeyEvent.KEYCODE_P) { - return pauseKeyToggle; - } - - return false; - } - - /** - * updateStateOnEvent() - a common method to process motion events - * to set the game state. When the motion event has been fully - * processed, this function will return true, otherwise if the - * calling method should also process the motion event, this - * function will return false. - * @param event - the MotionEvent to process for the purpose of - * updating the game state. If this parameter is null, then the - * game state is forced to update if applicable based on the current - * game state. - * @return This function returns true to inform the - * calling function that the game state has been updated and that no - * further processing is necessary, and false to - * indicate that the caller should continue processing the motion - * event. - */ - private boolean updateStateOnEvent(MotionEvent event) { - boolean event_action_down = false; - - if (event == null) - event_action_down = true; - else if (event.getAction() == MotionEvent.ACTION_DOWN) - event_action_down = true; - - if (event_action_down) { - switch (mMode) { - case ABOUT: - if (numPlayers > 1) { - setState(stateEnum.RUNNING); - return true; - } - else { - if (!mBlankScreen) { - setState(stateEnum.RUNNING); - return true; - } - } - break; - - case PAUSED: - if (mNetworkManager != null) { - if (mShowNetwork) { - if (mNetworkManager.gameIsReadyForAction()) { - mShowNetwork = false; - setState(stateEnum.RUNNING); - if (mGameListener != null) { - mGameListener.onGameEvent(eventEnum.LEVEL_START); - } - } - return true; - } - } - else if (mShowScores) { - mShowScores = false; - if (numPlayers > 1) { - setState(stateEnum.RUNNING); - } - else { - if (game1Status == gameEnum.WON) { - nextLevel(); - } - if (getCurrentLevelIndex() != 0) { - setState(stateEnum.RUNNING); - } - } - if (mGameListener != null) { - mGameListener.onGameEvent(eventEnum.LEVEL_START); - } - return true; - } - setState(stateEnum.RUNNING); - break; - - case RUNNING: - default: - break; - } - } - return false; - } - - private void updateGameState() { - if ((mFrozenGame1 == null) || - ((mFrozenGame2 == null) && (numPlayers > 1)) || - ((mOpponent == null) && mRemoteInput.isCPU)) { - return; - } - - gameEnum game1State = mFrozenGame1.play(mPlayer1.actionLeft(), - mPlayer1.actionRight(), - mPlayer1.actionUp(), - mPlayer1.actionDown(), - mPlayer1.getTrackBallDx(), - mPlayer1.actionTouchFire(), - mPlayer1.getTouchX(), - mPlayer1.getTouchY(), - mPlayer1.actionTouchFireATS(), - mPlayer1.getTouchDxATS()); - - if (numPlayers > 1) { - gameEnum game2State = mFrozenGame2.play(mPlayer2.actionLeft(), - mPlayer2.actionRight(), - mPlayer2.actionUp(), - mPlayer2.actionDown(), - mPlayer2.getTrackBallDx(), - mPlayer2.actionTouchFire(), - mPlayer2.getTouchX(), - mPlayer2.getTouchY(), - mPlayer2.actionTouchFireATS(), - mPlayer2.getTouchDxATS()); - - /* - * If playing a network game, update the bubble grid checksums. - */ - if (mNetworkManager != null) { - mNetworkManager.setLocalChecksum(mLocalInput.mGameRef.gridChecksum); - mNetworkManager.setRemoteChecksum(mRemoteInput.mGameRef.gridChecksum); - } - - /* - * If playing a CPU opponent, notify the computer that the current - * action has been processed and we are ready for a new action. - */ - if (mOpponent != null) { - mOpponent.clearAction(); - } - - /* - * Obtain the number of attack bubbles to add to each player's - * attack bar that are being sent by their respective opponents. - */ - malusBar1.addBubbles(mFrozenGame1.getSendToOpponent()); - malusBar2.addBubbles(mFrozenGame2.getSendToOpponent()); - - /* - * Use the immediate game play result to determine when a player - * wins or loses during a multiplayer game, as the other player - * will automatically lose or win, respectively. - */ - gameEnum game1Result = mFrozenGame1.getGameResult(); - gameEnum game2Result = mFrozenGame2.getGameResult(); - - if (game1Result != gameEnum.PLAYING) { - if (mNetworkManager != null) { - mNetworkManager.setGameIsFinished(); - } - if ((game1Result == gameEnum.WON) || - (game1Result == gameEnum.NEXT_WON)) { - mFrozenGame2.setGameResult(gameEnum.LOST); - } - else { - mFrozenGame2.setGameResult(gameEnum.WON); - } - } - else if (game2Result != gameEnum.PLAYING) { - if (mNetworkManager != null) { - mNetworkManager.setGameIsFinished(); - } - if ((game2Result == gameEnum.WON) || - (game2Result == gameEnum.NEXT_WON)) { - if (mHighScoreManager != null) { - mHighScoreManager.lostLevel(); - } - mFrozenGame1.setGameResult(gameEnum.LOST); - } - else { - if (mHighScoreManager != null) { - mHighScoreManager.endLevel(mFrozenGame1.nbBubbles); - } - mFrozenGame1.setGameResult(gameEnum.WON); - } - } - - /* - * When playing a network game, only start a new game when the - * current game is finished, which is indicated when both - * players have either won or lost. - * - * If the opponent in a multiplayer game is the CPU, only start - * a new game when player 1 provides input, because otherwise - * the CPU is prone to sneaking a launch attempt in after the - * game has already been decided. - * - * Otherwise, the first player to provide input initiates the - * new game. - */ - boolean gameFinished = false; - if (mNetworkManager != null) { - gameFinished = mNetworkManager.getGameIsFinished(); - } - - if (((mNetworkManager == null) || gameFinished) && - (((game1State == gameEnum.NEXT_LOST) || - (game1State == gameEnum.NEXT_WON)) || - (!mRemoteInput.isCPU && - ((game2State == gameEnum.NEXT_LOST) || - (game2State == gameEnum.NEXT_WON))))) { - if ((game1State == gameEnum.NEXT_WON) || - (game2State == gameEnum.NEXT_LOST)) { - numPlayer1GamesWon++; - } - else { - numPlayer2GamesWon++; - } - - if (mNetworkManager == null) { - mShowScores = true; - } - - pause(); - nextLevel(); - } - } - else if ((game1State == gameEnum.NEXT_LOST) || - (game1State == gameEnum.NEXT_WON )) { - if (FrozenBubble.arcadeGame) { - game1Status = gameEnum.WON; - mShowScores = true; - pause(); - } - else if (game1State == gameEnum.NEXT_WON) { - game1Status = gameEnum.WON; - mShowScores = true; - pause(); - } - else { - game1Status = gameEnum.LOST; - newGame(false); - } - } - - if (mGameListener != null) { - if (game1State == gameEnum.NEXT_WON) { - mGameListener.onGameEvent(eventEnum.GAME_WON); - } - else if (game1State == gameEnum.NEXT_LOST){ - mGameListener.onGameEvent(eventEnum.GAME_LOST); - } - } - } - - /** - * Use the player 1 horizontal screen offset to adjust the - * playfield horizontal touch position. - * @param x - the raw horizontal touch coordinate. - * @return The adjusted horizontal touch position. - */ - private double xFromScr(float x) { - return (x - mPlayer1DX) / mDisplayScale; - } - - private double yFromScr(float y) { - return (y - mDisplayDY) / mDisplayScale; - } - } - - /** - * GameView class constructor. - * @param context - the application context. - * @param attrs - the compiled XML attributes for the superclass. - */ - public GameView(Context context, AttributeSet attrs) { - super(context, attrs); - //Log.i("frozen-bubble", "GameView constructor"); - init(context, 1, (int) VirtualInput.PLAYER1, FrozenBubble.HUMAN, - FrozenBubble.LOCALE_LOCAL, FrozenBubble.arcadeGame, null, 0); - } - - /** - * GameView class constructor. - * @param context - the application context. - * @param levels - the single player game levels (can be null). - * @param startingLevel - the single player game starting level. - */ - public GameView(Context context, byte[] levels, int startingLevel) { - super(context); - //Log.i("frozen-bubble", "GameView constructor"); - init(context, 1, (int) VirtualInput.PLAYER1, FrozenBubble.HUMAN, - FrozenBubble.LOCALE_LOCAL, FrozenBubble.arcadeGame, levels, - startingLevel); - } - - /** - * GameView class constructor. - * @param context - the application context. - * @param numPlayers - the number of players (1 or 2). - * @param myPlayerId - the local player ID (1 or 2). - * @param opponentId - the opponent type ID, human or CPU. - * @param gameLocale - the game topology, which can be either local, - * or distributed over various network types. - * @param arcadeGame - arcade game mode flag. - */ - public GameView(Context context, - int numPlayers, - int myPlayerId, - int opponentId, - int gameLocale, - boolean arcadeGame) { - super(context); - //Log.i("frozen-bubble", "GameView constructor"); - init(context, numPlayers, myPlayerId, opponentId, gameLocale, arcadeGame, null, 0); - } - - private boolean checkImmediateAction() { - boolean actNow = false; - /* - * Preview the current action if one is available to see if it - * contains an asynchronous action (e.g., launch bubble swap). - */ - PlayerAction previewAction = mNetworkManager.getRemoteActionPreview(); - - if (previewAction != null) { - actNow = previewAction.compress || previewAction.swapBubble; - } - - return actNow; - } - - public void cleanUp() { - //Log.i("frozen-bubble", "GameView.cleanUp()"); - cleanUpNetworkManager(); - - mPlayer1.init(); - mPlayer2.init(); - - if (mOpponent != null) - mOpponent.stopThread(); - mOpponent = null; - - mGameThread.cleanUp(); - } - - private void cleanUpNetworkManager() { - if (mNetworkManager != null) - mNetworkManager.cleanUp(); - mNetworkManager = null; - } - - /** - * Display a blank screen (black background) for the specified wait - * interval. - * @param clearScreen - If true, show a blank screen for - * the specified wait interval. If false, show the - * normal screen. - * @param wait - The amount of time to display the blank screen. - */ - public void clearGameScreen(boolean clearScreen, int wait) { - mBlankScreen = clearScreen; - try { - if (clearScreen) { - mGameThread.setState(stateEnum.ABOUT); - Timer timer = new Timer(); - timer.schedule(new ResumeGameScreenTask(), wait, wait + 1); - } - } catch (IllegalArgumentException illArgEx) { - illArgEx.printStackTrace(); - mBlankScreen = false; - } catch (IllegalStateException illStateEx) { - illStateEx.printStackTrace(); - mBlankScreen = false; - } - } - - /** - * GameView object initialization. - * @param context - the application context. - * @param numPlayers - the number of players (1 or 2). - * @param myPlayerId - the local player ID (1 or 2). - * @param opponentId - the opponent type ID, human or CPU. - * @param gameLocale - the game topology, which can be either local, - * or distributed over various network types. - * @param arcadeGame - arcade game mode flag. - * @param levels - the single player game levels (can be null). - * @param startingLevel - the single player game starting level. - */ - private void init(Context context, - int numPlayers, - int myPlayerId, - int opponentId, - int gameLocale, - boolean arcadeGame, - byte[] levels, - int startingLevel) { - mContext = context; - this.gameLocale = gameLocale; - this.numPlayers = numPlayers; - SurfaceHolder holder = getHolder(); - holder.addCallback(this); - mOpponent = null; - - numPlayer1GamesWon = 0; - numPlayer2GamesWon = 0; - - boolean isRemote = gameLocale != FrozenBubble.LOCALE_LOCAL; - boolean isCPU = (opponentId == FrozenBubble.CPU) && !isRemote; - - if (myPlayerId == VirtualInput.PLAYER1) { - mPlayer1 = new PlayerInput(VirtualInput.PLAYER1, false, false); - mPlayer2 = new PlayerInput(VirtualInput.PLAYER2, isCPU, isRemote); - mLocalInput = mPlayer1; - mRemoteInput = mPlayer2; - } - else { - mPlayer1 = new PlayerInput(VirtualInput.PLAYER1, isCPU, isRemote); - mPlayer2 = new PlayerInput(VirtualInput.PLAYER2, false, false); - mLocalInput = mPlayer2; - mRemoteInput = mPlayer1; - } - - /* - * Create a network game manager if this is a network game. - */ - mNetworkManager = null; - if ((gameLocale == FrozenBubble.LOCALE_BLUETOOTH) || - (gameLocale == FrozenBubble.LOCALE_WIFI )) { - connectEnum mode; - if (gameLocale == FrozenBubble.LOCALE_BLUETOOTH) { - mode = connectEnum.BLUETOOTH; - } - else { - mode = connectEnum.UDP_MULTICAST; - } - mNetworkManager = new NetworkManager(context, - mode, - mLocalInput, - mRemoteInput); - remoteInterface = mNetworkManager.getRemoteInterface(); - } - - /* - * Give this view focus-ability for improved compatibility with - * various input devices. - */ - setFocusable(true); - setFocusableInTouchMode(true); - - /* - * Create and start the game thread. - */ - if (numPlayers > 1) { - mGameThread = new GameThread(holder); - } - else { - mGameThread = new GameThread(holder, levels, startingLevel, arcadeGame); - } - mGameThread.setRunning(true); - mGameThread.start(); - } - - public GameThread getThread() { - return mGameThread; - } - - private void monitorRemotePlayer() { - if ((mNetworkManager != null) && (mRemoteInput != null)) { - /* - * Check the remote player interface for game field updates. - * Reject the game field data if it doesn't correspond to the - * latest remote player game field. This is determined based on - * whether the game field data action ID matches the latest remote - * player action ID. - */ - if (remoteInterface.gotFieldData) { - if (mNetworkManager.getLatestRemoteActionId() == - remoteInterface.gameFieldData.localActionID) { - setPlayerGameField(remoteInterface.gameFieldData); - } - remoteInterface.gotFieldData = false; - } - - /* - * Once the game is ready, if the game thread is not running, then - * allow the remote player to update the game thread state. - * - * If an asynchronous action is available or we are clear to - * perform a synchronous action, retrieve and clear the current - * available action from the action queue. - */ - if (mNetworkManager.gameIsReadyForAction() && (checkImmediateAction() || - mRemoteInput.mGameRef.getOkToFire() || - (mGameThread.mMode != stateEnum.RUNNING))) { - if (mNetworkManager.getRemoteAction()) { - setPlayerAction(remoteInterface.playerAction); - remoteInterface.gotAction = false; - } - else if (mRemoteInput.mGameRef.getOkToFire()) { - mNetworkManager.checkRemoteChecksum(); - } - } - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - //Log.i("frozen-bubble", "GameView.onKeyDown()"); - return mGameThread.doKeyDown(keyCode, event) || - super.onKeyDown(keyCode, event); - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - //Log.i("frozen-bubble", "GameView.onKeyUp()"); - return mGameThread.doKeyUp(keyCode, event) || - super.onKeyUp(keyCode, event); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - //Log.i("frozen-bubble", "GameView.onTouchEvent()"); - return mGameThread.doTouchEvent(event) || - super.onTouchEvent(event); - } - - @Override - public boolean onTrackballEvent(MotionEvent event) { - //Log.i("frozen-bubble", "event.getX(): " + event.getX()); - //Log.i("frozen-bubble", "event.getY(): " + event.getY()); - return mGameThread.doTrackballEvent(event) || - super.onTrackballEvent(event); - } - - @Override - public void onWindowFocusChanged(boolean hasWindowFocus) { - //Log.i("frozen-bubble", "GameView.onWindowFocusChanged()"); - super.onWindowFocusChanged(hasWindowFocus); - if (!hasWindowFocus) { - if (mNetworkManager != null) { - mNetworkManager.pause(); - } - if (mGameThread != null) - mGameThread.pause(); - } - else if (mNetworkManager != null) { - mNetworkManager.unPause(); - } - } - - /** - * This is a class that extends TimerTask to resume displaying the - * game screen as normal after it has been shown as a blank screen. - * @author Eric Fortin - * - */ - class ResumeGameScreenTask extends TimerTask { - @Override - public void run() { - mBlankScreen = false; - cancel(); - } - }; - - /** - * Set the player action for a remote player - as in a person playing - * via a client device over a network. - * @param newAction - the object containing the remote input info. - */ - private void setPlayerAction(PlayerAction newAction) { - if ((newAction != null) && (mGameThread != null)) { - mGameThread.setPlayerAction(newAction); - } - } - - /** - * Set the remote player client game field. - * @param newGameField - the object containing the remote field data. - */ - private void setPlayerGameField(GameFieldData newField) { - if (newField == null) { - return; - } - - FrozenGame gameRef; - - if (newField.playerID == VirtualInput.PLAYER1) { - gameRef = mPlayer1.mGameRef; - } - else if (newField.playerID == VirtualInput.PLAYER2) { - gameRef = mPlayer2.mGameRef; - } - else { - return; - } - - /* - * Set the bubble grid, and lower the compressor and bubbles in play - * to the required number of compressor steps. - */ - gameRef.setGrid(newField.gameField, newField.compressorSteps); - - /* - * Set the launcher bubble colors. - */ - gameRef.setLaunchBubbleColors(newField.launchBubbleColor, - newField.nextBubbleColor, - gameRef.getNewNextColor()); - - /* - * Set the current value of the attack bar. - */ - gameRef.malusBar.setAttackBubbles(newField.attackBarBubbles, null); - } - - public void surfaceChanged(SurfaceHolder holder, int format, int width, - int height) { - //Log.i("frozen-bubble", "GameView.surfaceChanged"); - mGameThread.setSurfaceSize(width, height); - } - - public void surfaceCreated(SurfaceHolder holder) { - //Log.i("frozen-bubble", "GameView.surfaceCreated()"); - mGameThread.setSurfaceOK(true); - } - - public void surfaceDestroyed(SurfaceHolder holder) { - //Log.i("frozen-bubble", "GameView.surfaceDestroyed()"); - mGameThread.setSurfaceOK(false); - } -} diff --git a/src/org/jfedor/frozenbubble/ImageSprite.java b/src/org/jfedor/frozenbubble/ImageSprite.java deleted file mode 100644 index 20d9d68..0000000 --- a/src/org/jfedor/frozenbubble/ImageSprite.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import java.util.Vector; - -import android.graphics.Canvas; -import android.graphics.Point; -import android.graphics.Rect; -import android.os.Bundle; - -public class ImageSprite extends Sprite { - private BmpWrap displayedImage; - - public ImageSprite(Rect area, BmpWrap img) { - super(area); - this.displayedImage = img; - } - - public void saveState(Bundle map, Vector savedSprites, int id) { - if (getSavedId() != -1) { - return; - } - super.saveState(map, savedSprites, id); - map.putInt(String.format("%d-%d-imageId", id, getSavedId()), - displayedImage.id); - } - - public int getTypeId() { - return Sprite.TYPE_IMAGE; - } - - public void changeImage(BmpWrap img) { - this.displayedImage = img; - } - - public final void paint(Canvas c, double scale, int dx, int dy) { - Point p = super.getSpritePosition(); - drawImage(displayedImage, p.x, p.y, c, scale, dx, dy); - } -} diff --git a/src/org/jfedor/frozenbubble/LaunchBubbleSprite.java b/src/org/jfedor/frozenbubble/LaunchBubbleSprite.java deleted file mode 100644 index 7feeafd..0000000 --- a/src/org/jfedor/frozenbubble/LaunchBubbleSprite.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import java.util.Vector; - -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.os.Bundle; - -public class LaunchBubbleSprite extends Sprite { - private int currentColor; - private double currentDirection; - - private Drawable launcher; - private BmpWrap[] bubbles; - private BmpWrap[] colorblindBubbles; - - public LaunchBubbleSprite(int initialColor, double initialDirection, - Drawable launcher, - BmpWrap[] bubbles, BmpWrap[] colorblindBubbles) { - super(new Rect(276, 362, 276 + 86, 362 + 76)); - - currentColor = initialColor; - currentDirection = initialDirection; - this.launcher = launcher; - this.bubbles = bubbles; - this.colorblindBubbles = colorblindBubbles; - } - - public void saveState(Bundle map, Vector saved_sprites, int id) { - if (getSavedId() != -1) { - return; - } - super.saveState(map, saved_sprites, id); - map.putInt(String.format("%d-%d-currentColor", id, getSavedId()), - currentColor); - map.putDouble(String.format("%d-%d-currentDirection", id, getSavedId()), - currentDirection); - } - - public int getTypeId() { - return Sprite.TYPE_LAUNCH_BUBBLE; - } - - public void changeColor(int newColor) { - currentColor = newColor; - } - - public void changeDirection(double newDirection) { - currentDirection = newDirection; - } - - public final void paint(Canvas c, double scale, int dx, int dy) { - if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL) { - drawImage(bubbles[currentColor], 302, 390, c, scale, dx, dy); - } - else { - drawImage(colorblindBubbles[currentColor], 302, 390, c, scale, dx, dy); - } - - // Draw the scaled and rotated launcher. - c.save(); - int xCenter = 318; - int yCenter = 406; - c.rotate((float)(0.025 * 180 * (currentDirection - - FrozenGame.START_LAUNCH_DIRECTION)), - (float)(xCenter * scale + dx), (float)(yCenter * scale + dy)); - launcher.setBounds((int)((xCenter - 50) * scale + dx), - (int)((yCenter - 50) * scale + dy), - (int)((xCenter + 50) * scale + dx), - (int)((yCenter + 50) * scale + dy)); - launcher.draw(c); - c.restore(); - } -} diff --git a/src/org/jfedor/frozenbubble/LevelManager.java b/src/org/jfedor/frozenbubble/LevelManager.java deleted file mode 100644 index f8432e5..0000000 --- a/src/org/jfedor/frozenbubble/LevelManager.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import java.util.Random; -import java.util.Vector; - -import android.os.Bundle; - -public class LevelManager { - - /* - * Level row and column definitions. - */ - public static final int LANES = 15; - public static final int MAX_ROWS = 15; - public static final int NUM_COLS = 8; - public static final int NUM_ROWS = 13; - public static final int VS_ROWS = 5; - - /* - * Level difficulty (number of bubble colors) definitions. - */ - public static final int EASY = 4; - public static final int NORMAL = 5; - public static final int MODERATE = 6; - public static final int HARD = 7; - public static final int INSANE = 8; - - public static final String[] DifficultyStrings = { - "frozen bubble", - "frozen bubble", - "frozen bubble", - "frozen bubble", - "easy", - "normal", - "medium", - "hard", - "insane" - }; - - private boolean randomMode; - private long randomSeed; - private int currentLevel; - private int rowOffset; - private Vector levelList; - - public void saveState(Bundle map) { - map.putInt("LevelManager-currentLevel", currentLevel); - map.putInt("LevelManager-rowOffset", rowOffset); - } - - public void restoreState(Bundle map) { - currentLevel = map.getInt("LevelManager-currentLevel"); - rowOffset = map.getInt("LevelManager-rowOffset"); - } - - /** - * Constructor used to provide randomly generated levels. - * @param seed - the random bubble generation seed. - * @param difficulty - the number of different bubble colors to - * generate. Higher numbers make the level more difficult to play. - * Use the static difficulty values defined in this class to set the - * level difficulty, e.g. EASY, HARD, etc. - */ - public LevelManager(long seed, int difficulty) { - randomMode = true; - randomSeed = seed; - currentLevel = difficulty; - if (FrozenBubble.arcadeGame) { - rowOffset = 1; - } - else { - rowOffset = 0; - } - if (currentLevel < EASY) - currentLevel = EASY; - else if (currentLevel > INSANE) { - currentLevel = INSANE; - } - levelList = new Vector(); - levelList.addElement(getLevel(null)); - } - - /** - * Constructor used to parse levels provided via a formatted array. - * @param levels - the byte array containing the level information. - * @param startingLevel - the current level starting index. - */ - public LevelManager(byte[] levels, int startingLevel) { - randomMode = false; - randomSeed = 0; - String allLevels = new String(levels); - currentLevel = startingLevel; - rowOffset = 0; - levelList = new Vector(); - int nextLevel = allLevels.indexOf("\n\n"); - - if (nextLevel == -1 && allLevels.trim().length() != 0) { - nextLevel = allLevels.length(); - } - - while (nextLevel != -1) { - String currentLevel = allLevels.substring(0, nextLevel).trim(); - levelList.addElement(getLevel(currentLevel)); - allLevels = allLevels.substring(nextLevel).trim(); - - if (allLevels.length() == 0) { - nextLevel = -1; - } - else { - nextLevel = allLevels.indexOf("\n\n"); - - if (nextLevel == -1) { - nextLevel = allLevels.length(); - } - } - } - - if (currentLevel >= levelList.size()) { - currentLevel = 0; - } - } - - private byte[][] getLevel(String data) { - byte[][] temp = new byte[NUM_COLS][NUM_ROWS - 1]; - - for (int j = 0; j < (NUM_ROWS - 1); j++) { - for (int i = 0; i < NUM_COLS; i++) { - temp[i][j] = -1; - } - } - - if (!randomMode) { - int tempX = 0; - int tempY = 0; - - for (int i=0 ; i= 48 && data.charAt(i) <= 55) { - temp[tempX][tempY] = (byte)(data.charAt(i) - 48); - tempX++; - } - else if (data.charAt(i) == 45) { - temp[tempX][tempY] = -1; - tempX++; - } - - if (tempX == NUM_COLS) { - tempY++; - - if (tempY == NUM_ROWS - 1) { - return temp; - } - - tempX = tempY % 2; - } - } - } - else { - Random rand = new Random(randomSeed); - for (int j = 0; j < VS_ROWS; j++) { - for (int i = 0; i < NUM_COLS; i++) { - temp[i][j] = (byte)rand.nextInt(currentLevel); - } - if (FrozenBubble.arcadeGame) { - rowOffset = (rowOffset + 1) % 2; - } - } - randomSeed = rand.nextInt(); - } - return temp; - } - - public byte[] getNewRow(BubbleSprite[][] grid) { - byte[] tempRow = new byte[NUM_COLS]; - Random rand = new Random(randomSeed); - - for (int column = 0; column < NUM_COLS; column++) { - tempRow[column] = (byte)rand.nextInt(currentLevel); - } - - if (FrozenBubble.arcadeGame) { - rowOffset = (rowOffset + 1) % 2; - } - randomSeed = rand.nextInt(); - return tempRow; - } - - public int getRowOffset() { - return rowOffset; - } - - public byte[][] getCurrentLevel() { - if (!randomMode) { - if (currentLevel < levelList.size()) { - return (byte[][])levelList.elementAt(currentLevel); - } - } - else { - if (FrozenBubble.arcadeGame) { - rowOffset = VS_ROWS % 2; - } - return (byte[][])levelList.elementAt(0); - } - return null; - } - - public void goToNextLevel() { - if (!randomMode) { - currentLevel++; - if (currentLevel >= levelList.size()) { - currentLevel = 0; - } - } - else { - levelList.clear(); - levelList.addElement(getLevel(null)); - } - } - - public void goToFirstLevel() { - if (!randomMode) { - currentLevel = 0; - } - } - - public int getLevelIndex() { - return currentLevel; - } -} diff --git a/src/org/jfedor/frozenbubble/PenguinSprite.java b/src/org/jfedor/frozenbubble/PenguinSprite.java deleted file mode 100644 index 47f409f..0000000 --- a/src/org/jfedor/frozenbubble/PenguinSprite.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import java.util.Random; -import java.util.Vector; - -import android.graphics.Canvas; -import android.graphics.Rect; -import android.os.Bundle; - -public class PenguinSprite extends Sprite { - public final static int PENGUIN_HEIGHT = 45; - public final static int PENGUIN_WIDTH = 57; - - public final static int STATE_TURN_LEFT = 0; - public final static int STATE_TURN_RIGHT = 1; - public final static int STATE_FIRE = 2; - public final static int STATE_VOID = 3; - public final static int STATE_GAME_WON = 4; - public final static int STATE_GAME_LOST = 5; - - public final static int[][] LOST_SEQUENCE = - {{1,0}, {2,8}, {3,9}, {4,10}, {5,11}, {6,12}, {7,13}, {5,14}}; - public final static int[][] WON_SEQUENCE = - {{1,0}, {2,7}, {3,6}, {4,15}, {5,16}, {6,17}, {7,18}, {4,19}}; - - private int count; - private int currentPenguin; - private int finalState; - private int nextPosition; - - private BmpWrap spritesImage; - private Random rand; - - public PenguinSprite(Rect r, BmpWrap sprites, Random rand) { - super(r); - - this.spritesImage = sprites; - this.rand = rand; - - currentPenguin = 0; - finalState = STATE_VOID; - nextPosition = 0; - } - - public PenguinSprite(Rect r, BmpWrap sprites, Random rand, - int currentPenguin, int count, - int finalState, int nextPosition) { - super(r); - - this.spritesImage = sprites; - this.rand = rand; - this.currentPenguin = currentPenguin; - this.count = count; - this.finalState = finalState; - this.nextPosition = nextPosition; - } - - @Override - public void saveState(Bundle map, Vector saved_sprites, int id) { - if (getSavedId() != -1) { - return; - } - super.saveState(map, saved_sprites, id); - map.putInt(String.format("%d-%d-currentPenguin", id, getSavedId()), - currentPenguin); - map.putInt(String.format("%d-%d-count", id, getSavedId()), count); - map.putInt(String.format("%d-%d-finalState", id, getSavedId()), - finalState); - map.putInt(String.format("%d-%d-nextPosition", id, getSavedId()), - nextPosition); - } - - public int getTypeId() { - return Sprite.TYPE_PENGUIN; - } - - public void updateState(int state) { - if (finalState != STATE_VOID) { - count++; - - if (count % 6 == 0) { - if (finalState == STATE_GAME_LOST) { - currentPenguin = LOST_SEQUENCE[nextPosition][1]; - nextPosition = LOST_SEQUENCE[nextPosition][0]; - } - else if (finalState == STATE_GAME_WON) { - currentPenguin = WON_SEQUENCE[nextPosition][1]; - nextPosition = WON_SEQUENCE[nextPosition][0]; - } - } - } - else { - count++; - - switch(state) { - case STATE_TURN_LEFT: - count = 0; - currentPenguin = 3; - break; - case STATE_TURN_RIGHT: - count = 0; - currentPenguin = 2; - break; - case STATE_FIRE: - count = 0; - currentPenguin = 1; - break; - case STATE_VOID: - if (currentPenguin < 4 || currentPenguin > 7) { - currentPenguin = 0; - } - break; - case STATE_GAME_WON: - case STATE_GAME_LOST: - count = 0; - finalState = state; - currentPenguin = 0; - return; - } - - if (count>100) { - currentPenguin = 7; - } - else if (count % 15 == 0 && count > 25) { - currentPenguin = (rand.nextInt() % 3)+4; - if (currentPenguin < 4) { - currentPenguin = 0; - } - } - } - } - - public void paint(Canvas c, double scale, int dx, int dy) { - Rect r = this.getSpriteArea(); - /* - * Clip the specified penguin graphic from the image array. - */ - drawImageClipped(spritesImage, - (r.left - 1) - ((currentPenguin % 4) * PENGUIN_WIDTH), - (r.top - 1) - ((currentPenguin / 4) * PENGUIN_HEIGHT), - r, c, scale, dx, dy); - } -} diff --git a/src/org/jfedor/frozenbubble/SoundManager.java b/src/org/jfedor/frozenbubble/SoundManager.java deleted file mode 100644 index 760b51d..0000000 --- a/src/org/jfedor/frozenbubble/SoundManager.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import android.content.Context; -import android.media.AudioManager; -import android.media.SoundPool; - -public class SoundManager { - private SoundPool soundPool; - private int[] sm; - Context context; - - public SoundManager(Context context) { - this.context = context; - soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0); - sm = new int[ FrozenBubble.NUM_SOUNDS ]; - - sm[ FrozenBubble.SOUND_WON ] = soundPool.load(context, R.raw.applause, 1); - sm[ FrozenBubble.SOUND_LOST ] = soundPool.load(context, R.raw.lose, 1); - sm[ FrozenBubble.SOUND_LAUNCH ] = soundPool.load(context, R.raw.launch, 1); - sm[ FrozenBubble.SOUND_DESTROY ] = - soundPool.load(context, R.raw.destroy_group, 1); - sm[ FrozenBubble.SOUND_REBOUND ] = - soundPool.load(context, R.raw.rebound, 1); - sm[ FrozenBubble.SOUND_STICK ] = soundPool.load(context, R.raw.stick, 1); - sm[ FrozenBubble.SOUND_HURRY ] = soundPool.load(context, R.raw.hurry, 1); - sm[ FrozenBubble.SOUND_NEWROOT ] = - soundPool.load(context, R.raw.newroot_solo, 1); - sm[ FrozenBubble.SOUND_NOH ] = soundPool.load(context, R.raw.noh, 1); - sm[ FrozenBubble.SOUND_WHIP ] = soundPool.load(context, R.raw.whip, 1); - } - - public final void playSound(int sound) { - if (FrozenBubble.getSoundOn()) { - AudioManager mgr = - (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); - float volume = mgr.getStreamVolume (AudioManager.STREAM_MUSIC); - float volumeMax = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - volume = volume / volumeMax; - soundPool.play(sm[ sound ], volume, volume, 1, 0, 1f); - } - } - - public final void cleanUp() { - sm = null; - context = null; - soundPool.release(); - soundPool = null; - } -} diff --git a/src/org/jfedor/frozenbubble/Sprite.java b/src/org/jfedor/frozenbubble/Sprite.java deleted file mode 100644 index 5efdd7b..0000000 --- a/src/org/jfedor/frozenbubble/Sprite.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * [[ Frozen-Bubble ]] - * - * Copyright (c) 2000-2003 Guillaume Cottenceau. - * Java sourcecode - Copyright (c) 2003 Glenn Sanson. - * Additional source - Copyright (c) 2013 Eric Fortin. - * - * This code is distributed under the GNU General Public License - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 or 3, as published by the Free Software Foundation. - * - * 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, write to: - * Free Software Foundation, Inc. - * 675 Mass Ave - * Cambridge, MA 02139, USA - * - * Artwork: - * Alexis Younes <73lab at free.fr> - * (everything but the bubbles) - * Amaury Amblard-Ladurantie - * (the bubbles) - * - * Soundtrack: - * Matthias Le Bidan - * (the three musics and all the sound effects) - * - * Design & Programming: - * Guillaume Cottenceau - * (design and manage the project, whole Perl sourcecode) - * - * Java version: - * Glenn Sanson - * (whole Java sourcecode, including JIGA classes - * http://glenn.sanson.free.fr/jiga/) - * - * Android port: - * Pawel Aleksander Fedorynski - * Eric Fortin - * Copyright (c) Google Inc. - * - * [[ http://glenn.sanson.free.fr/fb/ ]] - * [[ http://www.frozen-bubble.org/ ]] - */ - -package org.jfedor.frozenbubble; - -import java.util.Vector; - -import android.graphics.Canvas; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.Region; -import android.os.Bundle; - -public abstract class Sprite { - public static int TYPE_BUBBLE = 1; - public static int TYPE_IMAGE = 2; - public static int TYPE_LAUNCH_BUBBLE = 3; - public static int TYPE_PENGUIN = 4; - - private Rect spriteArea; - private int saved_id; - - public Sprite(Rect spriteArea) { - this.spriteArea = spriteArea; - saved_id = -1; - } - - public void saveState(Bundle map, Vector saved_sprites, int id) { - if (saved_id != -1) { - return; - } - saved_id = saved_sprites.size(); - saved_sprites.addElement(this); - map.putInt(String.format("%d-%d-left", id, saved_id), spriteArea.left); - map.putInt(String.format("%d-%d-right", id, saved_id), spriteArea.right); - map.putInt(String.format("%d-%d-top", id, saved_id), spriteArea.top); - map.putInt(String.format("%d-%d-bottom", id, saved_id), spriteArea.bottom); - map.putInt(String.format("%d-%d-type", id, saved_id), getTypeId()); - } - - public final int getSavedId() { - return saved_id; - } - - public final void clearSavedId() { - saved_id = -1; - } - - public abstract int getTypeId(); - - public void changeSpriteArea(Rect newArea) { - spriteArea = newArea; - } - - public final void relativeMove(Point p) { - spriteArea = new Rect(spriteArea); - spriteArea.offset(p.x, p.y); - } - - public final void relativeMove(int x, int y) { - spriteArea = new Rect(spriteArea); - spriteArea.offset(x, y); - } - - public final void absoluteMove(Point p) { - spriteArea = new Rect(spriteArea); - spriteArea.offsetTo(p.x, p.y); - } - - public final Point getSpritePosition() { - return new Point(spriteArea.left, spriteArea.top); - } - - public final Rect getSpriteArea() { - return spriteArea; - } - - public static void drawImage(BmpWrap image, int x, int y, - Canvas c, double scale, int dx, int dy) { - c.drawBitmap(image.bmp, (float)(x * scale + dx), (float)(y * scale + dy), - null); - } - - public static void drawImageClipped(BmpWrap image, int x, int y, Rect clipr, - Canvas c, double scale, int dx, int dy) { - c.save(Canvas.CLIP_SAVE_FLAG); - c.clipRect((float)(clipr.left * scale + dx), - (float)(clipr.top * scale + dy), - (float)(clipr.right * scale + dx), - (float)(clipr.bottom * scale + dy), - Region.Op.REPLACE); - c.drawBitmap(image.bmp, (float)(x * scale + dx), (float)(y * scale + dy), - null); - c.restore(); - } - - public abstract void paint(Canvas c, double scale, int dx, int dy); -}