# HG changeset patch # User Chris Cannam # Date 1400259413 -3600 # Fri May 16 17:56:53 2014 +0100 # Node ID 66568cc047ad9dd706e1b8050ded8678f64b76c0 # Parent 94a9fec9843c9309f3c11bdcae86a4bd620b20b0 README, etc diff --git a/.hgsubstate b/.hgsubstate --- a/.hgsubstate +++ b/.hgsubstate @@ -1,1 +1,1 @@ -f12ee47e7f585c63a6d9939e5472fc62cf5f519d jni/rubberband +8bf18c61015d434020aa51e22c28b16758ff516e jni/rubberband diff --git a/README b/README new file mode 100644 --- /dev/null +++ b/README @@ -0,0 +1,28 @@ + +Rubber Band Android Simple Sample +================================= + +This is a very trivial example Android application that uses the +Rubber Band Library. + +This project serves as an example of how to link to, and call to, the +Rubber Band Library from Java code in an Android application. + +It is *not* an example of how to write an Android application! The +Android-specific code is absolutely not something that you should +refer to in your own work. + +To build: + + $ ndk-build + $ ant debug + $ ant debug install + +The application simply pops up a window with Play and Stop buttons and +plays a canned audio file, slowed down. The file itself is loaded (in +a raw format) from an app resource. Loading audio files and managing +the UI is outside the scope of this library. + +The example code is public domain; the Rubber Band Library licence is +documented separately. + diff --git a/jni/Android.mk b/jni/Android.mk --- a/jni/Android.mk +++ b/jni/Android.mk @@ -3,26 +3,5 @@ include $(LOCAL_PATH)/rubberband/Android.mk -include $(CLEAR_VARS) - -LOCAL_MODULE := testRubberBand -LOCAL_MODULE_FILENAME := libtestRubberBand - -TARGET_ARCH_ABI := armeabi-v7a -LOCAL_ARM_NEON := true -LOCAL_ARM_MODE := arm -LOCAL_STATIC_LIBRARIES := cpufeatures - -LOCAL_C_INCLUDES := $(LOCAL_PATH)/rubberband $(LOCAL_PATH)/rubberband/src - -LOCAL_SRC_FILES := testRubberBand.cpp - -#LOCAL_CFLAGS += -DWANT_TIMING -DFFT_MEASUREMENT - -LOCAL_SHARED_LIBRARIES = rubberband -LOCAL_LDLIBS += -llog - -include $(BUILD_SHARED_LIBRARY) - $(call import-module,android/cpufeatures) diff --git a/jni/testRubberBand.cpp b/jni/testRubberBand.cpp deleted file mode 100644 --- a/jni/testRubberBand.cpp +++ /dev/null @@ -1,206 +0,0 @@ - -#include "rubberband/RubberBandStretcher.h" - -#include -#include -#include -#include - -#include -#include "rubberband/src/dsp/FFT.h" -#include "rubberband/src/base/Profiler.h" - -#include -#define D(x...) __android_log_print(ANDROID_LOG_INFO, "TestRubberBand", x) - -extern "C" { -jstring -Java_com_breakfastquay_rubberbandexample_RubberBandExampleActivity_testRubberBand(JNIEnv*, jobject); -} - -using namespace RubberBand; - -static void printLong(std::string s) -{ - std::string bit; - int j = 0; - for (int i = 0; i < s.length(); ++i) { - if (s[i] == '\n') { - if (i > j) { - D("%s", bit.c_str()); - bit = ""; - } - j = i + 1; - } else { - bit += s[i]; - } - } - if (bit != "") D("%s", bit.c_str()); -} - -jstring -Java_com_breakfastquay_rubberbandexample_RubberBandExampleActivity_testRubberBand(JNIEnv* env, jobject thiz) -{ - char message[200]; - - uint64_t features = android_getCpuFeatures(); - D("CPU features: %d", (int)features); - if ((features & ANDROID_CPU_ARM_FEATURE_ARMv7) == 0) { - return env->NewStringUTF("Not an ARMv7 CPU\n"); - } - if ((features & ANDROID_CPU_ARM_FEATURE_NEON) == 0) { - return env->NewStringUTF("CPU lacks NEON support\n"); - } - -#ifdef FFT_MEASUREMENT - D("Running FFT tune...\n"); - std::string fftreport = FFT::tune(); - D("Report follows:\n"); - printLong(fftreport); -// return env->NewStringUTF(fftreport.c_str()); -#endif - - struct timeval begin; - gettimeofday(&begin, 0); - -#define SECONDS 30 -#define RATE 44100 -#define RATIO 1.01 -#define PITCHSHIFT 1.0 -#define SAMPLES (SECONDS * RATE) - - D("Ratio %lf, pitch shift %lf, total input samples: %d\n", RATIO, PITCHSHIFT, SAMPLES); - - float *input = new float[SAMPLES]; - - int insamples = SAMPLES; - int outsamples = insamples * RATIO; - - float irms = 0, orms = 0; - - for (int i = 0; i < insamples; ++i) { - input[i] = sinf(float(i) / 100.f); - } - - for (int i = 0; i < insamples; ++i) { -// input[i] = float(i % 100) / 50.f - 1.f; - irms += input[i] * input[i]; - } - irms = sqrtf(irms / insamples); - - RubberBandStretcher ts(RATE, 1, - RubberBandStretcher::OptionProcessRealTime | - RubberBandStretcher::OptionWindowShort, - RATIO, PITCHSHIFT); - - int outspace = outsamples + 44100; - float *output = new float[outspace]; - - if (!output) { - D("Failed to allocate space for %d samples\n", outspace); - return env->NewStringUTF("Allocation failed"); - } - - ts.setExpectedInputDuration(insamples); - - int iin = 0, iout = 0; - int bs = 1024; - int avail = 0; - - D("Total output samples: %d\n", outsamples); -/* - while (iin < SAMPLES) { - - int thisblock = SAMPLES - iin; - if (thisblock > bs) thisblock = bs; - float *iptr = input + iin; - ts.study(&iptr, thisblock, (iin + thisblock == SAMPLES)); - iin += thisblock; - - D("Studied: %d\n", iin); - } - - iin = 0; -*/ - - int printcounter = 0; - - while (iin < SAMPLES) { - - int thisblock = SAMPLES - iin; - if (thisblock > bs) thisblock = bs; - float *iptr = input + iin; - ts.process(&iptr, thisblock, (iin + thisblock == SAMPLES)); - iin += thisblock; - - if ((avail = ts.available()) > 0) { - int thisout = avail; - if (iout + thisout > outspace) thisout = outspace - iout; - float *optr = output + iout; - ts.retrieve(&optr, thisout); - for (int i = 0; i < thisout; ++i) { - orms += optr[i] * optr[i]; - } - iout += thisout; - } - - if (++printcounter == 10) { - D("Processed: %d\n", iout); - printcounter = 0; - } - } - - while ((avail = ts.available()) > 0) { - D("Available: %d\n", avail); - int thisout = avail; - if (iout + thisout > outspace) { - D("iout = %d, thisout = %d, but outspace is only %d\n", iout, thisout, outspace); - thisout = outspace - iout; - } - float *optr = output + iout; - ts.retrieve(&optr, thisout); - for (int i = 0; i < thisout; ++i) { - orms += optr[i] * optr[i]; - } - iout += thisout; - D("Processed: %d\n", iout); - } - - D("Done, processed: %d\n", iout); - orms = sqrtf(orms / iout); - - struct timeval end; - gettimeofday(&end, 0); - - int secs = end.tv_sec - begin.tv_sec; - if (end.tv_usec < begin.tv_usec) --secs; - - D(message, "iin = %d, iout = %d, in rms = %f, out rms = %f, elapsed = %d, in fps = %d, out fps = %d", - iin, iout, irms, orms, secs, iin / secs, iout / secs); - - sprintf(message, "iin = %d, iout = %d, in rms = %f, out rms = %f, elapsed = %d, in fps = %d, out fps = %d", - iin, iout, irms, orms, secs, iin / secs, iout / secs); - - D("..."); - D("0.2 sec from input:"); - for (int i = 44100 * 10; i < 44100 * 10 + (44100 / 5); i += 4) { - D("%f %f %f %f", input[i], input[i+1], input[i+2], input[i+3]); - } - - D("..."); - D("0.2 sec from output:"); - for (int i = 44100 * 10; i < 44100 * 10 + (44100 / 5); i += 4) { - D("%f %f %f %f", output[i], output[i+1], output[i+2], output[i+3]); - } - - delete[] input; - delete[] output; - -#ifdef WANT_TIMING - std::string report = Profiler::getReport(); - D("Done, report follows (%d chars):\n", report.length()); - printLong(report); -#endif - - return env->NewStringUTF(message); -} diff --git a/src/com/breakfastquay/rubberband/RubberBandStretcher.java b/src/com/breakfastquay/rubberband/RubberBandStretcher.java --- a/src/com/breakfastquay/rubberband/RubberBandStretcher.java +++ b/src/com/breakfastquay/rubberband/RubberBandStretcher.java @@ -103,7 +103,7 @@ public static final int PercussiveOptions = 0x00102000; static { - System.loadLibrary("rubberband"); + System.loadLibrary("rubberband-jni"); } };