diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..ceb2e5d --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +bin/ +obj/ +build/ +gen/ +libs/*/*.so +.gradle +*.o +*.exe diff --git a/.project b/.project index ba3919f..a9d601a 100755 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - TimidityAE2.0 + TimidityAE3.0 diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 2a2ccf8..201b2d2 100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,811 +1,830 @@ - - + + + + + - - - - - - + + + + + + - + - - - + android:configChanges="uiMode|keyboard|keyboardHidden|orientation|screenSize" + android:label="@string/app_name" + android:launchMode="singleTask" > + + + + + + + + + + - - - - - + + + + + + - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + android:name="com.xperia64.timidityae.DummyActivity" + android:allowTaskReparenting="true" + android:alwaysRetainTaskState="false" + android:clearTaskOnLaunch="true" + android:enabled="true" + android:excludeFromRecents="true" + android:finishOnTaskLaunch="true" + android:noHistory="true" + android:stateNotNeeded="true" + android:theme="@android:style/Theme.NoDisplay" /> + + - - - - - - - - - - \ No newline at end of file + android:label="Timidity AE Widget" > + + + + + + + + + diff --git a/README b/README index c064876..5f7eee4 100755 --- a/README +++ b/README @@ -7,7 +7,7 @@ Timidity AE contains TiMidity++ and sfArkLib: http://sourceforge.net/projects/timidity https://github.com/raboof/sfArkLib -This app uses an unmodified ActionBarSherlock Library which can be found at: -http://actionbarsherlock.com +This app uses an android-support-v4-preferencefragment Library which can be found at: +https://github.com/Machinarius/PreferenceFragment-Compat -Version 2.5.5 +Version 2.7.4 diff --git a/build.gradle b/build.gradle new file mode 100755 index 0000000..b62ef5d --- /dev/null +++ b/build.gradle @@ -0,0 +1,44 @@ +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:2.1.2' + } +} +allprojects { + + repositories { + mavenCentral() + } +} + +apply plugin: 'android' + +dependencies { + compile 'com.android.support:appcompat-v7:+' + //compile 'com.android.support:preference-v7:+' + compile 'com.android.support:support-v4:+' + compile 'com.github.machinarius:preferencefragment:0.1.2' + + //compile 'com.github.shkschneider:android_PreferenceFragmentCompat:1.2.0@aar' +} + +android { + buildToolsVersion "23.0.2" + compileSdkVersion "android-23" + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + resources.srcDirs = ['src'] + aidl.srcDirs = ['src'] + renderscript.srcDirs = ['src'] + res.srcDirs = ['res'] + assets.srcDirs = ['assets'] + jniLibs.srcDirs = ['libs'] + } + } +} diff --git a/jni/Application.mk b/jni/Application.mk index 47dc86e..e078c32 100755 --- a/jni/Application.mk +++ b/jni/Application.mk @@ -1,4 +1,4 @@ APP_ABI := armeabi-v7a arm64-v8a armeabi mips mips64 x86 x86_64 -APP_PLATFORM := android-8 +APP_PLATFORM := android-9 APP_OPTIM := release APP_CFLAGS := -DHAVE_CONFIG_H diff --git a/jni/helper/.gitignore b/jni/helper/.gitignore old mode 100644 new mode 100755 diff --git a/jni/helper/helper.c b/jni/helper/helper.c index cd8c299..16d2250 100755 --- a/jni/helper/helper.c +++ b/jni/helper/helper.c @@ -11,7 +11,6 @@ typedef double FLOAT_T; // So libtimidityplusplus doesn't have to have any android libs void andro_timidity_log_print(const char* tag, const char* fmt, ...) { - va_list listPointer; va_start( listPointer, fmt); __android_log_print(ANDROID_LOG_ERROR, tag, fmt, listPointer); @@ -67,7 +66,7 @@ char* configFile; char* configFile2; int sixteen; int mono; -int itIsDone=0; +int outputOpen=0; int shouldFreeInsts = 1; //JNIEnv* envelope; //JavaVM *jvm; @@ -273,6 +272,7 @@ Java_com_xperia64_timidityae_JNIHandler_unloadLib(JNIEnv * env, jobject obj) { if(libsLoaded&&!libHandle) { + __android_log_print(ANDROID_LOG_DEBUG, "TIMIDITY", "Nothing to unload"); return -1; // nothing to do } int libclose = dlclose(libHandle); @@ -290,7 +290,7 @@ Java_com_xperia64_timidityae_JNIHandler_unloadLib(JNIEnv * env, jobject obj) JNIEXPORT int JNICALL Java_com_xperia64_timidityae_JNIHandler_prepareTimidity(JNIEnv * env, jobject obj, jstring config, jstring config2, jint jmono, jint jcustResamp, jint jsixteen, jint jPresSil, jint jreloading, jint jfreeInsts) { - itIsDone = 0; + outputOpen = 0; if(!jreloading) { Android_JNI_SetupThread(); @@ -298,14 +298,14 @@ Java_com_xperia64_timidityae_JNIHandler_prepareTimidity(JNIEnv * env, jobject o //pushClazz = (jclass)(*env)->NewGlobalRef(env, tmp); pushClazz = (*env)->NewGlobalRef(env,(*env)->FindClass(env, "com/xperia64/timidityae/JNIHandler")); pushBuffit=(*env)->GetStaticMethodID(env, pushClazz, "buffit", "([BI)V"); - flushId=(*env)->GetStaticMethodID(env, pushClazz, "flushIt", "()V"); + flushId=(*env)->GetStaticMethodID(env, pushClazz, "flushTrack", "()V"); buffId=(*env)->GetStaticMethodID(env, pushClazz, "bufferSize", "()I"); - controlId=(*env)->GetStaticMethodID(env, pushClazz, "controlMe", "(I)V"); + controlId=(*env)->GetStaticMethodID(env, pushClazz, "controlCallback", "(I)V"); buffId=(*env)->GetStaticMethodID(env, pushClazz, "bufferSize", "()I"); rateId=(*env)->GetStaticMethodID(env, pushClazz, "getRate", "()I"); - finishId=(*env)->GetStaticMethodID(env, pushClazz, "finishIt", "()V"); - seekInitId=(*env)->GetStaticMethodID(env, pushClazz, "initSeeker", "(I)V"); - updateSeekId=(*env)->GetStaticMethodID(env, pushClazz, "updateSeeker", "(II)V"); + finishId=(*env)->GetStaticMethodID(env, pushClazz, "finishCallback", "()V"); + seekInitId=(*env)->GetStaticMethodID(env, pushClazz, "initSeekBar", "(I)V"); + updateSeekId=(*env)->GetStaticMethodID(env, pushClazz, "updateSeekBar", "(II)V"); pushLyricId=(*env)->GetStaticMethodID(env, pushClazz, "updateLyrics", "([B)V"); updateMaxChanId=(*env)->GetStaticMethodID(env, pushClazz, "updateMaxChannels", "(I)V"); updateProgId=(*env)->GetStaticMethodID(env, pushClazz, "updateProgramInfo", "(II)V"); @@ -360,11 +360,11 @@ Java_com_xperia64_timidityae_JNIHandler_loadSongTimidity(JNIEnv * env, jobject // Don't you just love JNI+threading? // Must be called once to open output. Thank you mac_main for the NULL file list thing - if(!itIsDone) + if(!outputOpen) { setMaxChannels((int)MAX_CHANNELS); (*timidity_play)(0, NULL); - itIsDone=1; + outputOpen=1; } int main_ret; char *filez[1]; @@ -373,7 +373,7 @@ Java_com_xperia64_timidityae_JNIHandler_loadSongTimidity(JNIEnv * env, jobject filez[0]=(char*)(*env)->GetStringUTFChars(env, song, &isCopy); //main_ret = timidity_play_main(1, filez); (*ext_play_list)(1,filez); -(*env)->ReleaseStringUTFChars(env, song, filez[0]); + (*env)->ReleaseStringUTFChars(env, song, filez[0]); finishAE(); //(*theGoodEnv)->DeleteLocalRef(theGoodEnv, pushClazz); diff --git a/jni/sfArkLib b/jni/sfArkLib deleted file mode 160000 index ee08d0c..0000000 --- a/jni/sfArkLib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ee08d0c8f6a872068c84fde5f4e6f6ee1d777f18 diff --git a/jni/sfArkLib/Android.mk b/jni/sfArkLib/Android.mk new file mode 100755 index 0000000..6227cc7 --- /dev/null +++ b/jni/sfArkLib/Android.mk @@ -0,0 +1,23 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := sfark + +LOCAL_C_INCLUDES := $(LOCAL_PATH) + +EMACS = no + +CFLAGS = -fPIC -Ofast + +LOCAL_CPP_EXTENSION := .cpp + +LOCAL_SRC_FILES:= sfklCoding.cpp +LOCAL_SRC_FILES+= sfklCrunch.cpp +LOCAL_SRC_FILES+= sfklDiff.cpp +LOCAL_SRC_FILES+= sfklFile.cpp +LOCAL_SRC_FILES+= sfklLPC.cpp +LOCAL_SRC_FILES+= sfklString.cpp +LOCAL_SRC_FILES+= sfklZip.cpp + +include $(BUILD_STATIC_LIBRARY) diff --git a/jni/sfArkLib/COPYING b/jni/sfArkLib/COPYING new file mode 100755 index 0000000..94a9ed0 --- /dev/null +++ b/jni/sfArkLib/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/jni/sfArkLib/Makefile b/jni/sfArkLib/Makefile new file mode 100755 index 0000000..8f1d03b --- /dev/null +++ b/jni/sfArkLib/Makefile @@ -0,0 +1,24 @@ + +INSTALL?=install + +OBJECTS=sfklCoding.o sfklDiff.o sfklLPC.o sfklZip.o sfklCrunch.o sfklFile.o sfklString.o + +ENDIANNESS=LITTLE_ENDIAN + +CXXFLAGS+=-fPIC -D__$(ENDIANNESS)__ -Wall -Wextra -lz + +LDFLAGS += -lz +SO = so +INSTALL += -D + +all: libsfark.$(SO) + +clean: + -rm *.o libsfark.$(SO) + +libsfark.$(SO): $(OBJECTS) + $(CXX) -shared $(LDFLAGS) $(OBJECTS) -o libsfark.$(SO) + +install: libsfark.$(SO) sfArkLib.h + $(INSTALL) libsfark.$(SO) $(DESTDIR)/usr/local/lib/libsfark.$(SO) + $(INSTALL) sfArkLib.h $(DESTDIR)/usr/local/include/sfArkLib.h diff --git a/jni/sfArkLib/README.md b/jni/sfArkLib/README.md new file mode 100755 index 0000000..e91cbcd --- /dev/null +++ b/jni/sfArkLib/README.md @@ -0,0 +1,15 @@ +sfArkLib +======== + +Library for decompressing sfArk soundfonts. + +If you just want to convert an sfArk file to sf2, +check out https://github.com/raboof/sfArkXTm + +Building +======== + + $ make + $ sudo make install + $ sudo ldconfig + diff --git a/jni/sfArkLib/sfArkLib.h b/jni/sfArkLib/sfArkLib.h new file mode 100755 index 0000000..b3263b2 --- /dev/null +++ b/jni/sfArkLib/sfArkLib.h @@ -0,0 +1,71 @@ +// Header for sfArkLib + +// copyright 1998-2000 Andy Inman +// Contact via: http://netgenius.co.uk or http://melodymachine.com + +// This file is part of sfArkLib. +// +// sfArkLib 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. +// +// sfArkLib 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 sfArkLib. If not, see . + +/* +Changes since V1.15 +=================== +All constants now prefixed with SFARKLIB_, and function names prefxied with sfkl_ + +sfkl_GetLicenseAgreement and sfkl_DisplayNotes functions now both take 2 parameters: the text of the text file +and the name of the text file. This makes it easier for the application to either display the text itself or pass +the filename onto some other program. Mac/Linux users note: the text is probably in Windows format! +Future sfArk versions will allow Notes and License files to be of other types than plain text (e.g. HTML, RTF) so +look at the file extenson in order to decide how to handle it. +*/ +#include "android/log.h" +// Some max sizes... +#define SFARKLIB_MAX_FILENAME 256 // Longest filename handled (or directory name) +#define SFARKLIB_MAX_FILEPATH 1024 // Longest full path handled +#define SFARKLIB_MAX_MSGTEXT (SFARKLIB_MAX_FILEPATH + 1024) // Longest message we might produce with sfkl_msg() + +// Flags used with msg() function... +#define SFARKLIB_MSG_SameLine (1 << 0) // Overwrite previous message +#define SFARKLIB_MSG_AppendLine (1 << 1) // Append to previous message +#define SFARKLIB_MSG_PopUp (1 << 2) // Should "pop up" a dialogue (usually an error message) + +// Error codes... +#define SFARKLIB_SUCCESS 0 // No error +#define SFARKLIB_ERR_INIT -1 // Failed to initialise +#define SFARKLIB_ERR_MALLOC -2 // Failed to allocate memory +#define SFARKLIB_ERR_SIGNATURE -3 // header does not contain "sfArk" signature +#define SFARKLIB_ERR_HEADERCHECK -4 // sfArk file has a corrupt header +#define SFARKLIB_ERR_INCOMPATIBLE -5 // sfArk file is incompatible (i.e. not sfArk V2.x) +#define SFARKLIB_ERR_UNSUPPORTED -6 // sfArk file uses unsupported feature +#define SFARKLIB_ERR_CORRUPT -7 // got invalid compressed data (file is corrupted) +#define SFARKLIB_ERR_FILECHECK -8 // file checksum failed (file is corrupted) +#define SFARKLIB_ERR_FILEIO -9 // File i/o error +#define SFARKLIB_ERR_LICENSE -10 // License included not agreed by user +#define SFARKLIB_ERR_OTHER -11 // Other error (currently unused) + +// Future SfArkLib versions may include additional further error codes, +// so, any other negative value is "unknown error" + +// Callback functions needed by sfArkLib (must be supplied by Application) ... +#define sfkl_msg(MessageText, Flags) __android_log_print(ANDROID_LOG_DEBUG, "TIMIDITY", "%s", MessageText) +#define sfkl_UpdateProgress(p) +#define sfkl_DisplayNotes(NotesText, NotesFileName); +//extern void sfkl_msg(const char *MessageText, int Flags); // Message display function +//extern void sfkl_UpdateProgress(int ProgressPercent); // Progress indication +//extern int sfkl_GetLicenseAgreement(const char *LicenseText, const char *LicenseFileName); // Display/confirm license +//extern void sfkl_DisplayNotes(const char *NotesText, const char *NotesFileName); // Display notes text file +#define sfkl_GetLicenseAgreement(LicenseText, LicenseFileName) 1 +// Functions in sfArkLib for use by Application... +extern "C" unsigned short sfkl_GetVersion(void); +extern "C" int skfl_Decode(const char *InFileName, const char *ReqOutFileName); diff --git a/jni/sfArkLib/sfklCoding.cpp b/jni/sfArkLib/sfklCoding.cpp new file mode 100755 index 0000000..c524f27 --- /dev/null +++ b/jni/sfArkLib/sfklCoding.cpp @@ -0,0 +1,860 @@ +//sfArkLib Coding +//Copyright 1998-2000 Andy Inman +//Contact via: http://netgenius.co.uk or http://melodymachine.com + +// This file is part of sfArkLib. +// +// sfArkLib 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. +// +// sfArkLib 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 sfArkLib. If not, see . + + +// V2.11 Initial release (with SDL 0.07) +// V2.12 Bug fix in UnMemcomp (OutBytes was uninitialised causing crash for some files) +// Used for SDL 0.08. +// V2.13 Bug fix, previously file written was corrupt due to wrong buffer pointers +// V2.14 Now using UpdateProgress function (supplied by application) +// V2.15 Now using GetLicenseAgreement & DisplayNotes functions (app-supplied) + +// 2.20 Version bumped to 2.20 - First version for MacOS support +// Major re-write to ReadHeader function, supports any size of self-extraction code in sfArk.exe files. +// 2.21 25-09-02 Fixed byte order on output samples (for MacOS). + +// 2.22 27-09-03 Fixed bug in call to UpdateProgress which reset to zero with large files when bytes +// written greater than (1<<31)/100 (approx 20MB) -- was due to 32-bit integer overflow +// Added more floating-point precision conversions in LPC to tighten-up on Mac compatibility issues +// Avoid potential bug in WriteOutputFile, now test BytesWritten != BytesToWrite instead of <= 0 +// Fixed rare bug when POST_AUDIO is more than ZBUF_SIZE (256kb) uncompressed (affected RealFont_2_1.sfArk) + +// 2.23 02-10-03 LPC Speeded up, now double the speed of earlier versions (on Intel at least) + +// CLIB headers... +#include +#include +#include +#include + + +// sfArk specific headers... +#define SFARKLIB_GLOBAL +#include "wcc.h" +#include "zlib.h" +#include "sfArkLib.h" +// Set to 1 for special debug mode (needs enabled version of compressor) +#define DB_BLOCKCHECK 0 + +// FileSection equates... +#define RIFF_HEADER 0 +#define RIFF_INFO 1 +#define INFO_LIST 2 +#define SDTA_LIST 3 +#define AUDIO_START 4 +#define AUDIO 5 +#define PRE_AUDIO 6 +#define POST_AUDIO 7 +#define NON_AUDIO 8 +#define FINISHED 9 + +// Misc equates... +#define OPTWINSIZE 32 // Default window size used by CrunchWin() +#define ZBUF_SIZE (256 * 1024) // Size of buffer used for MemComp (do not change!) +#define NSHIFTS (MAX_BUFSIZE / SHIFTWIN) // Max number of shift values per block (MaxBuf/SHIFTWIN = 4096/64) +#define MAX_DIFF_LOOPS 20 // Max number of BufDif loops + +// --- Version 2 File Header Structure --- + +#define HDR_NAME_LEN 5 +#define HDR_VERS_LEN 5 + +typedef struct +/* + NB: For compatibilty with sfArk V1, we must store "sfArk" at offset 27 (base 1) in + 5 characters and the compression method as one byte immediately afterwards at offset 32. + This will allow sfArk V1 to recoginse this as a .sfArk file (though not decompress it!) +*/ + { + uint32_t Flags; // 0-3 Bits 0 & 1 used to indicate presence of Notes and License files + uint32_t OriginalSize; // 4-7 Uncompressed file size + uint32_t CompressedSize; // 8-11 Compressed file size (including header) + uint32_t FileCheck; // 12-15 File Checksum + uint32_t HdrCheck; // 16-19 Header Checksum + uint8_t ProgVersionNeeded; // 20 SfArk version needed to unpack this file (20 = Version 2.0x, etc.) + char ProgVersion[HDR_NAME_LEN]; // 21-25 Version string (nn.nn) that created this file (NOT terminated) + char ProgName[HDR_VERS_LEN]; // 26-30 Signature "sfArk" (not terminated) + uint8_t CompMethod; // 31 Compression Method + uint16_t FileType; // 32-33 Currently always 0 (for SF2) + uint32_t AudioStart; // 34-37 Position in original file of start of audio data + uint32_t PostAudioStart; // 38-41 Position in original file of start any data after audio data (e.g. SF2 parameters) + char FileName[MAX_FILENAME]; // 42-297 Original filename, no path (stored variable length, null terminated) +} V2_FILEHEADER; + +// Some extras re. Header structure... +#define V2_FILEHEADER_SIZE 298 // *Actual* size of header data, may be less than sizeof(V2_FILEHEADER) +#define HEADER_HDRCHECK_POS 16 // Byte position of HeaderCheck field in header +#define HEADER_SIG_POS 26 // Byte position of "sfArk" signautre in header +#define HEADER_MAX_OFFSET (128*1024) // Maximum search extent: maximum expected size of "self-extractor" code. + +// FileHeader Flags... +#define FLAGS_Notes (1 << 0) // Notes file included +#define FLAGS_License (1 << 1) // License file included + +const char LicenseExt[] = ".license.txt"; // File extension for license file +const char NotesExt[] = ".txt"; // File extension for notes file + +static BYTE *Zbuf1 = NULL, *Zbuf2 = NULL; + +// Data per block, passed to ProcessNextBlock() + typedef struct + { + V2_FILEHEADER FileHeader; // FileHeader structre + int FileSection; // Track current "file section" + + int ReadSize; // Number of words to read per block + int MaxLoops; // Max loops for reduction with BufDiff2/3 + int MaxBD4Loops; // Max loops for reduction with BufDiff4 + int nc; // Number of LPC parameters + int WinSize; // Window size for CrunchWin + + AWORD *SrcBuf; // Address of source buffer + AWORD *DstBuf; // Address of destination buffer + + ULONG TotBytesWritten; // Total bytes written in file + ULONG FileCheck; // File checksum (accumulated) + AWORD PrevIn[MAX_DIFF_LOOPS]; // Previous values (per loop) + + USHORT PrevEncodeCount; // Previous number of loops used + USHORT BD4PrevEncodeCount; // Previous number of loops used for BD4 + short PrevShift; // Previous Shift value + short PrevUsedShift; // Previously used (non zero) Shift value + } BLOCK_DATA; + +// Messages... +const char CorruptedMsg[] = "- This file appears to be corrupted."; +const char UpgradeMsg[] = "Please see Help/About for information on how to obtain an update."; + +// ============================================================== +USHORT GetsfArkLibVersion(void) +{ + return (ProgVersionMaj * 10) + ProgVersionMin/10; +} +// ============================================================== + +char *ChangeFileExt(char *OutFileName, const char *NewExt, int OutFileNameSize) +{ + int n = strlen(OutFileName); + char *p; + + for (p = OutFileName+n; *p != '.'; p--) + { + if (*p == '\\' || p <= OutFileName) // No extension found? + { + p = OutFileName + n; + break; + } + } + + n = p - OutFileName; // Length of filename without extension + strncpy(p, NewExt, OutFileNameSize-1 - n); + return OutFileName; +} +// ============================================================== + +// Read the File Header.... +int ReadHeader(V2_FILEHEADER *FileHeader, BYTE *fbuf, int bufsize) +{ + int HeaderLen = 0, HdrOffset; + char CreatedByProg[HDR_NAME_LEN +1], CreatedByVersion[HDR_VERS_LEN +1]; + ULONG CalcHdrCheck = 0; + BYTE *HdrBuf, *bpFileHeader = (BYTE *) FileHeader; + + // Find and process the Header: This could be a plain sfArk file, a self-extracting file or some other (invalid) file. + // Also, it could be a sfArk V1 file, which we can't decompress, but should at least recognise. + // We locate the header by looking for the string "sfArk" within the first HEADER_MAX_OFFSET bytes of the file + // but because self-extractor code is likely to contain that string, we look for its final occurence + // by searching backwards. + // To speed things up, we first check at offset 0 (the case for a standard sfArk file) + // If we think we've found a (V2) header, we veryify it using the Header checksum. If the checksum fails, + // chances are it was a corrupt file, but could conceivably be a non-sfArk file. either way we report it as corrupt. + + int fbufsize = HEADER_MAX_OFFSET + V2_FILEHEADER_SIZE; // Amount data to read + if (fbufsize > bufsize) fbufsize = bufsize; // Buffer too small (should never happen) + + SetInputFilePosition(0); // set to logical start (maybe a predefined offset) + RETURN_ON_ERROR(); + ReadInputFile(fbuf, fbufsize); // Read a chunk of data from the start of the file + RETURN_ON_ERROR(); + + int SigFound = 0, SeemsV1 = 0, HdrCheckDone = 0; // Some flags to remember what we're doing + + for(int TryOffset = 0; TryOffset < HEADER_MAX_OFFSET; TryOffset++) + { + HdrOffset = (TryOffset == 0)? 0 : HEADER_MAX_OFFSET - TryOffset; // Check offset = 0 first, then backwards from end + + BYTE *sigpos = fbuf + HdrOffset + HEADER_SIG_POS; + if (*sigpos != 's' || memcmp(sigpos, "sfArk", 5) != 0) continue; + + SigFound = 1; // Set a flag to remember that we at least got this far + HdrBuf = fbuf + HdrOffset; + + if (V2_FILEHEADER_SIZE != sizeof(V2_FILEHEADER)) // Compare structure size to real size + { + // The compiler has messed with structure (alignment), so copy the data to the structure byte by byte... + BYTE *bptr = HdrBuf; // Point to start + // Copy all fields... + #define CPF(f) memcpy(&(FileHeader->f), bptr, sizeof(FileHeader->f)); bptr += sizeof(FileHeader->f) + CPF(Flags); CPF(OriginalSize); CPF(CompressedSize); CPF(FileCheck); CPF(HdrCheck); + CPF(ProgVersionNeeded); CPF(ProgVersion); CPF(ProgName); CPF(CompMethod); + CPF(FileType); CPF(AudioStart); CPF(PostAudioStart); CPF(FileName); + #undef CPF + if (bptr != HdrBuf+V2_FILEHEADER_SIZE) return (GlobalErrorFlag = SFARKLIB_ERR_OTHER); // Sanity check + } + else + memcpy(bpFileHeader, HdrBuf, V2_FILEHEADER_SIZE); // Copy entire data block to structure + + if (FileHeader->CompMethod < COMPRESSION_v2) // Looks like a sfArk V1 file? + { + SeemsV1 = 1; // set a flag + continue; // and keep searching + } + + // Header->FileName is a null-terminated string, we need it's length to calculate actual length of header data... + FileHeader->FileName[sizeof(FileHeader->FileName) -1] = '\0'; // Ensure strlen finds a terminator (string may be junk) + HeaderLen = V2_FILEHEADER_SIZE - sizeof(FileHeader->FileName) + strlen(FileHeader->FileName) + 1; + + // If we get this far, there's a good chance we've got the header... + /*#ifdef __BIG_ENDIAN__ + // FixEndians of all multi-byte integers (currently only relevent to Mac) + #define FIXENDIAN(field) FixEndian(&(FileHeader->field), sizeof(FileHeader->field)) + FIXENDIAN(Flags); FIXENDIAN(OriginalSize); FIXENDIAN(CompressedSize); + FIXENDIAN(FileCheck); FIXENDIAN(HdrCheck); FIXENDIAN(FileType); + FIXENDIAN(AudioStart); FIXENDIAN(PostAudioStart); + #undef FIXENDIAN + #endif*/ + + // Ok now, we know the HeaderLength and have the FileHeader structure properly populated... + #if 0 + // debug, display header... + printf("Flags %lx OrignalSize %ld CompressedSize %ld\n", FileHeader->Flags, FileHeader->OriginalSize, FileHeader->CompressedSize); + printf("FileCheck %lx HdrCheck %lx ProgVersionNeeded %d\n", FileHeader->FileCheck, FileHeader->HdrCheck, FileHeader->ProgVersionNeeded); + printf("AudioStart %ld PostAudioStart %ld Orginal filename %s\n", FileHeader->AudioStart, FileHeader->PostAudioStart, FileHeader->FileName); + #endif + *(uint32_t *)(HdrBuf+HEADER_HDRCHECK_POS) = 0; // Zero-out the HeaderChecksum position in the buffer + CalcHdrCheck = adler32(0, HdrBuf, HeaderLen); // and recalculate the header checksum + HdrCheckDone = 1; + if (CalcHdrCheck == FileHeader->HdrCheck) break; // Check passed: Yes, we've found the header! + } + + // When we get here, see what happened: + if (SigFound && HdrCheckDone && CalcHdrCheck == FileHeader->HdrCheck) // Everything Ok! File is V2 and valid + ; // Fall through to below (everything else is an error) + else if (SeemsV1) // Seems to be a sfArkV1 file + { + sprintf(MsgTxt, "This file was created with sfArk V1, and this program only handles sfArk V2+ files. Unfortunately sfArk V1 uses a proprietary compression algorithm for the non-audio metadata, so we cannot really support that. You might try running the Windows sfArk program from http://melodymachine.com/sfark.htm under Wine."); + msg(MsgTxt, MSG_PopUp); + return (GlobalErrorFlag = SFARKLIB_ERR_INCOMPATIBLE); + } + else if (SigFound) // Apparently a corrupt sfArk file (well, it had "sfArk" in it!) + { + sprintf(MsgTxt, "File Header fails checksum!%s", CorruptedMsg); + msg(MsgTxt, MSG_PopUp); + return (GlobalErrorFlag = SFARKLIB_ERR_HEADERCHECK); + } + else // Either very corrupted, or not a sfArk file + { + sprintf(MsgTxt, "This does not appear to be a sfArk file!"); + msg(MsgTxt, MSG_PopUp); + return (GlobalErrorFlag = SFARKLIB_ERR_SIGNATURE); + } + + // Get CreatedBy program name and version number (need null-terminated strings)... + strncpy(CreatedByProg, FileHeader->ProgName, HDR_NAME_LEN); // Copy program name + CreatedByProg[HDR_NAME_LEN] = 0; // Terminate string + strncpy(CreatedByVersion, FileHeader->ProgVersion, HDR_VERS_LEN); // Copy version string + CreatedByVersion[HDR_VERS_LEN] = 0; // Terminate string + + // Check for compatible version... + if (FileHeader->ProgVersionNeeded > ProgVersionMaj) + { + sprintf(MsgTxt, "You need %s version %2.1f (or higher) to decompress this file (your version is %s) %s", + ProgName, (float)FileHeader->ProgVersionNeeded/10, ProgVersion, UpgradeMsg); + msg(MsgTxt, MSG_PopUp); + return (GlobalErrorFlag = SFARKLIB_ERR_INCOMPATIBLE); + } + + // Warn if file was created by a newer version than this version... + float fProgVersion = (float) atof(ProgVersion); + float fCreatedByVersion = (float) atof(CreatedByVersion); + if (fCreatedByVersion > fProgVersion) + { + sprintf(MsgTxt, "This file was created with %s %s. Your version of %s (%s) can uncompress this file, " + "but you might like to obtain the latest version. %s", + CreatedByProg, CreatedByVersion, ProgName, ProgVersion, UpgradeMsg); + msg(MsgTxt, MSG_PopUp); + } + + SetInputFilePosition(HdrOffset + HeaderLen); // re-wind file to start of post-header data + RETURN_ON_ERROR(); + return SFARKLIB_SUCCESS; +} + +// ============================================================== +int InvalidEncodeCount(int EncodeCount, int MaxLoops) +{ + if (EncodeCount < 0 || EncodeCount > MaxLoops) // EncodeCount out of range? + { + sprintf(MsgTxt, "ERROR - Invalid EncodeCount (apparently %d) %s", EncodeCount, CorruptedMsg); + msg(MsgTxt, MSG_PopUp); + return 1; + } + else + return 0; +} + +// ============================================================== +int DecompressTurbo(BLOCK_DATA *Blk, USHORT NumWords) +{ + int EncodeCount = InputDiff(Blk->PrevEncodeCount); + if (InvalidEncodeCount(EncodeCount, Blk->MaxLoops)) return (GlobalErrorFlag = SFARKLIB_ERR_CORRUPT); + Blk->PrevEncodeCount = EncodeCount; + + int UnCrunchResult = UnCrunchWin(Blk->SrcBuf, NumWords, 8*OPTWINSIZE); + if (UnCrunchResult < 0) + { + sprintf(MsgTxt, "ERROR - UnCrunchWin returned: %d %s", UnCrunchResult, CorruptedMsg); + msg(MsgTxt, MSG_PopUp); + return (GlobalErrorFlag = SFARKLIB_ERR_CORRUPT); + } + + for (int j = EncodeCount-1; j >= 0; j--) + { + if (j == 0) Blk->FileCheck = (Blk->FileCheck << 1) + BufSum(Blk->SrcBuf, NumWords); + UnBufDif2(Blk->DstBuf, Blk->SrcBuf, NumWords, &(Blk->PrevIn[j])); + AWORD *SwapBuf = Blk->SrcBuf; Blk->SrcBuf = Blk->DstBuf; Blk->DstBuf = SwapBuf; + } + return SFARKLIB_SUCCESS; +} + +// ============================================================== +int CheckShift(short *ShiftVal, USHORT NumWords, short *PrevShift, short *PrevUsedShift) +// Here we look to see if the current buffer has been rightshifted +// There is a flag for the whole buffer to show if any shifted data exists, +// and if so there further flags to show if the Shift value changes within each sub block +// of ShiftWin words. +// For any changes, then follows the sub-block number where change occurs, then the new +// ShiftValue. The latter is given either as absolute value (if shift was previously +// non-zero) or relative change from previously used value (if shift was previously zero) +// For non-zero shift value, we then need to leftshift the data by that number of bits. +{ + #define ShiftWin 64 // Size of window for Shift + + int UsingShift = BioReadFlag(); // Read flag to see if using any shift + if (UsingShift) // and if so... + { + int MaxShifts = (NumWords+ShiftWin-1) / ShiftWin; // Number of ShiftWin sized sub-blocks in this block + int ChangePos = 0; // Init. position of last change + + int p = 0; + while (BioReadFlag()) // Read flag to see if there is a (further) change of shift value + { + // Read position of new shift value... + int nb = GetNBits(MaxShifts - ChangePos -1); // number of possible bits for ChangePos + ChangePos = BioRead(nb) + ChangePos; // Get position of next change of shift value + + // Read value of new shift... + short NewShift; + if (*PrevShift == 0) // If previous shift was 0 + { + NewShift = InputDiff(*PrevUsedShift); // Get new shift as diff from last used shift + *PrevUsedShift = NewShift; // Update PrevUsedShift + } + else // Else + NewShift = InputDiff(0); // Get new shift as difference from 0 + + // Update all ShiftVal[] data prior to change... + if (ChangePos > MaxShifts) // Corrupt data? + { + sprintf(MsgTxt, "ERROR - Invalid Shift ChangePos (apparently %d) %s", ChangePos, CorruptedMsg); + msg(MsgTxt, MSG_PopUp); + GlobalErrorFlag = SFARKLIB_ERR_CORRUPT; + return 0; + } + + for ( ; p < ChangePos; p++) ShiftVal[p] = *PrevShift; + *PrevShift = NewShift; // Update prev shift + } + + for ( ; p < MaxShifts; p++) ShiftVal[p] = *PrevShift; // Fill array to end with final shift value + + } + return UsingShift; +} + +// ============================================================== + +int DecompressFast(BLOCK_DATA *Blk, USHORT NumWords) +{ + int i, EncodeCount; + short ShiftVal[NSHIFTS]; // Shift values (one per SHIFTWIN words) + USHORT Method[MAX_DIFF_LOOPS]; // Block processing methods used per iteration + + #if DB_BLOCKCHECK // If debug mode block check enabled + ULONG BlockCheck = BioRead(16); // Read block check bits + #endif + + int UsingShift = CheckShift(ShiftVal, NumWords, &Blk->PrevShift, &Blk->PrevUsedShift); + int UsingBD4 = BioReadFlag(); // See if using BD4 + + if (UsingBD4) + { + EncodeCount = InputDiff(Blk->BD4PrevEncodeCount); + if (InvalidEncodeCount(EncodeCount, Blk->MaxBD4Loops)) return(GlobalErrorFlag = SFARKLIB_ERR_CORRUPT); + Blk->BD4PrevEncodeCount = EncodeCount; + } + else // Using BD2/3 + { + EncodeCount = InputDiff(Blk->PrevEncodeCount); + if (InvalidEncodeCount(EncodeCount, Blk->MaxLoops)) return(GlobalErrorFlag = SFARKLIB_ERR_CORRUPT); + Blk->PrevEncodeCount = EncodeCount; + + for(i = 0; i < EncodeCount; i++) + Method[i] = BioReadFlag(); // Read flags for BD2/3 + } + + // If using LPC, check for and read flags... + ULONG LPCflags; + int UsingLPC = (Blk->FileHeader.CompMethod != COMPRESSION_v2Fast); + if (UsingLPC) + { + if (BioReadFlag()) // Any flags? + LPCflags = BioRead(16) | (BioRead(16) << 16); // Then read them (32 bits) + else // else + LPCflags = 0; + } + + // Read the file and unpack the bitstream into buffer at Buf1p... + if (int UnCrunchResult = UnCrunchWin(Blk->SrcBuf, NumWords, OPTWINSIZE) < 0) // failed? + { + sprintf(MsgTxt, "ERROR - UnCrunchWin returned: %d %s", UnCrunchResult, CorruptedMsg); + msg(MsgTxt, MSG_PopUp); + return(GlobalErrorFlag = SFARKLIB_ERR_CORRUPT); + } + + if (UsingLPC) + { + UnLPC(Blk->DstBuf, Blk->SrcBuf, NumWords, Blk->nc, &LPCflags); + AWORD *SwapBuf = Blk->SrcBuf; Blk->SrcBuf = Blk->DstBuf; Blk->DstBuf = SwapBuf; + } + + if (UsingBD4) + { + for (i = EncodeCount-1; i >= 0; i--) + { + UnBufDif4(Blk->DstBuf, Blk->SrcBuf, NumWords, &(Blk->PrevIn[i])); + AWORD *SwapBuf = Blk->SrcBuf; Blk->SrcBuf = Blk->DstBuf; Blk->DstBuf = SwapBuf; + } + } + else + { + for (i = EncodeCount-1; i >= 0; i--) + { + switch (Method[i]) + { + case 0: UnBufDif2(Blk->DstBuf, Blk->SrcBuf, NumWords, &(Blk->PrevIn[i])); break; + case 1: UnBufDif3(Blk->DstBuf, Blk->SrcBuf, NumWords, &(Blk->PrevIn[i])); break; + } + AWORD *SwapBuf = Blk->SrcBuf; Blk->SrcBuf = Blk->DstBuf; Blk->DstBuf = SwapBuf; + } + } + + if (UsingShift) UnBufShift(Blk->SrcBuf, NumWords, ShiftVal); + + #if DB_BLOCKCHECK // If debug mode block check enabled + ULONG CalcBlockCheck = adler32(0, (const BYTE *) Blk->SrcBuf, 2*NumWords) & 0xffff; + //ULONG CalcBlockCheck = Blk->FileCheck & 0xffff; + //printf("Audio Block Checks Read: %ld, Calc %ld Length=%d\n", BlockCheck, CalcBlockCheck, 2*NumWords); + //getc(stdin); + if (BlockCheck != CalcBlockCheck) // Compare to calculated cheksum + { + msg("*** Audio Block check FAIL"); + } + //else + // printf("Audio Block check Ok\n"); + #endif + + Blk->FileCheck = 2 * Blk->FileCheck + BufSum(Blk->SrcBuf, NumWords); + return SFARKLIB_SUCCESS; +} +// ============================================================== +int ProcessNextBlock(BLOCK_DATA *Blk) +{ + //int TotBytesRead = 0; // Total bytes read in file + int NumWords; // + + uint32_t n, m; // NB: Must be 32-bit integer + + #define AWBYTES (sizeof(AWORD)) + BYTE *zSrcBuf = (BYTE *) Blk->SrcBuf; + BYTE *zDstBuf = (BYTE *) Blk->DstBuf; + + switch (Blk->FileSection) + { + case AUDIO: + { + NumWords = Blk->ReadSize; // Number of words we will read in this block + n = NumWords * AWBYTES; // ... and number of bytes + + if (Blk->TotBytesWritten + n >= Blk->FileHeader.PostAudioStart) // Short block? (near end of file) + { + n = Blk->FileHeader.PostAudioStart - Blk->TotBytesWritten; // Get exact length in bytes + NumWords = n / AWBYTES; // ... and words + Blk->FileSection = POST_AUDIO; // End of Audio -- PostAudio section is next + } + + //printf("AUDIO, read %ld bytes\n", n); + + if (Blk->FileHeader.CompMethod == COMPRESSION_v2Turbo) // If using Turbo compression + DecompressTurbo(Blk, NumWords); // Decompress + else // For all other methods + DecompressFast(Blk, NumWords); // Decompress + + //printf("B4 WriteOutputFile: %ld\n", adler32(0, (const BYTE *) Blk->SrcBuf, n) & 0xffff); + /*#ifdef __BIG_ENDIAN__ + #define WFIX(I) s = bp[I+0]; bp[I+0] = bp[I+1]; bp[I+1] = s; + BYTE *bp = (BYTE *) Blk->SrcBuf; BYTE *ep = bp + n; + do { + BYTE s; + WFIX(0); WFIX(2); WFIX(4); WFIX(6); + WFIX(8); WFIX(10); WFIX(12); WFIX(14); + bp += 16; + } while (bp < ep); + #undef WFIX + #endif*/ + + WriteOutputFile((const BYTE *)Blk->SrcBuf, n); // Write to output file + Blk->TotBytesWritten += n; // Accumulate total bytes written + break; + } + + case PRE_AUDIO: case POST_AUDIO: case NON_AUDIO: + { + BioReadBuf((BYTE *) &n, sizeof(n)); + FixEndian(&n, sizeof(n)); + //printf("Reading PRE/POST AUDIO block, compressed %ld bytes\n", n); + if (n > ZBUF_SIZE) // Check for valid block length + { + sprintf(MsgTxt, "ERROR - Invalid length for Non-audio Block (apparently %d bytes) %s", n, CorruptedMsg); + msg(MsgTxt, MSG_PopUp); + return (GlobalErrorFlag = SFARKLIB_ERR_CORRUPT); + } + + BioReadBuf(zSrcBuf, n); // Read the block + m = UnMemcomp(zSrcBuf, n, zDstBuf, ZBUF_SIZE); //printf("PRE/POST AUDIO block, compressed %ld bytes, uncompressed %ld bytes\n", n, m); + + // Uncompress + if (GlobalErrorFlag != SFARKLIB_SUCCESS) return(GlobalErrorFlag); + if (m <= ZBUF_SIZE) // Uncompressed ok & size is valid? + { + //printf("writing uncompressed block %ld bytes\n", m); + Blk->FileCheck = adler32(Blk->FileCheck, zDstBuf, m); // Accumulate checksum + WriteOutputFile(zDstBuf, m); // and write to output file + Blk->TotBytesWritten += m; // Accumulate byte count + } + else + return SFARKLIB_ERR_CORRUPT; + + #if DB_BLOCKCHECK // If debug mode block check enabled + ULONG BlockCheck = BioRead(16); // Read block check bits + FixEndian(&BlockCheck, sizeof(Blockcheck)); + ULONG CalcBlockCheck = adler32(0, zDstBuf, m) & 0xFFFF; + printf("NonAudio Block Checks Read: %ld, Calc %ld Length=%d\n", BlockCheck, CalcBlockCheck, m); + if (BlockCheck != CalcBlockCheck) // Compare to calculated cheksum + { + printf("*** NonAudio Block check FAIL\n"); + } + else + printf("NonAudio Block check Ok\n"); + #endif + + //printf("PRE/POST AUDIO, read %ld bytes, writing %ld bytes...", n, m); + + if (Blk->TotBytesWritten >= Blk->FileHeader.OriginalSize) // Have we finished the file? + Blk->FileSection = FINISHED; + else if (Blk->FileSection == PRE_AUDIO && Blk->TotBytesWritten >= Blk->FileHeader.AudioStart) // finished Pre-Audio? + Blk->FileSection = AUDIO; // .. then next section is Audio + + break; + } // case + } //switch + + //sprintf(MsgTxt, "BytesWritten: %ld of %ld", Blk->TotBytesWritten, Blk->FileHeader.OriginalSize); + //msg(MsgTxt, 0); + return SFARKLIB_SUCCESS; +} + +// ============================================================== +int EndProcess(int ErrorNum) +{ + CloseInputFile(); + CloseOutputFile(); + return ErrorNum; +} + +// ============================================================== +// Extract License & Notes files +// These are stored as 4-bytes length, followed by length-bytes of compressed data +int ExtractTextFile(BLOCK_DATA *Blk, ULONG FileType) +{ + ULONG n, m; + BYTE *zSrcBuf = (BYTE *) Blk->SrcBuf; + BYTE *zDstBuf = (BYTE *) Blk->DstBuf; + + const char *FileExt; + if (FileType == FLAGS_License) + FileExt = LicenseExt; + else if (FileType == FLAGS_Notes) + FileExt = NotesExt; + else + return 0; + + // NB:Can't use BioReadBuf... aligment problems? Yet it works for ProcessNextBlock() !!?? + // Ok, can use ReadInputFile here cause everythjing is whole no. of bytes... + + //BioReadBuf((BYTE *)&n, sizeof(n)); // Read length of block from file + ReadInputFile((BYTE *)&n, sizeof(n)); // Read length of block from file + FixEndian(&n, sizeof(n)); // Fix endian + + if (n <= 0 || n > ZBUF_SIZE) // Check for valid block length + { + sprintf(MsgTxt, "ERROR - Invalid length for %s file (apparently %ld bytes) %s", FileExt, n, CorruptedMsg); + msg(MsgTxt, MSG_PopUp); + GlobalErrorFlag = SFARKLIB_ERR_CORRUPT; + return 0; + } + + //BioReadBuf(zSrcBuf, n); // Read the block + ReadInputFile((BYTE *)zSrcBuf, n); // Read the block + m = UnMemcomp(zSrcBuf, n, zDstBuf, ZBUF_SIZE); // Uncompress + Blk->FileCheck = adler32(Blk->FileCheck, zDstBuf, m); // Accumulate checksum + if (GlobalErrorFlag || m > ZBUF_SIZE) // Uncompressed ok & size is valid? + return 0; + + // Write file - Use original file name plus specified extension for OutFileName... + char OutFileName[MAX_FILENAME]; + strncpy(OutFileName, Blk->FileHeader.FileName, sizeof(OutFileName)); // copy output filename + ChangeFileExt(OutFileName, FileExt, sizeof(OutFileName)); + OpenOutputFile(OutFileName); // Create notes / license file + WriteOutputFile(zDstBuf, m); // and write to output file + CloseOutputFile(); + if (FileType == FLAGS_License) + { + sprintf(MsgTxt, "Created license file: %s", OutFileName); + msg(MsgTxt, 0); + if (GetLicenseAgreement((const char *)zDstBuf, OutFileName) == 0) + { + GlobalErrorFlag = SFARKLIB_ERR_LICENSE; + return EndProcess(0); + } + } + else if (FileType == FLAGS_Notes) + { + sprintf(MsgTxt, "Created notes file: %s", OutFileName); + msg(MsgTxt, 0); + DisplayNotes((const char *)zDstBuf, OutFileName); + } + + return 1; +} + +// ============================================================== + +extern "C" int sfkl_Decode(const char *InFileName, const char *ReqOutFileName) +{ + char OutFileName[MAX_FILEPATH]; // File name for current output file + int NumLoops; // Number of loops before screen update etc. + + BLOCK_DATA Blk; + memset(&Blk, 0, sizeof(Blk)); + V2_FILEHEADER *FileHeader = &Blk.FileHeader; + + // NB: We keep 2 buffers with pointers in Blk->SrcBuf and Blk->DstBuf + // Generally we process from SrcBuf to DstBuf then swap the pointers, + // so that current data is always at SrcBuf + + // NB: On MacOS/GNU C, the following allocation of Zbuf1 and Zbuf2 causes "segmentation fault" + // BYTE Zbuf1[ZBUF_SIZE]; // Buffer1 + // BYTE Zbuf2[ZBUF_SIZE]; // Buffer2 + // so instead... + + #if 0 + static BYTE Zbuf1[ZBUF_SIZE]; // Buffer1 + static BYTE Zbuf2[ZBUF_SIZE]; // Buffer2 + + #else + if (Zbuf1 == NULL) Zbuf1 = (BYTE *) calloc(ZBUF_SIZE, sizeof(BYTE)); + if (Zbuf2 == NULL) Zbuf2 = (BYTE *) calloc(ZBUF_SIZE, sizeof(BYTE)); + + if (Zbuf1 == NULL || Zbuf2 == NULL) + return EndProcess(SFARKLIB_ERR_MALLOC); + #endif + + Blk.SrcBuf = (AWORD *) Zbuf1; // Point to Zbuf1 + Blk.DstBuf = (AWORD *) Zbuf2; // Point to Zbuf2 + + // Initialisation... + BioDecompInit(); // Initialise bit i/o + LPCinit(); // Init LPC + GlobalErrorFlag = SFARKLIB_SUCCESS; + + // Open input (.sfArk) file and read the header... + OpenInputFile(InFileName); + if (GlobalErrorFlag) return EndProcess(GlobalErrorFlag); // Something went wrong? + ReadHeader(FileHeader, Zbuf1, ZBUF_SIZE); + + if (GlobalErrorFlag) return EndProcess(GlobalErrorFlag); // Something went wrong? + + if (ReqOutFileName == NULL) // If no output filename requested + ReqOutFileName = FileHeader->FileName; + + if ((FileHeader->Flags & FLAGS_License) != 0) // License file exists? + { + if (ExtractTextFile(&Blk, FLAGS_License) == 0) + return EndProcess(GlobalErrorFlag); + } + + if ((FileHeader->Flags & FLAGS_Notes) != 0) // Notes file exists? + { + if (ExtractTextFile(&Blk, FLAGS_Notes) == 0) + return EndProcess(GlobalErrorFlag); + } + + // Use original file extension for OutFileName... + strncpy(OutFileName, ReqOutFileName, sizeof(OutFileName)); // Copy output filename + OpenOutputFile(OutFileName); // Create the main output file... + + // Set the decompression parameters... + switch (FileHeader->CompMethod) // Depending on compression method that was used... + { + case COMPRESSION_v2Max: + { + //msg("Compression: Max\n"); + Blk.ReadSize = 4096; + Blk.MaxLoops = 3; + Blk.MaxBD4Loops = 5; + Blk.nc = 128; + Blk.WinSize = OPTWINSIZE; + NumLoops = 2 * 4096 / Blk.ReadSize; + break; + } + case COMPRESSION_v2Standard: + { + //printf("Compression: Standard\n"); + Blk.MaxLoops = 3; + Blk.MaxBD4Loops = 3; + Blk.ReadSize = 4096; + Blk.nc = 8; + Blk.WinSize = OPTWINSIZE; + NumLoops = 50 * 4096 / Blk.ReadSize; + break; + } + case COMPRESSION_v2Fast: + { + //printf("Compression: Fast\n"); + Blk.MaxLoops = 20; + Blk.MaxBD4Loops = 20; + Blk.ReadSize = 1024; + Blk.WinSize = OPTWINSIZE; + NumLoops = 300 * 4096 / Blk.ReadSize; + break; + } + case COMPRESSION_v2Turbo: + { + //printf("Compression: Turbo\n"); + Blk.MaxLoops = 3; + Blk.MaxBD4Loops = 0; + Blk.ReadSize = 4096; + Blk.WinSize = OPTWINSIZE << 3; + NumLoops = 400 * 4096 / Blk.ReadSize; + break; + } + default: + { + sprintf(MsgTxt, "Unknown Compression Method: %d%s", FileHeader->CompMethod, CorruptedMsg); + GlobalErrorFlag = SFARKLIB_ERR_INCOMPATIBLE; + msg(MsgTxt, MSG_PopUp); + return EndProcess(GlobalErrorFlag); + } + } + + // Process the main file... + Blk.FileSection = PRE_AUDIO; // We start with pre-audio data + + ULONG ProgressUpdateInterval = Blk.FileHeader.OriginalSize / 100; // Calculate progress update + ULONG NextProgressUpdate = ProgressUpdateInterval; + int ProgressPercent = 0; + UpdateProgress(0); + + //int BlockNum = 0; + for (Blk.FileSection = PRE_AUDIO; Blk.FileSection != FINISHED; ) + { + for (int BlockCount = 0; BlockCount < NumLoops && Blk.FileSection != FINISHED; BlockCount++) + { + //printf("Block: %d\n", ++BlockNum); + ProcessNextBlock(&Blk); + + while (Blk.TotBytesWritten >= NextProgressUpdate) // Further 1% done since last UpdateProgress? + { + UpdateProgress(++ProgressPercent); + NextProgressUpdate += ProgressUpdateInterval; + } + if (GlobalErrorFlag) return EndProcess(GlobalErrorFlag); + } + // CheckForCancel(); + if (GlobalErrorFlag) return EndProcess(GlobalErrorFlag); + } + + if (ProgressPercent != 100) UpdateProgress(100); + + // Check the CheckSum... + if (Blk.FileCheck != FileHeader->FileCheck) + { + sprintf(MsgTxt, "CheckSum Fail!%s",CorruptedMsg); + msg(MsgTxt, MSG_PopUp); + //sprintf(MsgTxt, "Calc check %lx", Blk.FileCheck); + //msg(MsgTxt, MSG_PopUp); + GlobalErrorFlag = SFARKLIB_ERR_FILECHECK; + return EndProcess(GlobalErrorFlag); + } + + sprintf(MsgTxt, "Created %s (%ld kb) successfully.", ReqOutFileName, Blk.TotBytesWritten/1024); + msg(MsgTxt, 0); + + return EndProcess(GlobalErrorFlag); +} + +// ============================================================== + +// Adjust integer held at *num for this machine's endian system +void FixEndian(void *num, int nsize) +{ +/*#ifdef __BIG_ENDIAN__ + int i; + BYTE bb[4]; + for (i = 0; i < nsize; i++) bb[i] = ((BYTE *) num)[i]; + for (i = 0; i < nsize; i++) ((BYTE *) num)[i] = bb[nsize-1-i]; +#else */ + //#ifndef __LITTLE_ENDIAN__ + //#error ENDIAN system undefined + //#endif +//#endif +} + +// ============================================================== diff --git a/jni/sfArkLib/sfklCrunch.cpp b/jni/sfArkLib/sfklCrunch.cpp new file mode 100755 index 0000000..7924127 --- /dev/null +++ b/jni/sfArkLib/sfklCrunch.cpp @@ -0,0 +1,271 @@ +// BIO (Bit i/o) routines for sfArk / daArk +// Copyright 1998-2000 Andy Inman +// Contact via: http://netgenius.co.uk or http://melodymachine.com + +// This file is part of sfArkLib. +// +// sfArkLib 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. +// +// sfArkLib 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 sfArkLib. If not, see . + + +#include "wcc.h" +#include +#include + +// Static table to store number of bits per word... +static BYTE nb_init = 0; +static BYTE nb[1 << (AWORD_BITS-1)]; // Array to hold number of bits needed to represent each unsigned short value + +// ========================================================================= +// Macros for Bit I/O (BIO) .... + +// Static buffer and pointers.... + #define BIO_WBITS ((signed) (8 * sizeof(BIOWORD))) + #define BIOBUFSIZE (16 * 1024) // Disk-read buffer size, bigger may increased speed + + BIOWORD2 bioBits; // Bits not yet shifted from bioBuf (up to double length of BIOWORD) + BIOWORD bioBuf[BIOBUFSIZE]; // Buffer + + int bioP; // Count of output (index into bioBuf) + int bioRemBits; // Remaining bits left in bioBits + int bioWholeBlocks; // Count blocks read from disk + short bioPfb; // Previous "FixBits" value + +// -------------------------------------------------------------------------- +#define GRP_INBITS(g) \ + /* Get grp value from input by counting number of zeroes before we get a 1 */\ + g = 0; \ + while (bioBits == 0) \ + { \ + g += bioRemBits; \ + CHECK_INBUFFER \ + bioBits = bioBuf[bioP++]; \ + bioRemBits = BIO_WBITS; \ + } \ + \ + g += bioRemBits; \ + while ((bioBits >> --bioRemBits) != 1); \ + g -= bioRemBits+1; \ + bioBits = LOWBITS(bioBits, bioRemBits) + +// -------------------------------------------------------------------------- +#define INBITS(w, n) \ + /* Input value w using n bits (n must be <= BIO_WBITS) ... */\ + if (bioRemBits < BIO_WBITS) \ + { \ + CHECK_INBUFFER \ + bioBits = (bioBits << BIO_WBITS) | bioBuf[bioP++]; \ + bioRemBits += BIO_WBITS; \ + } \ + bioRemBits -= n; \ + w = (BIOWORD) (bioBits >> bioRemBits); \ + bioBits = LOWBITS(bioBits, bioRemBits) + +// ========================================================================= +/*#ifdef __BIG_ENDIAN__ + +#define WFIX(I) s = bp[I+0]; bp[I+0] = bp[I+1]; bp[I+1] = s; +// Read from disk if needed, and fix endians +#define CHECK_INBUFFER \ + if (bioP == BIOBUFSIZE) \ + { \ + bioWholeBlocks++; \ + bioP = 0; \ + int ReadLen = ReadInputFile((BYTE *) bioBuf, BIOBUFSIZE * sizeof(BIOWORD)); \ + if (ReadLen <= 0) return 0; \ + BYTE *bp = (BYTE *) bioBuf, *ep = (BYTE *) (bioBuf+BIOBUFSIZE); \ + do { \ + BYTE s; \ + WFIX(0); WFIX(2); WFIX(4); WFIX(6); \ + WFIX(8); WFIX(10); WFIX(12); WFIX(14); \ + bp += 16; \ + } while (bp < ep); \ + } + +#else*/ +// Read from disk if needed... +#define CHECK_INBUFFER \ + if (bioP == BIOBUFSIZE) \ + { \ + bioWholeBlocks++; \ + bioP = 0; \ + int ReadLen = ReadInputFile((BYTE *) bioBuf, BIOBUFSIZE * sizeof(BIOWORD)); \ + if (ReadLen <= 0) return 0; \ + } + +//#endif + +// -------------------------------------------------------------------------- +// End of macros +// -------------------------------------------------------------------------- + + +// ========================================================================= +void BioDecompInit() +{ + GetNBits(0); // Initialise nb array + bioRemBits= 0; + bioBits = 0; + bioP = BIOBUFSIZE; + bioPfb = 8; + return; +} +// ========================================================================= +void BioDecompEnd() +{ + return; +} +// ========================================================================= +BIOWORD BioRead(int n) +// Read bits from input, return value +{ + BIOWORD w; + INBITS(w, n); + return w; +} + +// ========================================================================= +int BioReadFlag(void) +// Read single bit from input, return value as int +{ + BIOWORD w; + INBITS(w, 1); + return (w != 0); +} + +// ========================================================================= +long BioReadBuf(BYTE *buf, long n) +// Read *bytes* to output, return number of BYTES +{ + int SavebioP = bioP; + bioWholeBlocks = 0; + + while (n--) + { + BIOWORD b; + INBITS(b, 8); + *buf++ = (BYTE) b; + } + + return (bioP - SavebioP + bioWholeBlocks * BIOBUFSIZE) * sizeof(BIOWORD); +} +// ========================================================================= +AWORD InputDiff(AWORD Prev) +// Read a value from input as difference from Previous value, return new value +{ + AWORD x; + + GRP_INBITS(x); + if (x != 0) // If non-zero, check sign bit + { + int sign; INBITS(sign, SIGNBIT); + if (sign != 0) x = -x; + } + return x + Prev; +} + +// ============================================================== + +long UnCrunch(AWORD *UnCompBuf, USHORT bufsize) +{ + short FixBits; + AWORD *bp = UnCompBuf, *endp = UnCompBuf+bufsize; + + FixBits = InputDiff(bioPfb); + bioPfb = FixBits; + + if (FixBits >= 0 && FixBits < 14) + { + // Uncompress the block... + short FSbits = FixBits + SIGNBIT; + do { + UAWORD grp, LoBits; + INBITS(LoBits, FSbits); // Get LowBits & SignBit + GRP_INBITS(grp); // Get group bits + *bp = ((grp << FixBits) | (LoBits>>1)) ^ -(LoBits&1); // NB: -Sign gives 0 or 0xFFFF + } while (++bp < endp); + } + else if (FixBits == 14) // Non-compressed block? + { + do { + INBITS(*bp, AWORD_BITS); + } while (++bp < endp); + } + else if (FixBits == -1) // Data all 0 and -1 ? + { + do { + INBITS(*bp, 1); // Get SignBit + *bp = -*bp; // Sign=0 means word is 0, Sign=1 means word is -1; + } while (++bp < endp); + } + else if (FixBits == -2) // Data all 0? + { + do *bp = 0; while (++bp < endp); // Set buffer to 0 + } + else // Shouldn't happen! + return -1; // Issues an error message + + return 0; +} + +// ========================================================================= +long UnCrunchWin(AWORD *buf, USHORT bufsize, USHORT winsize) +{ + USHORT finalwinsize = bufsize % winsize; + AWORD *endp = buf + bufsize - finalwinsize; + + for ( ; buf < endp; buf += winsize) + { + long result = UnCrunch(buf, winsize); + if (result < 0) return result; + } + + if (finalwinsize) + { + long result = UnCrunch(buf, finalwinsize); + if (result < 0) return result; + } + + return bufsize; +} + +// ========================================================================= +short GetNBits(short w) + // Get the number of bits used by value w + // e.g. w=000b, n=0 + // w=001b, n=1 + // w=010b, n=2 + // w=011b, n=2 + // w=100b, n=3 + // w=111b, n=3 etc. + +{ + // If not initialised (first time), build table in nb[] array... + if (nb_init == 0) + { + long first = 1, last, i; + BYTE nbits = 1; + nb_init = 1; + nb[0] = 0; + + do { + last = first + (1 << (nbits-1)); + for (i = first; i < last; i++) nb[i] = nbits; + nbits++; + first = last; + } while(last <= MAX_AWORD); + } + return nb[w]; +} + +// ========================================================================= diff --git a/jni/sfArkLib/sfklDiff.cpp b/jni/sfArkLib/sfklDiff.cpp new file mode 100755 index 0000000..f2d7aee --- /dev/null +++ b/jni/sfArkLib/sfklDiff.cpp @@ -0,0 +1,248 @@ +// Misc C stuff for sfArk/daArk +// Copyright 1998-2000 Andy Inman +// Contact via: http://netgenius.co.uk or http://melodymachine.com + +// This file is part of sfArkLib. +// +// sfArkLib 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. +// +// sfArkLib 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 sfArkLib. If not, see . + + +#include "wcc.h" +#include +#include + +// ========================================================================= + void UnBufDif2(AWORD *OutBuf, const AWORD *InBuf, USHORT bufsize, AWORD *prev) +{ +// NB: This code is optimised for speed - do not change order of operations or data types!!! +// ----------------------------------------------------------------------------------------- + +#if 0 + const AWORD *bufend1 = InBuf + bufsize; + + // Process start of buffer... + *OutBuf++ = *InBuf++ + *prev; + + // Process rest of buffer... + #define STEPSIZE 8 + #define DO_ONE(N) OutBuf[N] = InBuf[N] + OutBuf[N-1]; + // ---------------------------------------------------- + + const AWORD *bufend2 = bufend1 - STEPSIZE; + while (InBuf < bufend2) + { + DO_ONE(0); DO_ONE(1); DO_ONE(2); DO_ONE(3); + DO_ONE(4); DO_ONE(5); DO_ONE(6); DO_ONE(7); + OutBuf += STEPSIZE; InBuf += STEPSIZE; + } + + // Do final few... + while (InBuf < bufend1) { DO_ONE(0); OutBuf++; InBuf++; }; + + *prev = OutBuf[-1]; + +#else + const AWORD *bufend1 = OutBuf + bufsize; + + //for (int i = 0; i < bufsize; i++) OutBuf[i] = InBuf[i]; + memcpy(OutBuf, InBuf, bufsize*sizeof(AWORD)); + + // Process start of buffer... + *OutBuf++ += *prev; + + // Process rest of buffer... + #define STEPSIZE 8 + #define DO_ONE(N) OutBuf[N] += OutBuf[N-1]; + // ---------------------------------------------------- + + const AWORD *bufend2 = bufend1 - STEPSIZE; + while (OutBuf < bufend2) + { + DO_ONE(0); DO_ONE(1); DO_ONE(2); DO_ONE(3); + DO_ONE(4); DO_ONE(5); DO_ONE(6); DO_ONE(7); + OutBuf += STEPSIZE; + } + + // Do final few... + while (OutBuf < bufend1) { + *OutBuf += OutBuf[-1]; + OutBuf++; + }; + + *prev = OutBuf[-1]; +#endif + + return; + + #undef DO_ONE + #undef STEPSIZE +} + +// ========================================================================= + void old_UnBufDif3(AWORD *OutBuf, const AWORD *InBuf, USHORT bufsize, AWORD *prev) +{ + // Decoding is done from the END of the buffer, backwards... + + const AWORD *bufstart = InBuf; + + InBuf += bufsize-1; + OutBuf+= bufsize-1; + + // Process end of buffer... + *OutBuf-- = *InBuf--; + + //----------------------------------------- + #define DO_ONE(N) OutBuf[N] = InBuf[N] + NSDIV(InBuf[N-1] + OutBuf[N+1], 1); + // Process rest of buffer... + while (InBuf > bufstart) { DO_ONE(0); InBuf--; OutBuf--; } + + // Final word + *OutBuf = *InBuf + NSDIV(OutBuf[1], 1); + + *prev = OutBuf[bufsize-1]; + return; + #undef DO_ONE +} + + + void UnBufDif3(AWORD *OutBuf, const AWORD *InBuf, USHORT bufsize, AWORD *prev) +{ + // Decoding is done from the END of the buffer, backwards... + + #define STEPSIZE 8 + const AWORD *bufstart = InBuf, *bufstart1 = InBuf+STEPSIZE; + + InBuf += bufsize-1; + OutBuf+= bufsize-1; + + // Process end of buffer... + *OutBuf-- = *InBuf--; + + // Process rest of buffer... + //----------------------------------------- + #define DO_ONE(N) OutBuf[N] = InBuf[N] + NSDIV(InBuf[N-1] + OutBuf[N+1], 1); + //----------------------------------------- + + // Process most of buffer... + while (InBuf > bufstart1) + { + DO_ONE(0); DO_ONE(-1);DO_ONE(-2);DO_ONE(-3); + DO_ONE(-4);DO_ONE(-5);DO_ONE(-6);DO_ONE(-7); + InBuf-=STEPSIZE; OutBuf-=STEPSIZE; + } + + // Process rest of buffer... + while (InBuf > bufstart) { DO_ONE(0); InBuf--; OutBuf--; } + + // Final word + *OutBuf = *InBuf + NSDIV(OutBuf[1], 1); + + *prev = OutBuf[bufsize-1]; + return; + #undef DO_ONE + #undef STEPSIZE +} + +// ========================================================================= + void UnBufDif4(AWORD *OutBuf, const AWORD *InBuf, USHORT bufsize, AWORD *prev) +{ + AWORD avg = *prev; + const AWORD *bufend1 = InBuf + bufsize; + + // Process rest of buffer... + //----------------------------------------- + #define STEPSIZE 8 + const AWORD *bufend2 = bufend1 - STEPSIZE; + + #define DO_ONE(N) \ + OutBuf[N] = InBuf[N] + avg; \ + avg += SDIV(InBuf[N], 1); \ + + //----------------------------------------- + + for (; InBuf < bufend2; InBuf += STEPSIZE, OutBuf += STEPSIZE) + { + DO_ONE(0); DO_ONE(1); DO_ONE(2); DO_ONE(3); + DO_ONE(4); DO_ONE(5); DO_ONE(6); DO_ONE(7); + } + for (; InBuf < bufend1; ++InBuf, ++OutBuf) + { + DO_ONE(0); + } + + *prev = avg; + return; + + #undef DO_ONE + #undef STEPSIZE +} +// ========================================================================= + long BufSum(const AWORD *buf, USHORT bufsize) +{ + // --- Optimised! --- + long Total = 0; + + const AWORD *endp1 = buf + bufsize - 7; + const AWORD *endp2 = buf + bufsize; + + for (; buf < endp1; buf += 8) + { + Total += QUICKABS2(buf[0]) + QUICKABS2(buf[1]) + QUICKABS2(buf[2]) + QUICKABS2(buf[3]) + + QUICKABS2(buf[4]) + QUICKABS2(buf[5]) + QUICKABS2(buf[6]) + QUICKABS2(buf[7]); + } + + for ( ; buf < endp2; ++buf) + Total += QUICKABS2(*buf); + + return Total; +} + +// ========================================================================= + void UnBufShift1(AWORD *InBuf, USHORT bufsize, short Shift) +{ + #define STEPSIZE 8 + + // Ok, now we have a shift value - perform the shift... + AWORD *bps = InBuf, *bufend1s = bps + bufsize; + AWORD *bufend2s = bufend1s - STEPSIZE; + + #define DO_ONE(I) bps[I] <<= Shift + while (bps < bufend2s) + { + DO_ONE(0); DO_ONE(1); DO_ONE(2); DO_ONE(3); + DO_ONE(4); DO_ONE(5); DO_ONE(6); DO_ONE(7); + bps += STEPSIZE; + } + + // Do final few... + while (bps < bufend1s) { DO_ONE(0); bps++; }; + + return; + + #undef DO_ONE + #undef STEPSIZE +} + +// ========================================================================= + void UnBufShift(AWORD *InBuf, USHORT bufsize, short *shift) +{ + for(AWORD *endp = InBuf + bufsize; InBuf < endp; InBuf+= SHIFTWIN) + { + short s = *shift++; + if (s != 0) UnBufShift1(InBuf, SHIFTWIN, s); + } + + return; +} +// ========================================================================= diff --git a/jni/sfArkLib/sfklFile.cpp b/jni/sfArkLib/sfklFile.cpp new file mode 100755 index 0000000..33a2e78 --- /dev/null +++ b/jni/sfArkLib/sfklFile.cpp @@ -0,0 +1,210 @@ +// sfArkLib file i/o +// copyright 1998-2000, Andy Inman +// Contact via: http://netgenius.co.uk or http://melodymachine.com + +// This file is part of sfArkLib. +// +// sfArkLib 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. +// +// sfArkLib 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 sfArkLib. If not, see . + + +// NB: When sfArkLib is used with SDL, these functions are replaced +// by equvalents in sdl.cpp because the linker finds those first. + +#include +#include + +#include "wcc.h" +//#include "zlib.h" // only needed for debug printf + +#ifdef TARGET_WIN32 +// Windows32 target +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include "windows.h" +#undef WIN32_LEAN_AND_MEAN + +#define FILE_SHARE_NONE 0 +#define NO_SECURITY ((LPSECURITY_ATTRIBUTES) 0) +#define NOT_OVERLAPPED ((LPOVERLAPPED) 0) +#define NO_TEMPLATE ((HANDLE) 0) + +#define CREATEFILE(FileName) CreateFile((LPCTSTR)FileName, GENERIC_WRITE, FILE_SHARE_NONE, NO_SECURITY, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, NO_TEMPLATE) +#define OPENFILE(FileName) CreateFile((LPCTSTR)FileName, GENERIC_READ, FILE_SHARE_READ, NO_SECURITY, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, NO_TEMPLATE) +#define READFILE(fh, Buf, BytesToRead, pBytesRead) ReadFile(fh, Buf, BytesToRead, pBytesRead, NOT_OVERLAPPED) +#define WRITEFILE(fh, Buf, BytesToWrite, pBytesWritten) ReadFile(fh, Buf, BytesToWrite, pBytesWritten, NOT_OVERLAPPED) +#define SETFILEPOINTER(fh, NewPos) (SetFilePointer(fh, NewPos, 0, FILE_BEGIN)) +#define CLOSEFILE(fh) (CloseHandle(fh)) +#define GETLASTERROR() (GetLastError()) + +// Mac, Linux target +#else +typedef FILE* HANDLE; + +#define INVALID_HANDLE_VALUE (NULL) + +#define CREATEFILE(filename) fopen(filename, "wb") +#define OPENFILE(filename) fopen(filename, "rb") +#define READFILE(fh, Buf, BytesToRead, pBytesRead) *pBytesRead = fread(Buf, 1, BytesToRead, fh) +#define WRITEFILE(fh, Buf, BytesToWrite, pBytesWritten) *pBytesWritten = fwrite(Buf, 1, BytesToWrite, fh) +#define SETFILEPOINTER(fh, NewPos) (fseek(fh, NewPos, SEEK_SET)) +#define CLOSEFILE(fh) (fclose(fh) == 0) +#define GETLASTERROR() (-1) +#endif + + +// Static data to track current input and output file... +HANDLE InputFileHandle = INVALID_HANDLE_VALUE; // current input file handle +HANDLE OutputFileHandle = INVALID_HANDLE_VALUE; // ... output file handle +char InFileName[SFARKLIB_MAX_FILEPATH]; // current input file name +char OutFileName[SFARKLIB_MAX_FILEPATH]; // ... and output file name +//char *TempFileExt = "$sfkl"; + +// Local prototypes... +int ChkErr(const char *message, const char *filename); + +// ================================================================================= + +void OpenOutputFile(const char *FileName) +{ + #if 1 + int i; + int lenInFileName = strlen(InFileName); + for (i = lenInFileName; i >= 0; i--) + { + char c = InFileName[i]; + if (c == '\\' || c == '/') break; + } + + if (i < 0) + strncpy(OutFileName, FileName, sizeof(OutFileName)); + else + { + strncpy(OutFileName, InFileName, i+1); + strncpy(OutFileName+i+1, FileName, sizeof(OutFileName) - (i+1)); + } + #else + strncpy(OutFileName, FileName, sizeof(OutFileName)); + #endif + + //strcat(OutFileName, TempFileExt); // Add temporary extension + + OutputFileHandle = CREATEFILE(OutFileName); + if (OutputFileHandle == INVALID_HANDLE_VALUE) ChkErr("create", OutFileName); + return; +} +// ================================================================================= + +void OpenInputFile(const char *FileName) +{ + //printf("OpenInputFile: %s\n", FileName); + strncpy(InFileName, FileName, sizeof(InFileName)); + InputFileHandle = OPENFILE(FileName); + if (InputFileHandle == INVALID_HANDLE_VALUE) ChkErr("open", InFileName); + //else printf("OpenInputFile successful\n"); + return; +} +// ================================================================================= + +int ReadInputFile(BYTE *Buf, int BytesToRead) +{ + int BytesRead; + + READFILE(InputFileHandle, Buf, BytesToRead, &BytesRead); + if (BytesRead < 0) + { + ChkErr("read from", InFileName); + BytesRead = 0; + } + //else printf("ReadInputFile Ok: %d bytes read\n", BytesRead); + return BytesRead; +} +// ================================================================================= + +int WriteOutputFile(const BYTE *Buf, int BytesToWrite) +{ + int BytesWritten; + //printf("WriteOutputFile: bytes=%d\n", BytesToWrite); + WRITEFILE(OutputFileHandle, Buf, BytesToWrite, &BytesWritten); + if (BytesWritten != BytesToWrite) + { + //printf("WriteOutputFile error: %d bytes to write, %d bytes written\n", BytesToWrite, BytesWritten); + ChkErr("write to", OutFileName); + BytesWritten = 0; + } + //else printf("WriteOutputFile Ok: %d bytes written\n", BytesWritten); + return BytesWritten; +} + +// ================================================================================= + +int SetInputFilePosition(int NewPos) +{ + if (SETFILEPOINTER(InputFileHandle, NewPos) != 0) + { + ChkErr("SetInputFilePosition", InFileName); + return 0; + } + //else printf("SetInputFilePosition Ok: Requested %d Actual %ld\n", NewPos, ftell(InputFileHandle)); + return 1; +} +// ================================================================================= + +int SetOutputFilePosition(int NewPos) +{ + if (SETFILEPOINTER(OutputFileHandle, NewPos) != 0) + { + ChkErr("SetOutputFilePosition", OutFileName); + return 0; + } + //else printf("SetOutputFilePosition Ok: Requested %d Actual %ld\n", NewPos, ftell(InputFileHandle)); + return 1; +} +// ================================================================================= + +void CloseInputFile(void) +{ + if (InputFileHandle != INVALID_HANDLE_VALUE && CLOSEFILE(InputFileHandle) == 0) + ChkErr("Close input file: ", InFileName); + InputFileHandle = INVALID_HANDLE_VALUE; + return; +} +// ================================================================================= + +void CloseOutputFile(void) +{ + if (OutputFileHandle != INVALID_HANDLE_VALUE && CLOSEFILE(OutputFileHandle) == 0) + ChkErr("Close output file", OutFileName); + + //char FinalFileName[SFARKLIB_MAX_FILEPATH]; + OutputFileHandle = INVALID_HANDLE_VALUE; + return; +} +// ================================================================================= + +int ChkErr(const char *ErrorMsg, const char *FileName) +{ + int ErrCode; + char ErrDesc[MAX_MSGTEXT]; + + if (~GlobalErrorFlag) // Prevent multiple error messages + { + ErrCode = GETLASTERROR(); + sprintf(ErrDesc, "OS ERROR %d - Failed to %s: %s", ErrCode, ErrorMsg, FileName); + msg(ErrDesc, MSG_PopUp); + GlobalErrorFlag = SFARKLIB_ERR_FILEIO; + } + return(GlobalErrorFlag); +} + +// ================================================================================= +// eof diff --git a/jni/sfArkLib/sfklLPC.cpp b/jni/sfArkLib/sfklLPC.cpp new file mode 100755 index 0000000..4bedbc4 --- /dev/null +++ b/jni/sfArkLib/sfklLPC.cpp @@ -0,0 +1,395 @@ +// sfArkLib LPC +// copyright 1998-2000, Andy Inman +// Contact via: http://netgenius.co.uk or http://melodymachine.com + +// This file is part of sfArkLib. +// +// sfArkLib 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. +// +// sfArkLib 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 sfArkLib. If not, see . + +#include +#include +#include +#include + +#include "wcc.h" +#include "zlib.h" + +void LPCinit(); + +#define REFINT 1 // Integers for Reflection Coefficients (faster) + +#define LPCWIN 4096 + +#define PMAX 128 // Max allowed nc +#define ZWINMIN 128 // 128 or 256 best. Smaller - slightly slower +#define ZWINMAX ZWINMIN + +#if (LPCWIN / ZWINMIN) > 32 // Check use of 32bit *Flags + #error Invalid LPCWIN / ZWINMIN +#endif + +// The following parameters determine the history sized used for LPC analysis (little impact on speed) +// The history is the amount of prev +#define HISTSIZE (4*128/ZWINMIN) // Multiple of number of ZWINs to use as history size (seems best value) + +typedef LAWORD LPC_WORD; // LPC_WORD must have (slightly) greater range than AWORD + +// There are compatibility issues in floating point calculations between Intel and Mac versions. Not sure if this +// is a compiler issue or a processor issue -- in short on Windows it seems that calculations performed on float +// datatype get done in double precision. So, we need to force the correct precision when used on Mac. +// Better longterm solution is to force single precision for all calculations (for the compressor also) but +// that would require a version update. +#if 0 // Use double for datatypes, convert to single before storage (doesn't work!) +typedef double LPC_FLOAT; +#else // Use single for datatypes, convert to double for calculations (works) +typedef float LPC_FLOAT; +#endif +typedef double XPN; // eXtra PrecisioN during calculations +typedef float LPN; // Lower PrecisioN to store results of calculations + +#define ISCALE_BITS 14 // Fixed scale seems to work fine in practice +#define ISCALE (1 << ISCALE_BITS) + +#if REFINT == 1 + typedef long LPC_PRAM; +#else + typedef LPC_FLOAT LPC_PRAM; +#endif + +typedef LPC_FLOAT LPC_CORR; +typedef LPC_FLOAT LPC_CORR2; // Holds LPC_CORR*LPC_CORR + +// ====================================================================== +LPC_CORR schur( // returns the minimum mean square error + LPC_CORR const * ac, // in: [0...p] autocorrelation values + int nc, // in: number of ref. coeff + LPC_PRAM * ref) // out: [0...p-1] reflection coefficients +{ + int i, m; + + LPC_CORR2 error, r; + LPC_CORR2 Gen0[PMAX], Gen1[PMAX]; + + if (ac[0] == 0) + { + for (i = 0; i < nc; i++) ref[i] = 0; + return 0; + } + + // Initialize the rows of the generator matrix G to ac[1...p]. + error = ac[0]; + + for (i = 0; i < nc; i++) + Gen0[i] = Gen1[i] = ac[i + 1]; + +// static int blk = 0; + + for (i = 0;;) + { + // Calculate this iteration's reflection coefficient and error. + r = - (LPN) ((XPN)Gen1[0] / (XPN)error); + error = (LPN) ( (XPN)error + ((XPN)Gen1[0] * (XPN)r) ); + + #if REFINT == 1 + ref[i] = (LPC_PRAM) ( (LPN)((XPN)r * ISCALE)) ; // Scale-up to avoid loss of precision + #else + ref[i] = r; + #endif + + if (++i >= nc) break; + + // Update the generator matrix. + for (m = 0; m < nc - i; m++) + { +// Gen1[m] = (XPN) Gen1[m + 1] + ((XPN) r * (XPN) Gen0[m]); +// Gen0[m] = (XPN) Gen0[m] + ((XPN) r * (XPN) Gen1[m + 1]); + Gen1[m] = (LPN) ( (XPN) Gen1[m + 1] + ((XPN) r * (XPN) Gen0[m]) ); + Gen0[m] = (LPN) ( (XPN) Gen0[m] + ((XPN) r * (XPN) Gen1[m + 1]) ); + } + } + +// blk++; + return error; +} + +// ====================================================================== +// Compute the autocorrelation +void autocorrelation(int n, LPC_WORD const *ibuf, int nc, LPC_CORR *ac) +{ + int i; + + // Copy integer data to float -- speeds things up slightly... + LPC_FLOAT buf[ZWINMAX]; + for (i = 0; i < n ; i++) buf[i] = (LPC_FLOAT) ibuf[i]; + + while (nc--) + { + LPC_CORR c = 0; + LPC_FLOAT const *lbuf = buf + nc; // Points to current sample + nc + + #define CI(I) ( ((XPN)buf[I] * (XPN)lbuf[I]) ) + //#define CI(I) (buf[I] * lbuf[I]) + + int istop = n - nc - 15; // Process 16 steps at a time for speed... + for (i = 0; i < istop; i += 16) + c = (LPN) ((XPN) c + CI(i+0) + CI(i+1) + CI(i+2) + CI(i+3) + CI(i+4) + CI(i+5) + CI(i+6) + CI(i+7) + + CI(i+8) + CI(i+9) + CI(i+10)+ CI(i+11)+ CI(i+12)+ CI(i+13)+ CI(i+14)+ CI(i+15) ); + + istop = n - nc; // Process any remainder, one step at a time... + for (; i < istop; i++) + c = (LPN) ( (XPN) c + CI(i) ); + + ac[nc] = c; + #undef CI + } +} + + +// ====================================================================== +// Add the autocorrelation for the end section of previous Window / start of current window +void AddAC (LPC_WORD const *hbuf, LPC_WORD const *ibuf, int nc, LPC_CORR *ac) +{ + int i; + + // Copy integer data to float -- speeds things up slightly... + LPC_FLOAT buf[PMAX*2]; + + int n = nc-1; // Number of samples is always one less than nc value + + for (i = 0; i < n ; i++) + { + buf[i] = (LPC_FLOAT) hbuf[i]; + buf[i + n] = (LPC_FLOAT) ibuf[i]; + } + + while (nc-- > 1) + { + LPC_CORR c = 0; + LPC_FLOAT const *lbuf = buf + nc; // Points to current sample + nc + + int istop; + + #define CI(I) ( ((XPN)buf[I] * (XPN)lbuf[I]) ) + //#define CI(I) (buf[I] * lbuf[I]) + + istop = n - 15; // Process 16 steps at a time for speed... + i = n - nc; + + for (; i < istop; i += 16) + c = (LPN) ( (XPN) c + CI(i+0) + CI(i+1) + CI(i+2) + CI(i+3) + CI(i+4) + CI(i+5) + CI(i+6) + CI(i+7) + + CI(i+8) + CI(i+9) + CI(i+10)+ CI(i+11)+ CI(i+12)+ CI(i+13)+ CI(i+14)+ CI(i+15) ); + + istop = n; // Process any remainder, one step at a time... + for (; i < istop; i++) + c = (LPN) ( (XPN) c + (XPN) CI(i) ); + + ac[nc] = (LPN) ( (XPN) ac[nc] + (XPN) c ); + #undef CI + } +} + +// ====================================================================== +static void LPCdecode( + LPC_PRAM const *ref, // in: [0...p-1] reflection coefficients + int nc, // in: number of coefficients + int n, // # of samples + LPC_WORD const *in, // [0...n-1] residual input + LPC_WORD *out) // out: [0...n-1] short-term signal + +{ + LPC_WORD s; + static LPC_WORD u[PMAX+1]; // NB: Intermediate values here can be out of range of AWORD + int i; + + if (in == LAW_NULL) // Initialise? + { + for (i = 0; i < PMAX; i++) u[i] = 0; + return; + } + + while (n--) + { + s = *in++; + + #if REFINT == 1 //22.4 8gm + // ------------------------------------------------------ + #define LPC_AN1(I) \ + s -= SDIV(refp[I] * up[I], ISCALE_BITS); \ + up[I+1] = up[I] + SDIV(refp[I] * s, ISCALE_BITS); \ + // ------------------------------------------------------ + + LPC_PRAM const *refp = ref+nc-1; + LPC_WORD *up = u+nc-1; + + while(refp >= ref) + { + LPC_AN1(0) ; LPC_AN1(-1); LPC_AN1(-2); LPC_AN1(-3); + LPC_AN1(-4); LPC_AN1(-5); LPC_AN1(-6); LPC_AN1(-7); + up -= 8; refp -= 8; + } + #undef LPC_AN1 + + #else + for (i = nc; i--;) + { + #if REFINT == 1 + #if 1 // Use SDIV + long m; + m = ( ref[i] * u[i] ); + s = ( s - SDIV(m, ISCALE_BITS) ); + m = ( ref[i] * s ); + u[i+1] = ( u[i] + SDIV(m, ISCALE_BITS) ); + #else + s = s - ref[i] * u[i] / ISCALE; + u[i+1] = u[i] + (ref[i] * s / ISCALE); + #endif + #else // Use floating point, convert to int... + s = s - (int) (ref[i] * u[i]); + u[i+1] = u[i] + (int) (ref[i] * s); + #endif + } + #endif + + *out++ = u[0] = s; + } +} + + +// ====================================================================== + +// UnLPC2() is called by UnLPC() -- process one LPCWIN sized chunk + +long UnLPC2(LPC_WORD *OutBuf, LPC_WORD *InBuf, short bufsize, short nc, ULONG *Flags) +{ + static LPC_WORD HistBuf[PMAX*2]; + + static LPC_CORR AcHist[HISTSIZE][PMAX+1]; + static int HistNum; + + LPC_PRAM ref[PMAX]; + LPC_CORR ac[PMAX+1]; + + int i, k; + ULONG FlagMask = 1; + int zwin = ZWINMIN; + if (nc > zwin) zwin = ZWINMAX; + + if (InBuf == LAW_NULL) // Initialise? + { + HistNum = 0; + for (i = 0; i < nc; i++) ref[i] = 0; + for (i = 0; i < PMAX*2; i++) HistBuf[i] = 0; + for (i = 0; i < PMAX+1; i++) + for (int j = 0; j < HISTSIZE; j++) + AcHist[j][i] = 0; +// LPCdecode(LAW_NULL, nc, 0, LAW_NULL, LAW_NULL); + LPCdecode(NULL, nc, 0, NULL, NULL); + return 0; + } + + //if ((bufsize % zwin) != 0) return -3; + + for (i = 0; i < bufsize; i += zwin) + { + #if HISTSIZE == 4 + for (k = 0; k < nc+1; k++) + ac[k] = (XPN)AcHist[0][k] + (XPN)AcHist[1][k] + (XPN)AcHist[2][k] + (XPN)AcHist[3][k]; + #else + for (k = 0; k < nc+1; k++) + { + ac[k] = 0; + for (int h = 0; h < HISTSIZE; h++) + ac[k] = (XPN)ac[k] + (XPN)AcHist[h][k]; + } + #endif + + // Decode... + + if ((*Flags & FlagMask) == 0) + { + schur(ac, nc, ref); + LPCdecode(ref, nc, zwin, InBuf+i, OutBuf+i); + } + else + { + LPCinit(); // Re-initialise + for (int j = 0; j < zwin; j++) OutBuf[i+j] = InBuf[i+j]; // Copy input to output + } + FlagMask <<= 1; + + // Update the AutoCorrelation history data... + AddAC(HistBuf, OutBuf+i, nc+1, AcHist[HistNum]); // Process overlap of prev. & current buffer + if (++HistNum == HISTSIZE) HistNum = 0; // Increment History counter, wrap-around if needed + + autocorrelation(zwin, OutBuf+i, nc+1, AcHist[HistNum]); // Update AcHist with current buffer + for (k = 0; k < nc; k++) HistBuf[k] = OutBuf[i+k]; // Store beginning of current buffer for next AddAC() + } + + return 0; +} + +// ====================================================================== + +void LPCinit() +{ + UnLPC2(LAW_NULL, LAW_NULL, 0, 0, (ULONG *)0); +} +// ====================================================================== + +long UnLPC(AWORD *OutBuf, AWORD *InBuf, short bufsize, short nc, ULONG *Flags) +{ + long OutBits = 0; + LPC_WORD lInBuf[MAX_BUFSIZE], lOutBuf[MAX_BUFSIZE]; + LPC_WORD *inp = lInBuf, *bufend = inp + bufsize, *outp = lOutBuf; + + int i; + + // Copy 16 bit data to 32 bits... + while (inp < bufend) *inp++ = *InBuf++; + + inp = lInBuf; + + short WinSize = LPCWIN; + if (WinSize > bufsize) WinSize = bufsize; + + int WordsLeft = bufsize; + do { + if (WordsLeft < ZWINMIN) + { + for (i = 0; i < WordsLeft; i++) + outp[i] = inp[i]; + } + else + { + long LPCout = UnLPC2(outp, inp, WinSize, nc, Flags); + if (LPCout < 0) return LPCout; + OutBits += LPCout; + } + + inp += WinSize; + outp += WinSize; + WordsLeft -= WinSize; + + } while (inp < bufend); + + // Copy 32 bit data to 16 bits... + outp = lOutBuf; bufend = outp + bufsize; + while (outp < bufend) + *OutBuf++ = (AWORD) *outp++; + + return 0; +} + + +// ====================================================================== diff --git a/jni/sfArkLib/sfklString.cpp b/jni/sfArkLib/sfklString.cpp new file mode 100755 index 0000000..93e9c0c --- /dev/null +++ b/jni/sfArkLib/sfklString.cpp @@ -0,0 +1,31 @@ +//sfArkLib String functions +// copyright 1998-2000 Andy Inman +// Contact via: http://netgenius.co.uk or http://melodymachine.com + +// This file is part of sfArkLib. +// +// sfArkLib 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. +// +// sfArkLib 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 sfArkLib. If not, see . + +#include + +const char *GetFileExt(const char *FileName) +{ + // return pointer to (final) file extension including the dot e.g. '.txt' + const char *p; + + for(p = FileName + strlen(FileName); p > FileName && *p != '.'; p--) {} + if (*p == '.') p = FileName + strlen(FileName); + return p; +} + diff --git a/jni/sfArkLib/sfklZip.cpp b/jni/sfArkLib/sfklZip.cpp new file mode 100755 index 0000000..63044a9 --- /dev/null +++ b/jni/sfArkLib/sfklZip.cpp @@ -0,0 +1,44 @@ +// sfArkLib ZLIB interface +// Copyright 1998-2000 Andy Inman +// Contact via: http://netgenius.co.uk or http://melodymachine.com + +// This file is part of sfArkLib. +// +// sfArkLib 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. +// +// sfArkLib 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 sfArkLib. If not, see . + +#include +#include + +#include "wcc.h" +#include "zlib.h" + +ULONG UnMemcomp(const BYTE *InBuf, int InBytes, BYTE *OutBuf, int OutBufLen) +{ + // Uncompress buffer using ZLIBs uncompress function... + ULONG OutBytes = OutBufLen; + int Result = uncompress(OutBuf, &OutBytes, InBuf, InBytes); + if (Result != Z_OK) // uncompress failed? + { + sprintf(MsgTxt, "ZLIB uncompress failed: %d", Result); + msg(MsgTxt, MSG_PopUp); + OutBytes = 0; + if (Result == Z_MEM_ERROR) + GlobalErrorFlag = SFARKLIB_ERR_MALLOC; + else + GlobalErrorFlag = SFARKLIB_ERR_CORRUPT; + } + + return OutBytes; +} + diff --git a/jni/sfArkLib/wcc.h b/jni/sfArkLib/wcc.h new file mode 100755 index 0000000..c2603c7 --- /dev/null +++ b/jni/sfArkLib/wcc.h @@ -0,0 +1,203 @@ +// Definitions for sfArk / WaveComp +// Copyright 1998-2000 Andy Inman +// Contact via: http://netgenius.co.uk or http://melodymachine.com + +// This file is part of sfArkLib. +// +// sfArkLib 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. +// +// sfArkLib 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 sfArkLib. If not, see . + + + +#include "sfArkLib.h" + +// ------------------------------------------------------------------------------------ +// The following are now defined in sfarklib.h ... redefined here for compatibility... +#define MAX_FILENAME SFARKLIB_MAX_FILENAME +#define MAX_FILEPATH SFARKLIB_MAX_FILEPATH +#define MAX_MSGTEXT SFARKLIB_MAX_MSGTEXT +#define MSG_SameLine SFARKLIB_MSG_SameLine +#define MSG_AppendLine SFARKLIB_MSG_AppendLine +#define MSG_PopUp SFARKLIB_MSG_PopUp + +#define msg(a, b) sfkl_msg(a, b) // Message display function +#define UpdateProgress(a) sfkl_UpdateProgress(a) // Progress indication +#define GetLicenseAgreement(a, b) sfkl_GetLicenseAgreement(a, b)// Display/confirm license +#define DisplayNotes(a, b) sfkl_DisplayNotes(a, b) // Display notes text file +#define GetsfArkLibVersion(a) sfkl_GetVersion(a) +#define Decode(a, b) sfkl_Decode(a, b) +// ------------------------------------------------------------------------------------ + +// -------- Global flags and data ---------- +#ifdef SFARKLIB_GLOBAL // Compiling main file? + //int Aborted; + int GlobalErrorFlag; + const char ProgName[] = "sfArkLib"; + const char ProgVersion[] = " 3.00"; // 5 characters xx.xx + const unsigned char ProgVersionMaj = 30; // 0-255 = V0 to V25.5xx, etc. + const unsigned char ProgVersionMin = 00; // 0-99 = Vx.x99, etc. + char MsgTxt[MAX_MSGTEXT]; // Used with sprintf to build message // Text buffer for msg() + unsigned SourceFileOffset = 0; // Set non-zero by app for self-extraction +#else + //extern int Aborted; + extern int GlobalErrorFlag; + extern char *MsgTxt; + + extern const char *ProgName; // e.g. "sfArkLib" + extern const char *ProgVersion; // e.g."2.10 " + extern const unsigned char ProgVersionMaj; // 00-255 = V25.5x, etc. + extern const unsigned char ProgVersionMin; // 00-99 = Vx.x99, etc. + extern unsigned SourceFileOffset; // Set non-zero by app for self-extraction +#endif + +// ----- typdefs ----- +typedef unsigned short USHORT; +typedef unsigned char BYTE; +typedef unsigned long ULONG; +//typedef int int; + +typedef short AWORD; // Audio word (i.e., 16-bit audio) +typedef unsigned short UAWORD; +typedef long LAWORD; // "long" audio word i.e. 32 bits +typedef unsigned long ULAWORD; + +// Types used by Bit I/O (BIO) routines... +typedef USHORT BIOWORD; +typedef ULONG BIOWORD2; + +// ------------------- + + +// ----- Constants ----- +//#ifndef 1 +//#define 1 1 +//#define 0 0 +//#endif + +#define SHIFTWIN 64 // window size used for shift operations + +// Just for readability... +#define SIGNBIT 1 +#define FLAGBIT 1 + +// Some max sizes... +#define MAX_BUFSIZE 4096 // Largest buffer size +#define MAX_AWORD ( (1 << (AWORD_BITS-1)) -1 ) // 32767 for 16-Bit AWORD +#define MAX_UAWORD ( (1 << AWORD_BITS)-1 ) // 65535 for 16-Bit AWORD + +// Typed NULLs ... +#define FL_NULL ((float *) 0) +#define AW_NULL ((AWORD *) 0) +#define LAW_NULL ((LAWORD *) 0) + +// Compression methods... +#define COMPRESSION_v1 0 // sfArk V1 compression +#define COMPRESSION_v1Fast 1 // sfArk V1.1 "Fast" compression +#define COMPRESSION_v1Full 2 // sfArk V1.1 "Full" compression + +#define COMPRESSION_v2 3 // Lowest value for V2 compression + +#define COMPRESSION_v2NonAudio 3 // sfArk V2 "NonAudio" (uses ZLib MemComp) +#define COMPRESSION_v2Turbo 4 // sfArk V2 "Turbo" compression (BD2 only, maxloops 3) +#define COMPRESSION_v2Fast 5 // sfArk V2 "Fast" compression (BD2,3,4, maxloops 15) +#define COMPRESSION_v2Standard 6 // sfArk V2 "Standard" compression (BD2 + LPC, 8 LPC parameters) +#define COMPRESSION_v2Max 7 // sfArk V2 "Max" compression (BD2, 3, 4 + LPC with 128(?) LPC parameters) +#define COMPRESSION_v2Custom 8 // sfArk V2 "Custom" compression (user choices) +#define COMPRESSION_NotV1 254 // Returned by ReadV1Header() for non-V1 files +#define COMPRESSION_Error 255 // Returned by ReadV1Header() for unrecognised compression type + +// ---------------------- + +// ------ Macros ------- +#define RETURN_ON_ERROR() if (GlobalErrorFlag != SFARKLIB_SUCCESS) return(GlobalErrorFlag) +#define JUMP_ON_ERROR(label) if (GlobalErrorFlag != SFARKLIB_SUCCESS) goto label + +//#ifdef __BIG_ENDIAN__ +// #define FIX_ENDIAN16(w) ((((BYTE) w) << 8) | (((USHORT)w) >> 8)) +//#else + #define FIX_ENDIAN16(w) (w) +//#endif + +#define BIT_SIZEOF(x) (sizeof(x) * 8) +#define AWORD_BITS BIT_SIZEOF(AWORD) // Number of bits in Audio Word + +#define ABS(x) ( ((x) > 0) ? (x) : -(x)) + +#define MIN(x, y) ( ( (x) < (y) )? (x) : (y) ) +#define MAX(x, y) ( ( (x) > (y) )? (x) : (y) ) +#define NZSIGN(w) ((w) != 0) // Used to add 1 for SignBit if value is non-zero +#define LOWBITS(w, n) ( (w) & ((1 << (n))-1) ) + + +#if 0 // Safer methods (use in case of compile compatibility problems, etc)... +#define SIGN(x) ( ((x) >= 0) ? 0 : 1) +#define QUICKABS(x) ABS(x) +#define QUICKABS2(x) ( ABS(x) - SIGN(x) ) + +#else +// Quick "absolute value" for (much faster than using conditional) ... +// if x is positive QUICKABS2(x) = abs(x) ... but... +// if x is negative QUICKABS2(x) = abs(x)-1 -- wrong! but suits many of our purposes here! +#define SIGN(x) ( (((x)) >> (BIT_SIZEOF(x)-1)) & 1 ) // Fast! Returns 0 for positive, 1 for negative +#define QUICKABS2(x) ( (x) ^ ( (x) >> (BIT_SIZEOF(x)-1) ) ) // Fast version (inaccurate for negative value) +#define QUICKABS(x) ( QUICKABS2(x) + SIGN(x) ) // Correct ABS value + +#endif + +// Fast division using Shift for Unsigned numbers (or where innacuracy isn't a problem) +// Innacurate on negative odd numbers, e.g. NSDIV(-100, 1) gives -51 instead of -50. (Use SDIV instead). +#define NSDIV(x, y) ( (x) >> (y) ) + +// Fast division using Shift for Signed numbers +#define SDIV(x, y) ( ((x) >= 0)? (x) >> (y) : -((-(x)) >> (y)) ) + +// ------- Prototypes ------- + +// sfArkLib_Coding... +//extern USHORT GetsfArkLibVersion(void); +//extern int Decode(const char *InFileName, const char *ReqOutFileName); +extern void FixEndian(void *num, int nsize); + +// sfArkLib_Diff... +extern long BufSum(const AWORD *buf, USHORT bufsize); +extern void UnBufDif2(AWORD *OutBuf, const AWORD *InBuf, USHORT bufsize, AWORD *prev); +extern void UnBufDif4(AWORD *OutBuf, const AWORD *InBuf, USHORT bufsize, AWORD *prev); +extern void UnBufDif3(AWORD *OutBuf, const AWORD *InBuf, USHORT bufsize, AWORD *prev); +extern void UnBufShift(AWORD *Buf, USHORT SizeOfBuf, short *Shifts); + +// sfArkLib_Crunch... +extern long UnCrunchWin(AWORD *Buf, USHORT BufSize, USHORT WinSize); +extern void BioDecompInit(void); +extern void BioDecompEnd(void); +extern BIOWORD BioRead(int NumberOfBits); +extern int BioReadFlag(void); +extern long BioReadBuf(BYTE *Buf, long BufSize); +extern AWORD InputDiff(AWORD PrevValue); +extern short GetNBits(short w); + +// sfArkLib_File (or supplied by SDL.cpp)... +extern void OpenOutputFile(const char *FileName); +extern void OpenInputFile(const char *FileName); +extern int ReadInputFile(BYTE *Buf, int NumberOfBytesToRead); +extern int WriteOutputFile(const BYTE *Buf, int NumberOfBytesToWrite); +extern int SetInputFilePosition(int NewPos); +extern int SetOutputFilePosition(int NewPos); +extern void CloseInputFile(void); +extern void CloseOutputFile(void); + +// sfArkLib_LPC... +extern void LPCinit(void); +extern long UnLPC(AWORD *OutBuf, AWORD *InBuf, short bufsize, short nc, ULONG *Flags); + +// sfArkLib_Zip... +extern ULONG UnMemcomp(const BYTE *InBuf, int InBytes, BYTE *OutBuf, int OutBufLen); diff --git a/jni/timidity/Android.mk b/jni/timidity/Android.mk index 3aa7303..ef96022 100755 --- a/jni/timidity/Android.mk +++ b/jni/timidity/Android.mk @@ -39,7 +39,6 @@ LOCAL_SRC_FILES+= mod.c LOCAL_SRC_FILES+= mod2midi.c LOCAL_SRC_FILES+= modmid_a.c LOCAL_SRC_FILES+= mt19937ar.c -#LOCAL_SRC_FILES+= opensl_io.c LOCAL_SRC_FILES+= optcode.c LOCAL_SRC_FILES+= output.c LOCAL_SRC_FILES+= playmidi.c diff --git a/jni/timidity/a.exe b/jni/timidity/a.exe deleted file mode 100755 index e26739e..0000000 Binary files a/jni/timidity/a.exe and /dev/null differ diff --git a/jni/timidity/opensl_io.c b/jni/timidity/opensl_io.c deleted file mode 100755 index 23189e5..0000000 --- a/jni/timidity/opensl_io.c +++ /dev/null @@ -1,534 +0,0 @@ -/* -opensl_io.c: -Android OpenSL input/output module -Copyright (c) 2012, Victor Lazzarini -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "opensl_io.h" -#define CONV16BIT 32768 -#define CONVMYFLT (1./32768.) -#include -#include -#include -#include -static void* createThreadLock(void); -static int waitThreadLock(void *lock); -static void notifyThreadLock(void *lock); -static void destroyThreadLock(void *lock); -static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context); -static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context); -// creates the OpenSL ES audio engine -static SLresult openSLCreateEngine(OPENSL_STREAM *p) -{ - SLresult result; - // create engine - result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL); - if(result != SL_RESULT_SUCCESS) goto engine_end; - - // realize the engine - result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE); - if(result != SL_RESULT_SUCCESS) goto engine_end; - - // get the engine interface, which is needed in order to create other objects - result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, &(p->engineEngine)); - if(result != SL_RESULT_SUCCESS) goto engine_end; - - engine_end: - return result; -} - -// opens the OpenSL ES device for output -static SLresult openSLPlayOpen(OPENSL_STREAM *p) -{ - SLresult result; - SLuint32 sr = p->sr; - SLuint32 channels = p->outchannels; - - if(channels){ - // configure audio source - SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; - - switch(sr){ - - case 8000: - sr = SL_SAMPLINGRATE_8; - break; - case 11025: - sr = SL_SAMPLINGRATE_11_025; - break; - case 16000: - sr = SL_SAMPLINGRATE_16; - break; - case 22050: - sr = SL_SAMPLINGRATE_22_05; - break; - case 24000: - sr = SL_SAMPLINGRATE_24; - break; - case 32000: - sr = SL_SAMPLINGRATE_32; - break; - case 44100: - sr = SL_SAMPLINGRATE_44_1; - break; - case 48000: - sr = SL_SAMPLINGRATE_48; - break; - case 64000: - sr = SL_SAMPLINGRATE_64; - break; - case 88200: - sr = SL_SAMPLINGRATE_88_2; - break; - case 96000: - sr = SL_SAMPLINGRATE_96; - break; - case 192000: - sr = SL_SAMPLINGRATE_192; - break; - default: - return -1; - } - - const SLInterfaceID ids[] = {SL_IID_VOLUME}; - const SLboolean req[] = {SL_BOOLEAN_FALSE}; - result = (*p->engineEngine)->CreateOutputMix(p->engineEngine, &(p->outputMixObject), 1, ids, req); - if(result != SL_RESULT_SUCCESS) goto end_openaudio; - - // realize the output mix - result = (*p->outputMixObject)->Realize(p->outputMixObject, SL_BOOLEAN_FALSE); - - int speakers; - if(channels > 1) - speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; - else speakers = SL_SPEAKER_FRONT_CENTER; - SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM,channels, sr, - SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, - speakers, SL_BYTEORDER_LITTLEENDIAN}; - - SLDataSource audioSrc = {&loc_bufq, &format_pcm}; - - // configure audio sink - SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, p->outputMixObject}; - SLDataSink audioSnk = {&loc_outmix, NULL}; - - // create audio player - const SLInterfaceID ids1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; - const SLboolean req1[] = {SL_BOOLEAN_TRUE}; - result = (*p->engineEngine)->CreateAudioPlayer(p->engineEngine, &(p->bqPlayerObject), &audioSrc, &audioSnk, - 1, ids1, req1); - if(result != SL_RESULT_SUCCESS) goto end_openaudio; - - // realize the player - result = (*p->bqPlayerObject)->Realize(p->bqPlayerObject, SL_BOOLEAN_FALSE); - if(result != SL_RESULT_SUCCESS) goto end_openaudio; - - // get the play interface - result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_PLAY, &(p->bqPlayerPlay)); - if(result != SL_RESULT_SUCCESS) goto end_openaudio; - - // get the buffer queue interface - result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, - &(p->bqPlayerBufferQueue)); - if(result != SL_RESULT_SUCCESS) goto end_openaudio; - - // register callback on the buffer queue - result = (*p->bqPlayerBufferQueue)->RegisterCallback(p->bqPlayerBufferQueue, bqPlayerCallback, p); - if(result != SL_RESULT_SUCCESS) goto end_openaudio; - - // set the player's state to playing - result = (*p->bqPlayerPlay)->SetPlayState(p->bqPlayerPlay, SL_PLAYSTATE_PLAYING); - - end_openaudio: - return result; - } - return SL_RESULT_SUCCESS; -} - -// Open the OpenSL ES device for input -static SLresult openSLRecOpen(OPENSL_STREAM *p){ - - SLresult result; - SLuint32 sr = p->sr; - SLuint32 channels = p->inchannels; - - if(channels){ - - switch(sr){ - - case 8000: - sr = SL_SAMPLINGRATE_8; - break; - case 11025: - sr = SL_SAMPLINGRATE_11_025; - break; - case 16000: - sr = SL_SAMPLINGRATE_16; - break; - case 22050: - sr = SL_SAMPLINGRATE_22_05; - break; - case 24000: - sr = SL_SAMPLINGRATE_24; - break; - case 32000: - sr = SL_SAMPLINGRATE_32; - break; - case 44100: - sr = SL_SAMPLINGRATE_44_1; - break; - case 48000: - sr = SL_SAMPLINGRATE_48; - break; - case 64000: - sr = SL_SAMPLINGRATE_64; - break; - case 88200: - sr = SL_SAMPLINGRATE_88_2; - break; - case 96000: - sr = SL_SAMPLINGRATE_96; - break; - case 192000: - sr = SL_SAMPLINGRATE_192; - break; - default: - return -1; - } - - // configure audio source - SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, - SL_DEFAULTDEVICEID_AUDIOINPUT, NULL}; - SLDataSource audioSrc = {&loc_dev, NULL}; - - // configure audio sink - int speakers; - if(channels > 1) - speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; - else speakers = SL_SPEAKER_FRONT_CENTER; - SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; - SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, channels, sr, - SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, - speakers, SL_BYTEORDER_LITTLEENDIAN}; - SLDataSink audioSnk = {&loc_bq, &format_pcm}; - - // create audio recorder - // (requires the RECORD_AUDIO permission) - const SLInterfaceID id[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; - const SLboolean req[1] = {SL_BOOLEAN_TRUE}; - result = (*p->engineEngine)->CreateAudioRecorder(p->engineEngine, &(p->recorderObject), &audioSrc, - &audioSnk, 1, id, req); - if (SL_RESULT_SUCCESS != result) goto end_recopen; - - // realize the audio recorder - result = (*p->recorderObject)->Realize(p->recorderObject, SL_BOOLEAN_FALSE); - if (SL_RESULT_SUCCESS != result) goto end_recopen; - - // get the record interface - result = (*p->recorderObject)->GetInterface(p->recorderObject, SL_IID_RECORD, &(p->recorderRecord)); - if (SL_RESULT_SUCCESS != result) goto end_recopen; - - // get the buffer queue interface - result = (*p->recorderObject)->GetInterface(p->recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, - &(p->recorderBufferQueue)); - if (SL_RESULT_SUCCESS != result) goto end_recopen; - - // register callback on the buffer queue - result = (*p->recorderBufferQueue)->RegisterCallback(p->recorderBufferQueue, bqRecorderCallback, - p); - if (SL_RESULT_SUCCESS != result) goto end_recopen; - result = (*p->recorderRecord)->SetRecordState(p->recorderRecord, SL_RECORDSTATE_RECORDING); - - end_recopen: - return result; - } - else return SL_RESULT_SUCCESS; - - -} - -// close the OpenSL IO and destroy the audio engine -static void openSLDestroyEngine(OPENSL_STREAM *p){ - - // destroy buffer queue audio player object, and invalidate all associated interfaces - if (p->bqPlayerObject != NULL) { - (*p->bqPlayerObject)->Destroy(p->bqPlayerObject); - p->bqPlayerObject = NULL; - p->bqPlayerPlay = NULL; - p->bqPlayerBufferQueue = NULL; - p->bqPlayerEffectSend = NULL; - } - - // destroy audio recorder object, and invalidate all associated interfaces - if (p->recorderObject != NULL) { - (*p->recorderObject)->Destroy(p->recorderObject); - p->recorderObject = NULL; - p->recorderRecord = NULL; - p->recorderBufferQueue = NULL; - } - - // destroy output mix object, and invalidate all associated interfaces - if (p->outputMixObject != NULL) { - (*p->outputMixObject)->Destroy(p->outputMixObject); - p->outputMixObject = NULL; - } - - // destroy engine object, and invalidate all associated interfaces - if (p->engineObject != NULL) { - (*p->engineObject)->Destroy(p->engineObject); - p->engineObject = NULL; - p->engineEngine = NULL; - } - -} - - -// open the android audio device for input and/or output -OPENSL_STREAM *android_OpenAudioDevice(int sr, int inchannels, int outchannels, int bufferframes){ - - OPENSL_STREAM *p; - p = (OPENSL_STREAM *) calloc(sizeof(OPENSL_STREAM),1); - - p->inchannels = inchannels; - p->outchannels = outchannels; - p->sr = sr; - p->inlock = createThreadLock(); - p->outlock = createThreadLock(); - - if((p->outBufSamples = bufferframes*outchannels) != 0) { - if((p->outputBuffer[0] = (short *) calloc(p->outBufSamples, sizeof(short))) == NULL || - (p->outputBuffer[1] = (short *) calloc(p->outBufSamples, sizeof(short))) == NULL) { - android_CloseAudioDevice(p); - return NULL; - } - } - - if((p->inBufSamples = bufferframes*inchannels) != 0){ - if((p->inputBuffer[0] = (short *) calloc(p->inBufSamples, sizeof(short))) == NULL || - (p->inputBuffer[1] = (short *) calloc(p->inBufSamples, sizeof(short))) == NULL){ - android_CloseAudioDevice(p); - return NULL; - } - } - - p->currentInputIndex = 0; - p->currentOutputBuffer = 0; - p->currentInputIndex = p->inBufSamples; - p->currentInputBuffer = 0; - - if(openSLCreateEngine(p) != SL_RESULT_SUCCESS) { - android_CloseAudioDevice(p); - return NULL; - } - - if(openSLRecOpen(p) != SL_RESULT_SUCCESS) { - android_CloseAudioDevice(p); - return NULL; - } - - if(openSLPlayOpen(p) != SL_RESULT_SUCCESS) { - android_CloseAudioDevice(p); - return NULL; - } - - notifyThreadLock(p->outlock); - notifyThreadLock(p->inlock); - - p->time = 0.; - return p; -} - -// close the android audio device -void android_CloseAudioDevice(OPENSL_STREAM *p){ - - if (p == NULL) - return; - - openSLDestroyEngine(p); - - if (p->inlock != NULL) { - notifyThreadLock(p->inlock); - destroyThreadLock(p->inlock); - p->inlock = NULL; - } - - if (p->outlock != NULL) { - notifyThreadLock(p->outlock); - destroyThreadLock(p->outlock); - p->inlock = NULL; - } - - if (p->outputBuffer[0] != NULL) { - free(p->outputBuffer[0]); - p->outputBuffer[0] = NULL; - } - - if (p->outputBuffer[1] != NULL) { - free(p->outputBuffer[1]); - p->outputBuffer[1] = NULL; - } - - if (p->inputBuffer[0] != NULL) { - free(p->inputBuffer[0]); - p->inputBuffer[0] = NULL; - } - - if (p->inputBuffer[1] != NULL) { - free(p->inputBuffer[1]); - p->inputBuffer[1] = NULL; - } - - free(p); -} - -// returns timestamp of the processed stream -double android_GetTimestamp(OPENSL_STREAM *p){ - return p->time; -} -int android_getOutputBuffer(OPENSL_STREAM *p) -{ - return p->currentOutputBuffer; -} - -// this callback handler is called every time a buffer finishes recording -void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context) -{ - OPENSL_STREAM *p = (OPENSL_STREAM *) context; - notifyThreadLock(p->inlock); -} - -// gets a buffer of size samples from the device -int android_AudioIn(OPENSL_STREAM *p,float *buffer,int size){ - short *inBuffer; - int i, bufsamps = p->inBufSamples, index = p->currentInputIndex; - if(p == NULL || bufsamps == 0) return 0; - - inBuffer = p->inputBuffer[p->currentInputBuffer]; - for(i=0; i < size; i++){ - if (index >= bufsamps) { - waitThreadLock(p->inlock); - (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue, - inBuffer,bufsamps*sizeof(short)); - p->currentInputBuffer = (p->currentInputBuffer ? 0 : 1); - index = 0; - inBuffer = p->inputBuffer[p->currentInputBuffer]; - } - buffer[i] = (float) inBuffer[index++]*CONVMYFLT; - } - p->currentInputIndex = index; - if(p->outchannels == 0) p->time += (double) size/(p->sr*p->inchannels); - return i; -} - -// this callback handler is called every time a buffer finishes playing -void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) -{ - OPENSL_STREAM *p = (OPENSL_STREAM *) context; - notifyThreadLock(p->outlock); -} - -// puts a buffer of size samples to the device -int android_AudioOut(OPENSL_STREAM *p, char *buffer,int size){ - - short *outBuffer; - int i, bufsamps = p->outBufSamples, index = p->currentOutputIndex; - if(p == NULL || bufsamps == 0) return 0; - outBuffer = p->outputBuffer[p->currentOutputBuffer]; - - for(i=0; i < size; i++){ - outBuffer[index++] = (short) (((int)(char)buffer[i])*CONV16BIT); - if (index >= p->outBufSamples) { - waitThreadLock(p->outlock); - (*p->bqPlayerBufferQueue)->Enqueue(p->bqPlayerBufferQueue, - outBuffer,bufsamps*sizeof(short)); - p->currentOutputBuffer = (p->currentOutputBuffer ? 0 : 1); - index = 0; - outBuffer = p->outputBuffer[p->currentOutputBuffer]; - } - } - p->currentOutputIndex = index; - p->time += (double) size/(p->sr*p->outchannels); - return i; -} - -//---------------------------------------------------------------------- -// thread Locks -// to ensure synchronisation between callbacks and processing code -void* createThreadLock(void) -{ - threadLock *p; - p = (threadLock*) malloc(sizeof(threadLock)); - if (p == NULL) - return NULL; - memset(p, 0, sizeof(threadLock)); - if (pthread_mutex_init(&(p->m), (pthread_mutexattr_t*) NULL) != 0) { - free((void*) p); - return NULL; - } - if (pthread_cond_init(&(p->c), (pthread_condattr_t*) NULL) != 0) { - pthread_mutex_destroy(&(p->m)); - free((void*) p); - return NULL; - } - p->s = (unsigned char) 1; - - return p; -} - -int waitThreadLock(void *lock) -{ - threadLock *p; - int retval = 0; - p = (threadLock*) lock; - pthread_mutex_lock(&(p->m)); - while (!p->s) { - pthread_cond_wait(&(p->c), &(p->m)); - } - p->s = (unsigned char) 0; - pthread_mutex_unlock(&(p->m)); -} - -void notifyThreadLock(void *lock) -{ - threadLock *p; - p = (threadLock*) lock; - pthread_mutex_lock(&(p->m)); - p->s = (unsigned char) 1; - pthread_cond_signal(&(p->c)); - pthread_mutex_unlock(&(p->m)); -} - -void destroyThreadLock(void *lock) -{ - threadLock *p; - p = (threadLock*) lock; - if (p == NULL) - return; - notifyThreadLock(p); - pthread_cond_destroy(&(p->c)); - pthread_mutex_destroy(&(p->m)); - free(p); -} diff --git a/jni/timidity/opensl_io.h b/jni/timidity/opensl_io.h deleted file mode 100755 index bc0ab67..0000000 --- a/jni/timidity/opensl_io.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -opensl_io.c: -Android OpenSL input/output module header -Copyright (c) 2012, Victor Lazzarini -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef OPENSL_IO -#define OPENSL_IO - -#include -#include -#include -#include - -typedef struct threadLock_{ - pthread_mutex_t m; - pthread_cond_t c; - unsigned char s; -} threadLock; - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct opensl_stream { - - // engine interfaces - SLObjectItf engineObject; - SLEngineItf engineEngine; - - // output mix interfaces - SLObjectItf outputMixObject; - - // buffer queue player interfaces - SLObjectItf bqPlayerObject; - SLPlayItf bqPlayerPlay; - SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; - SLEffectSendItf bqPlayerEffectSend; - - // recorder interfaces - SLObjectItf recorderObject; - SLRecordItf recorderRecord; - SLAndroidSimpleBufferQueueItf recorderBufferQueue; - - // buffer indexes - int currentInputIndex; - int currentOutputIndex; - - // current buffer half (0, 1) - int currentOutputBuffer; - int currentInputBuffer; - - // buffers - short *outputBuffer[2]; - short *inputBuffer[2]; - - // size of buffers - int outBufSamples; - int inBufSamples; - - // locks - void* inlock; - void* outlock; - - double time; - int inchannels; - int outchannels; - int sr; - -} OPENSL_STREAM; - - /* - Open the audio device with a given sampling rate (sr), input and output channels and IO buffer size - in frames. Returns a handle to the OpenSL stream - */ - OPENSL_STREAM* android_OpenAudioDevice(int sr, int inchannels, int outchannels, int bufferframes); - /* - Close the audio device - */ - void android_CloseAudioDevice(OPENSL_STREAM *p); - /* - Read a buffer from the OpenSL stream *p, of size samples. Returns the number of samples read. - */ - int android_AudioIn(OPENSL_STREAM *p, float *buffer,int size); - /* - Write a buffer to the OpenSL stream *p, of size samples. Returns the number of samples written. - */ - int android_AudioOut(OPENSL_STREAM *p, char *buffer,int size); - /* - Get the current IO block time in seconds - */ - double android_GetTimestamp(OPENSL_STREAM *p); - int android_getOutputBuffer(OPENSL_STREAM *p); -#ifdef __cplusplus -}; -#endif - -#endif // #ifndef OPENSL_IO diff --git a/project.properties b/project.properties index 7de2846..38ddba3 100755 --- a/project.properties +++ b/project.properties @@ -12,5 +12,5 @@ # Project target. target=android-23 -android.library.reference.1=..\\..\\..\\..\\Program Files (x86)\\Android\\android-sdk\\extras\\android\\support\\v7\\appcompat -android.library.reference.2=..\\android-support-v4-preferencefragment +android.library.reference.1=..\\appcompat_v7 +android.library.reference.2=../../PreferenceFragment-Compat diff --git a/res/drawable-hdpi/ic_menu_moreoverflow.png b/res/drawable-hdpi/ic_menu_moreoverflow.png new file mode 100755 index 0000000..33bb5e7 Binary files /dev/null and b/res/drawable-hdpi/ic_menu_moreoverflow.png differ diff --git a/res/drawable-mdpi/ic_menu_moreoverflow.png b/res/drawable-mdpi/ic_menu_moreoverflow.png new file mode 100755 index 0000000..e478922 Binary files /dev/null and b/res/drawable-mdpi/ic_menu_moreoverflow.png differ diff --git a/res/drawable-xhdpi/ic_menu_moreoverflow.png b/res/drawable-xhdpi/ic_menu_moreoverflow.png new file mode 100755 index 0000000..2998d65 Binary files /dev/null and b/res/drawable-xhdpi/ic_menu_moreoverflow.png differ diff --git a/res/drawable-xxhdpi/ic_menu_moreoverflow.png b/res/drawable-xxhdpi/ic_menu_moreoverflow.png new file mode 100755 index 0000000..c3a1390 Binary files /dev/null and b/res/drawable-xxhdpi/ic_menu_moreoverflow.png differ diff --git a/res/layout-v14/list_reorder.xml b/res/layout-v14/list_reorder.xml new file mode 100755 index 0000000..b993543 --- /dev/null +++ b/res/layout-v14/list_reorder.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/res/layout-v14/row_menu.xml b/res/layout-v14/row_menu.xml new file mode 100755 index 0000000..afb24f9 --- /dev/null +++ b/res/layout-v14/row_menu.xml @@ -0,0 +1,29 @@ + + + + + + + + \ No newline at end of file diff --git a/res/layout-v21/music_notification.xml b/res/layout-v21/music_notification.xml index 3930d2b..b65a4ec 100755 --- a/res/layout-v21/music_notification.xml +++ b/res/layout-v21/music_notification.xml @@ -17,9 +17,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" - android:singleLine="true" - android:ellipsize="end" android:layout_toEndOf="@id/imagey" + android:ellipsize="end" + android:singleLine="true" android:text="" android:textColor="#000000" /> diff --git a/res/layout-v21/settings_toolbar.xml b/res/layout-v21/settings_toolbar.xml index a15785f..f3bf4e3 100755 --- a/res/layout-v21/settings_toolbar.xml +++ b/res/layout-v21/settings_toolbar.xml @@ -1,15 +1,12 @@ - - \ No newline at end of file + app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" + app:title="@string/action_settings" /> diff --git a/res/layout/filebrowser.xml b/res/layout/filebrowser.xml index 7bdb8f2..a69fe61 100755 --- a/res/layout/filebrowser.xml +++ b/res/layout/filebrowser.xml @@ -1,46 +1,24 @@ - - - - - - - - - + android:descendantFocusability="blocksDescendants" + android:orientation="vertical" > + + + + + + + + \ No newline at end of file diff --git a/res/layout/fragment_page.xml b/res/layout/fragment_page.xml index c6fae6f..0e365a3 100755 --- a/res/layout/fragment_page.xml +++ b/res/layout/fragment_page.xml @@ -1,5 +1,5 @@ \ No newline at end of file + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" /> diff --git a/res/layout/list.xml b/res/layout/list.xml index 92d4486..06a76b9 100755 --- a/res/layout/list.xml +++ b/res/layout/list.xml @@ -1,17 +1,15 @@ - + + + + - - - \ No newline at end of file diff --git a/res/layout/lyrical_fragment.xml b/res/layout/lyrical_fragment.xml index 1e96895..fb1d87e 100755 --- a/res/layout/lyrical_fragment.xml +++ b/res/layout/lyrical_fragment.xml @@ -1,21 +1,20 @@ - + android:layout_height="fill_parent" > - + android:orientation="vertical" > + + + - \ No newline at end of file diff --git a/res/layout/main.xml b/res/layout/main.xml index 8d15792..6d3d1ac 100755 --- a/res/layout/main.xml +++ b/res/layout/main.xml @@ -3,9 +3,10 @@ android:id="@+id/vp_main" android:layout_width="match_parent" android:layout_height="match_parent" > - + + \ No newline at end of file diff --git a/res/layout/midi_options.xml b/res/layout/midi_options.xml index 18790c5..537e1b9 100755 --- a/res/layout/midi_options.xml +++ b/res/layout/midi_options.xml @@ -1,185 +1,181 @@ - + android:focusableInTouchMode="true" + android:padding="3dp" > - + android:orientation="vertical" + android:paddingEnd="5dp" + android:paddingLeft="5dp" + android:paddingRight="5dp" + android:paddingStart="5dp" > + + + + + +