Imported Upstream version 1.9.0

parent ed1a9897
## Process this file with automake to create Makefile.in
##
## $Id: Makefile.am 89 2010-04-03 15:30:08Z oparviai $
## $Id: Makefile.am 199 2014-10-05 15:33:08Z oparviai $
##
## Copyright (C) 2003 - David W. Durham
##
......@@ -26,9 +26,8 @@ include $(top_srcdir)/config/am_include.mk
## subdirectories Start at frontend_fox/Makefile.am to see how everything works.
SUBDIRS=include source
# list files that are documentation to be packaged in a release tarball and installed
pkgdoc_DATA=COPYING.TXT README.html
dist_doc_DATA=COPYING.TXT README.html
# extra data files that are to be pacakged in a release tarball and installed into the data directory
#pkgdata_DATA=
......
This diff is collapsed.
## vim:tw=78
## Process this file with automake to create Makefile.in
##
## $Id: am_include.mk 130 2011-07-17 11:46:22Z oparviai $
## $Id: am_include.mk 218 2015-05-18 17:04:47Z oparviai $
##
## This file is part of SoundTouch, an audio processing library for pitch/time adjustments
##
......@@ -22,13 +22,7 @@
## It is actually included when a makefile.am is coverted to Makefile.in
## by automake, so it's ok to have @MACROS@ that will be set by configure
## INCLUDES is automatically added to CXXFLAGS at compile time. The
## $(top_srcdir) macro is set by configure. It's important to use $(top_srcdir)
## in case a user decides to build in a separate directory from the base package
## directory. Using absolute, or relative paths is a bad idea.
INCLUDES=-I$(top_srcdir)/include
AM_CPPFLAGS=-I$(top_srcdir)/include
# doc directory
pkgdocdir=$(prefix)/doc/@PACKAGE@
dnl SoundTouch configure.ac, by David W. Durham
dnl
dnl $Id: configure.ac 188 2014-01-07 19:58:54Z oparviai $
dnl $Id: configure.ac 221 2015-05-18 17:54:01Z oparviai $
dnl
dnl This file is part of SoundTouch, an audio processing library for pitch/time adjustments
dnl
......@@ -19,9 +19,10 @@ dnl this program; if not, write to the Free Software Foundation, Inc., 59 Temple
dnl Place - Suite 330, Boston, MA 02111-1307, USA
# Process this file with autoconf to produce a configure script.
AC_INIT(SoundTouch, 1.8.0, [http://www.surina.net/soundtouch])
AC_INIT(SoundTouch, 1.9.0, [http://www.surina.net/soundtouch])
AC_CONFIG_AUX_DIR(config)
AM_CONFIG_HEADER([include/soundtouch_config.h])
AC_CONFIG_MACRO_DIR([config/m4])
AM_CONFIG_HEADER([config.h include/soundtouch_config.h])
AM_INIT_AUTOMAKE
AM_SILENT_RULES([yes])
#AC_DISABLE_SHARED dnl This makes libtool only build static libs
......@@ -78,10 +79,15 @@ AC_C_INLINE
AC_ARG_ENABLE(integer-samples,
[AC_HELP_STRING([--enable-integer-samples],
[use integer samples instead of floats
[default=yes]])],,
[default=no]])],,
[enable_integer_samples=no])
AC_ARG_ENABLE(openmp,
[AC_HELP_STRING([--enable-openmp],
[use parallel multicore calculation through OpenMP [default=no]])],,
[enable_openmp=no])
# Let the user enable/disable the x86 optimizations.
# Useful when compiling on non-x86 architectures.
AC_ARG_ENABLE([x86-optimizations],
......@@ -105,14 +111,21 @@ else
fi
if test "x$enable_openmp" = "xyes"; then
echo "****** openmp optimizations enabled ******"
AM_CXXFLAGS="-fopenmp $AM_CXXFLAGS"
else
echo "****** openmp optimizations disabled ******"
fi
# Check if optimizations are supported in the system at build time.
if test "x$enable_x86_optimizations" = "xyes" -a "x$ac_cv_header_cpuid_h" = "xyes"; then
echo "****** x86 optimizations enabled ******"
original_saved_CXXFLAGS=$CXXFLAGS
have_mmx_intrinsics=no
OPT_CXXFLAGS="-mmmx -Winline"
CXXFLAGS="$OPT_CXXFLAGS $CXXFLAGS"
CXXFLAGS="-mmmx -Winline $CXXFLAGS"
# Check if the user can compile MMX code using intrinsics.
# GCC supports MMX intrinsics since version 3.3
......@@ -143,9 +156,10 @@ if test "x$enable_x86_optimizations" = "xyes" -a "x$ac_cv_header_cpuid_h" = "xye
fi
# SSE support
original_saved_CXXFLAGS=$CXXFLAGS
have_sse_intrinsics=no
OPT_CXXFLAGS="-msse -Winline"
CXXFLAGS="$OPT_CXXFLAGS $CXXFLAGS"
CXXFLAGS="-msse -Winline $CXXFLAGS"
# Check if the user can compile SSE code using intrinsics.
# GCC supports SSE intrinsics since version 3.3
......@@ -181,6 +195,13 @@ else
AC_DEFINE([SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS],[1],[Do not use x86 optimizations])
fi
# Set AM_CXXFLAGS
AC_SUBST([AM_CXXFLAGS], [$AM_CXXFLAGS])
# Empty default CXXFLAGS so user can set them if desirable
AC_SUBST([CXXFLAGS], [ ])
# SSTypes.h by default enables optimizations. Those already got disabled if
# the user requested for it or if the system does not support them.
#
......
......@@ -26,7 +26,7 @@
///
////////////////////////////////////////////////////////////////////////////////
//
// Last changed : $Date: 2012-08-30 22:53:44 +0300 (Thu, 30 Aug 2012) $
// Last changed : $Date: 2012-08-30 19:53:44 +0000 (Thu, 30 Aug 2012) $
// File revision : $Revision: 4 $
//
// $Id: BPMDetect.h 150 2012-08-30 19:53:44Z oparviai $
......
......@@ -15,7 +15,7 @@
///
////////////////////////////////////////////////////////////////////////////////
//
// Last changed : $Date: 2014-01-05 23:40:22 +0200 (Sun, 05 Jan 2014) $
// Last changed : $Date: 2014-01-05 21:40:22 +0000 (Sun, 05 Jan 2014) $
// File revision : $Revision: 4 $
//
// $Id: FIFOSampleBuffer.h 177 2014-01-05 21:40:22Z oparviai $
......
......@@ -17,7 +17,7 @@
///
////////////////////////////////////////////////////////////////////////////////
//
// Last changed : $Date: 2012-06-13 22:29:53 +0300 (Wed, 13 Jun 2012) $
// Last changed : $Date: 2012-06-13 19:29:53 +0000 (Wed, 13 Jun 2012) $
// File revision : $Revision: 4 $
//
// $Id: FIFOSamplePipe.h 143 2012-06-13 19:29:53Z oparviai $
......
......@@ -8,10 +8,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
// Last changed : $Date: 2014-01-07 20:24:28 +0200 (Tue, 07 Jan 2014) $
// Last changed : $Date: 2015-05-18 15:25:07 +0000 (Mon, 18 May 2015) $
// File revision : $Revision: 3 $
//
// $Id: STTypes.h 183 2014-01-07 18:24:28Z oparviai $
// $Id: STTypes.h 215 2015-05-18 15:25:07Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
......@@ -60,20 +60,6 @@ typedef unsigned long ulong;
#include "soundtouch_config.h"
#endif
#ifndef _WINDEF_
// if these aren't defined already by Windows headers, define now
#if defined(__APPLE__)
typedef signed char BOOL;
#else
typedef int BOOL;
#endif
#define FALSE 0
#define TRUE 1
#endif // _WINDEF_
namespace soundtouch
{
......@@ -89,7 +75,7 @@ namespace soundtouch
/// runtime performance so recommendation is to keep this off.
// #define USE_MULTICH_ALWAYS
#if (defined(__SOFTFP__))
#if (defined(__SOFTFP__) && defined(ANDROID))
// For Android compilation: Force use of Integer samples in case that
// compilation uses soft-floating point emulation - soft-fp is way too slow
#undef SOUNDTOUCH_FLOAT_SAMPLES
......@@ -186,6 +172,7 @@ namespace soundtouch
#else
// use c++ standard exceptions
#include <stdexcept>
#include <string>
#define ST_THROW_RT_ERROR(x) {throw std::runtime_error(x);}
#endif
......
......@@ -41,10 +41,10 @@
///
////////////////////////////////////////////////////////////////////////////////
//
// Last changed : $Date: 2014-01-07 21:26:29 +0200 (Tue, 07 Jan 2014) $
// Last changed : $Date: 2015-05-18 15:28:41 +0000 (Mon, 18 May 2015) $
// File revision : $Revision: 4 $
//
// $Id: SoundTouch.h 185 2014-01-07 19:26:29Z oparviai $
// $Id: SoundTouch.h 216 2015-05-18 15:28:41Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
......@@ -79,10 +79,10 @@ namespace soundtouch
{
/// Soundtouch library version string
#define SOUNDTOUCH_VERSION "1.8.0"
#define SOUNDTOUCH_VERSION "1.9.0"
/// SoundTouch library version id
#define SOUNDTOUCH_VERSION_ID (10800)
#define SOUNDTOUCH_VERSION_ID (10900)
//
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
......@@ -160,7 +160,7 @@ private:
float virtualPitch;
/// Flag: Has sample rate been set?
BOOL bSrateSet;
bool bSrateSet;
/// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and
/// 'virtualPitch' parameters.
......@@ -247,8 +247,8 @@ public:
/// Changes a setting controlling the processing system behaviour. See the
/// 'SETTING_...' defines for available setting ID's.
///
/// \return 'TRUE' if the setting was succesfully changed
BOOL setSetting(int settingId, ///< Setting ID number. see SETTING_... defines.
/// \return 'true' if the setting was succesfully changed
bool setSetting(int settingId, ///< Setting ID number. see SETTING_... defines.
int value ///< New setting value.
);
......
/* Do not use x86 optimizations */
#undef SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS
/* Use Float as Sample type */
#undef SOUNDTOUCH_FLOAT_SAMPLES
/* Use Integer as Sample type */
#undef SOUNDTOUCH_INTEGER_SAMPLES
......@@ -7,7 +7,7 @@
@REM Copyright (c) Olli Parviainen
@REM File Created: 09/Sep/2003
@REM
@REM $Id: make-win.bat 142 2012-04-04 19:55:37Z oparviai $
@REM $Id: make-win.bat 197 2014-04-06 18:03:48Z oparviai $
@rem ****************************
@rem try first for VS6.0 support
......@@ -37,10 +37,12 @@ devenv source\SoundTouch\SoundTouch.vcproj /build release
devenv source\SoundStretch\SoundStretch.vcproj /upgrade
devenv source\SoundStretch\SoundStretch.vcproj /build debug
devenv source\SoundStretch\SoundStretch.vcproj /build release
devenv source\SoundStretch\SoundStretch.vcproj /build releasex64
devenv source\SoundTouchDll\SoundTouchDll.vcproj /upgrade
devenv source\SoundTouchDll\SoundTouchDll.vcproj /build debug
devenv source\SoundTouchDll\SoundTouchDll.vcproj /build release
devenv source\SoundTouchDll\SoundTouchDll.vcproj /build releasex64
@goto end
......
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ExampleActivity</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.surina.soundtouchexample"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="net.surina.ExampleActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
......@@ -45,49 +45,34 @@
open Cygwin/bash shell, go to directory <b>&quot;soundtouch/source/Android-lib/jni&quot;</b> and invoke the NDK
compiler with following command:</p>
<pre> $NDK/ndk-build</pre>
<p>This will build the ARMv5 and ARMv7 versions of SoundTouch library (including
also the example JNI
interface, see below) into the &quot;libs&quot; subdirectory.</p>
<p>This will build binaries for all the supported Android platforms (arm-v5, arm-v7, X86, MIPS etc) of SoundTouch library, plus the JNI wrapper interface as discussed below. The target binaries will be built into the &quot;libs&quot; subdirectory. As long as all these .so binary library versions are included in the APK Application delivery package, the targer Android device can choose the correct library version to use. </p>
<p>Notice that to allow Cygwin/bash to locate the NDK compile scripts, you
need to define the location of the NDK installation defined in environment
variable &quot;NDK&quot;. That's easiest done by adding the NDK path definition at end of
your <b>~/.bash_profile</b> file, for instance as follows:</p>
<pre> NDK=/cygdrive/d/Android/android-ndk-r6</pre>
<hr />
<h2>
Android floating-point performance considerations</h2>
<p><b>Enabling OpenMP parallel computing mode</b></p>
<p>
Default build target for
Android NDK is ARMv5 CPU generation, as that works in
all ARM-based Android devices.<p>
This has a pitfall though: For ideal sound quality SoundTouch should be compiled
to use floating-point algorithms, however, all low-end Android devices do not
have floating-point hardware in their CPUs, and hence the default ARMv5 compilation uses software-emulation for floating-point calculations instead of
hardware floating-point to allow running the binary executables also in low-end devices.<p>
The floating point software-emulation is however several tens of times slower
than real hardware-level floating-point calculations, making
floating-point-intensive applications such as SoundTouch infeasible with low-end
devices.<p>
As workaround, the SoundTouch Android compilation builds two separate versions
of the library:<ul>
<li>ARMv5 version that compiles SoundTouch using integer algorithm version. The integer
algorithm version compromises the sound quality but provides good performance also
with low-end
devices without hardware floating-point support in the CPU level.</li>
<li>ARMv7 version that compiles SoundTouch using hardware floating-point algorithms.
These algorithms provide ideal sound quality yet do not work in simpler CPU
models.</li>
</ul>
<p>
These two library compilations are already defined in file &quot;<b>jni/Application.mk</b>&quot;
so that these two separate library targets are automatically built under the &quot;<b>libs</b>&quot;
directory. As far as you include both these compiled library versions into your
application delivery, the Android devices can automatically select the right
library version based on the available device&#39;s capabilities.<p>
Please yet be aware that depending on capabilities of the Android devices you
will need to provide the SoundTouch routines with samples in either integer or
floating-point format, so build your interface routines to take this into
account.<hr />
SoundTouch supports OpenMP for parallel computing in multi-core
environments, and these improvements can be enabled also in the Android
build. See the SoundTouch main README.html file for generic notes about the
OpenMP implementation.</p>
<p>
To enable OpenMP mode in Android compilation, edit file <strong>Android.mk</strong>
and enable the &quot;-fopenmp&quot; flag in LOCAL_CFLAGS and LOCAL_LDFLAGS variables.
This is done by removing hash # from before the following lines in the
Android.mk file, before compiling the library:</p>
<pre> LOCAL_CFLAGS += -fopenmp
LOCAL_LDFLAGS += -fopenmp</pre>
<p><strong>OpenMP COMPATIBILITY NOTE: </strong>Android NDK has a threading issue
(at least until NDK v10) that causes the native library crash with fatal signal
11 if calling OpenMP-improved routines from a background thread. SoundTouch has
a workaround for this issue in soundtouch-jni.cpp, and this workaround requires
calling function <strong>SoundTouch.getVersionString() </strong>from the Android
application's main thread at least once before calling other SoundTouch
processing routines. See the SoundTouch Android example application and comments
in the <strong>soundtouch-jni.cpp </strong>source code file for more details.</p>
<hr />
<h2>
Calling SoundTouch native routines from Android application</h2>
<p>The NDK tools build the SoundTouch c++ routines into a native binary library, while
......@@ -96,23 +81,42 @@
Interface (JNI).</p>
<p>
The SoundTouch source code package provides source code example how to
use JNI to call native c++ routines from a Java class through the following
source code file pair:<ul>
<li><b>Android-lib/jni/soundtouch-jni.cpp</b>: This file contains c/c++ routine that
calls SoundTouch library routine to return the library version string to the main
Android application. The NDK compiles this file along with the SoundTouch
use JNI to call native c++ routines from a Java class, and provides source codes also for
a simple example Android application:<ul>
<li><b>ExampleActivity</b>: This is simple Android example application that
utilizes SoundTouch native routines for processing WAV audio files. To build the example
application, use Eclipse Android SDK environment to import the "ExampleActivity" project in the "Android-lib" folder into the Eclipse workspace.
<li><b>Android-lib/jni/soundtouch-jni.cpp</b>: This file contains c/c++ wrapper routines
for performing elementary audio file processing with adjusted tempo/pitch/speed parameters
from the Android application. The wrapper interface is not complete, but provides example
that is easy to extend when necessary. The NDK compiles this file along with the SoundTouch
routines into the native binary library.</li>
<li><b>Android-lib/src/net/surina/soundtouch/SoundTouch.java</b>: This file provides
a Java interface class to load the native library and to invoke the native routine implemented in
the file <b>soundtouch-jni.cpp</b></li>
<li><b>Android-lib/src/net/surina/soundtouch/SoundTouch.java</b>: This file implements
the Java interface class that loasd & accesses the JNI routines in the natively compiled library.
The example Android application uses this class as interface for processing audio files
with SoundTouch.</li>
</ul>
<p>
Feel free to examine and extend the provided cpp/java source code example file pair to
implement and integrate the desired SoundTouch library capabilities into your Android application.</p>
implement and integrate the desired SoundTouch library capabilities into your own Android application.</p>
<hr />
<h2>
Android floating-point performance considerations</h2>
<p>
The make process will build dedicated binaries for each supported Android CPU hardware platform type.
</p><p>SoundTouch uses floating-point algorithms for ideal sound quality on all other platform than in the lowest-end ARMv5. That is because lowest-end Android devices are not guaranteed to
have floating-point hardware in their CPUs, so that the ARMv5 compilation uses by default software-emulation for floating-point calculations to allow running the binary executables also in low-end devices without floating-point hardware.<p>
As floating point software-emulation is however several tens of times slower
than real hardware-level floating-point calculations, that would make running
floating-point-intensive applications such as SoundTouch infeasible in these low-end
devices. As workaround, the SoundTouch Android compilation builds the ARMv5 version using integer algorithm versions. The integer
algorithm version compromises the sound quality but provides good performance also
with low-end devices without hardware floating-point support in the CPU level.</p>
<p>When Android devices with more capable device is used, the device will automatically choose a proper library version for ideal sound quality.</p>
<hr />
<p style="text-align: center"><i>Copyright &copy; Olli Parviainen</i></p>
<!--
$Id: README-SoundTouch-Android.html 165 2012-12-28 19:55:23Z oparviai $
$Id: README-SoundTouch-Android.html 216 2015-05-18 15:28:41Z oparviai $
-->
</body>
</html>
\ No newline at end of file
</html>
......@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# $Id: Android.mk 165 2012-12-28 19:55:23Z oparviai $
# $Id: Android.mk 216 2015-05-18 15:28:41Z oparviai $
LOCAL_PATH := $(call my-dir)
......@@ -23,18 +23,30 @@ include $(CLEAR_VARS)
LOCAL_MODULE := soundtouch
LOCAL_SRC_FILES := soundtouch-jni.cpp ../../SoundTouch/AAFilter.cpp ../../SoundTouch/FIFOSampleBuffer.cpp \
../../SoundTouch/FIRFilter.cpp ../../SoundTouch/cpu_detect_x86.cpp \
../../SoundTouch/sse_optimized.cpp ../../SoundStretch/WavFile.cpp \
../../SoundTouch/RateTransposer.cpp ../../SoundTouch/SoundTouch.cpp \
../../SoundTouch/TDStretch.cpp ../../SoundTouch/BPMDetect.cpp ../../SoundTouch/PeakFinder.cpp
../../SoundTouch/InterpolateCubic.cpp ../../SoundTouch/InterpolateLinear.cpp \
../../SoundTouch/InterpolateShannon.cpp ../../SoundTouch/TDStretch.cpp \
../../SoundTouch/BPMDetect.cpp ../../SoundTouch/PeakFinder.cpp
# for native audio
LOCAL_LDLIBS += -lgcc
LOCAL_SHARED_LIBRARIES += -lgcc
# --whole-archive -lgcc
# for logging
LOCAL_LDLIBS += -llog
# for native asset manager
#LOCAL_LDLIBS += -landroid
# don't export all symbols
# added "-marm" switch to use arm instruction set instead of thumb for improved calculation performance.
LOCAL_CFLAGS += -Wall -fvisibility=hidden -I ../../../include -D ST_NO_EXCEPTION_HANDLING -fdata-sections -ffunction-sections -marm
# Custom Flags:
# -fvisibility=hidden : don't export all symbols
LOCAL_CFLAGS += -fvisibility=hidden -I ../../../include -fdata-sections -ffunction-sections
# OpenMP mode : enable these flags to enable using OpenMP for parallel computation
#LOCAL_CFLAGS += -fopenmp
#LOCAL_LDFLAGS += -fopenmp
# Use ARM instruction set instead of Thumb for improved calculation performance in ARM CPUs
LOCAL_ARM_MODE := arm
include $(BUILD_SHARED_LIBRARY)
# $Id: Application.mk 165 2012-12-28 19:55:23Z oparviai $
# $Id: Application.mk 212 2015-05-15 10:22:36Z oparviai $
#
# Build both ARMv5TE and ARMv7-A machine code.
# Build library bilaries for all supported architectures
#
APP_ABI := armeabi-v7a armeabi
APP_ABI := all #armeabi-v7a armeabi
APP_OPTIM := release
APP_STL := stlport_static
APP_CPPFLAGS := -fexceptions # -D SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS
......@@ -8,23 +8,155 @@
///
////////////////////////////////////////////////////////////////////////////////
//
// $Id: soundtouch-jni.cpp 173 2013-06-15 11:44:11Z oparviai $
// $Id: soundtouch-jni.cpp 212 2015-05-15 10:22:36Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
#include <jni.h>
#include <android/log.h>
#include <stdexcept>
#include <string>
using namespace std;
#include "../../../include/SoundTouch.h"
#include "../source/SoundStretch/WavFile.h"
#define LOGV(...) __android_log_print((int)ANDROID_LOG_INFO, "SOUNDTOUCH", __VA_ARGS__)
//#define LOGV(...)
// String for keeping possible c++ exception error messages. Notice that this isn't
// thread-safe but it's expected that exceptions are special situations that won't
// occur in several threads in parallel.
static string _errMsg = "";
#define DLL_PUBLIC __attribute__ ((visibility ("default")))
#define BUFF_SIZE 4096
using namespace soundtouch;
// Set error message to return
static void _setErrmsg(const char *msg)
{
_errMsg = msg;
}
#ifdef _OPENMP
#include <pthread.h>
extern pthread_key_t gomp_tls_key;
static void * _p_gomp_tls = NULL;
/// Function to initialize threading for OpenMP.
///
/// This is a workaround for bug in Android NDK v10 regarding OpenMP: OpenMP works only if
/// called from the Android App main thread because in the main thread the gomp_tls storage is
/// properly set, however, Android does not properly initialize gomp_tls storage for other threads.
/// Thus if OpenMP routines are invoked from some other thread than the main thread,
/// the OpenMP routine will crash the application due to NULL pointer access on uninitialized storage.
///
/// This workaround stores the gomp_tls storage from main thread, and copies to other threads.
/// In order this to work, the Application main thread needws to call at least "getVersionString"
/// routine.
static int _init_threading(bool warn)
{
void *ptr = pthread_getspecific(gomp_tls_key);
LOGV("JNI thread-specific TLS storage %ld", (long)ptr);
if (ptr == NULL)
{
LOGV("JNI set missing TLS storage to %ld", (long)_p_gomp_tls);
pthread_setspecific(gomp_tls_key, _p_gomp_tls);
}
else
{
LOGV("JNI store this TLS storage");
_p_gomp_tls = ptr;
}
// Where critical, show warning if storage still not properly initialized
if ((warn) && (_p_gomp_tls == NULL))
{
_setErrmsg("Error - OpenMP threading not properly initialized: Call SoundTouch.getVersionString() from the App main thread!");
return -1;
}
return 0;
}
#else
static int _init_threading(bool warn)
{
// do nothing if not OpenMP build
return 0;
}
#endif
// Processes the sound file
static void _processFile(SoundTouch *pSoundTouch, const char *inFileName, const char *outFileName)
{
int nSamples;
int nChannels;
int buffSizeSamples;
SAMPLETYPE sampleBuffer[BUFF_SIZE];
// open input file
WavInFile inFile(inFileName);
int sampleRate = inFile.getSampleRate();
int bits = inFile.getNumBits();
nChannels = inFile.getNumChannels();
// create output file
WavOutFile outFile(outFileName, sampleRate, bits, nChannels);
pSoundTouch->setSampleRate(sampleRate);
pSoundTouch->setChannels(nChannels);
assert(nChannels > 0);
buffSizeSamples = BUFF_SIZE / nChannels;
// Process samples read from the input file
while (inFile.eof() == 0)
{
int num;
// Read a chunk of samples from the input file
num = inFile.read(sampleBuffer, BUFF_SIZE);
nSamples = num / nChannels;
// Feed the samples into SoundTouch processor
pSoundTouch->putSamples(sampleBuffer, nSamples);
// Read ready samples from SoundTouch processor & write them output file.
// NOTES:
// - 'receiveSamples' doesn't necessarily return any samples at all
// during some rounds!
// - On the other hand, during some round 'receiveSamples' may have more
// ready samples than would fit into 'sampleBuffer', and for this reason
// the 'receiveSamples' call is iterated for as many times as it
// outputs samples.
do
{
nSamples = pSoundTouch->receiveSamples(sampleBuffer, buffSizeSamples);
outFile.write(sampleBuffer, nSamples * nChannels);
} while (nSamples != 0);
}
// Now the input file is processed, yet 'flush' few last samples that are
// hiding in the SoundTouch's internal processing pipeline.
pSoundTouch->flush();
do
{
nSamples = pSoundTouch->receiveSamples(sampleBuffer, buffSizeSamples);
outFile.write(sampleBuffer, nSamples * nChannels);
} while (nSamples != 0);
}
extern "C" DLL_PUBLIC jstring Java_net_surina_soundtouch_SoundTouch_getVersionString(JNIEnv *env, jobject thiz)
{
const char *verStr;
......@@ -34,6 +166,94 @@ extern "C" DLL_PUBLIC jstring Java_net_surina_soundtouch_SoundTouch_getVersionSt
// Call example SoundTouch routine
verStr = SoundTouch::getVersionString();
/// gomp_tls storage bug workaround - see comments in _init_threading() function!
_init_threading(false);
int threads = 0;
#pragma omp parallel
{
#pragma omp atomic
threads ++;
}
LOGV("JNI thread count %d", threads);
// return version as string
return env->NewStringUTF(verStr);
}
extern "C" DLL_PUBLIC jlong Java_net_surina_soundtouch_SoundTouch_newInstance(JNIEnv *env, jobject thiz)
{
return (jlong)(new SoundTouch());
}