diff --git a/com/breakfastquay/rubberband/RubberBandStretcher.java b/com/breakfastquay/rubberband/RubberBandStretcher.java index 8469d621..036516d7 100644 --- a/com/breakfastquay/rubberband/RubberBandStretcher.java +++ b/com/breakfastquay/rubberband/RubberBandStretcher.java @@ -23,6 +23,9 @@ License, or (at your option) any later version. See the file package com.breakfastquay.rubberband; +import java.util.Map; +import java.util.Set; + public class RubberBandStretcher { public RubberBandStretcher(int sampleRate, int channels, @@ -45,6 +48,8 @@ public RubberBandStretcher(int sampleRate, int channels, public native double getTimeRatio(); public native double getPitchScale(); + public native int getPreferredStartPad(); + public native int getStartDelay(); public native int getLatency(); public native void setTransientsOption(int options); @@ -54,11 +59,25 @@ public RubberBandStretcher(int sampleRate, int channels, public native void setPitchOption(int options); public native void setExpectedInputDuration(long samples); + public native int getProcessSizeLimit(); public native void setMaxProcessSize(int samples); public native int getSamplesRequired(); - //!!! todo: setKeyFrameMap + public native void setKeyFrameMap(long[] from, long[] to); + public void setKeyFrameMap(Map m) { + Set keys = m.keySet(); + int n = keys.size(); + long[] from = new long[n]; + long[] to = new long[n]; + int i = 0; + for (Long k : keys) { + from[i] = k.longValue(); + to[i] = m.get(k).longValue(); + ++i; + } + setKeyFrameMap(from, to); + } public native void study(float[][] input, int offset, int n, boolean finalBlock); public void study(float[][] input, boolean finalBlock) { @@ -120,6 +139,9 @@ private native void initialise(int sampleRate, int channels, int options, public static final int OptionChannelsApart = 0x00000000; public static final int OptionChannelsTogether = 0x10000000; + public static final int OptionEngineFaster = 0x00000000; + public static final int OptionEngineFiner = 0x20000000; + public static final int DefaultOptions = 0x00000000; public static final int PercussiveOptions = 0x00102000; diff --git a/com/breakfastquay/rubberband/test/RubberBandTest.java b/com/breakfastquay/rubberband/test/RubberBandTest.java new file mode 100644 index 00000000..578f5ecc --- /dev/null +++ b/com/breakfastquay/rubberband/test/RubberBandTest.java @@ -0,0 +1,110 @@ + +package com.breakfastquay.rubberband.test; + +import com.breakfastquay.rubberband.RubberBandStretcher; + +import java.util.TreeMap; + +public class RubberBandTest +{ + + public static void main(String[] args) { + + int channels = 1; + int rate = 44100; + + RubberBandStretcher stretcher = new RubberBandStretcher + (rate, + channels, + RubberBandStretcher.OptionEngineFiner + + RubberBandStretcher.OptionProcessOffline, + 1.0, + 1.0); + + stretcher.setTimeRatio(1.5); + stretcher.setPitchScale(0.8); + + System.err.println + (String.format("Channel count: %d\n" + + "Time ratio: %f\n" + + "Pitch scale: %f\n" + + "Preferred start pad: %d\n" + + "Start delay: %d\n" + + "Process size limit: %d", + stretcher.getChannelCount(), + stretcher.getTimeRatio(), + stretcher.getPitchScale(), + stretcher.getPreferredStartPad(), + stretcher.getStartDelay(), + stretcher.getProcessSizeLimit() + )); + + int blocksize = 1024; + int blocks = 400; + double freq = 440.0; + + stretcher.setMaxProcessSize(blocksize); + + TreeMap keyFrameMap = new TreeMap(); + keyFrameMap.put((long)(3 * rate), (long)(4 * rate)); + keyFrameMap.put((long)(5 * rate), (long)(5 * rate)); + stretcher.setKeyFrameMap(keyFrameMap); + + float[][] buffer = new float[channels][blocksize]; + + int i0 = 0; + + for (int block = 0; block < blocks; ++block) { + + for (int c = 0; c < channels; ++c) { + for (int i = 0; i < blocksize; ++i) { + buffer[c][i] = (float)Math.sin + ((double)i0 * freq * Math.PI * 2.0 / (double)rate); + if (i0 % rate == 0) { + buffer[c][i] = 1.f; + } + ++i0; + } + } + + stretcher.study(buffer, block + 1 == blocks); + } + + i0 = 0; + + for (int block = 0; block < blocks; ++block) { + + for (int c = 0; c < channels; ++c) { + for (int i = 0; i < blocksize; ++i) { + buffer[c][i] = (float)Math.sin + ((double)i0 * freq * Math.PI * 2.0 / (double)rate); + if (i0 % rate == 0) { + buffer[c][i] = 1.f; + } + ++i0; + } + } + + stretcher.process(buffer, block + 1 == blocks); + + while (true) { + int available = stretcher.available(); + if (available <= 0) { + break; + } + int requested = available; + if (requested > blocksize) { + requested = blocksize; + } + int obtained = stretcher.retrieve(buffer, 0, requested); + for (int i = 0; i < obtained; ++i) { + System.out.println(Float.toString(buffer[0][i])); + } + } + } + + stretcher.dispose(); + } + +} + diff --git a/meson.build b/meson.build index 050dbd56..4f4408f9 100644 --- a/meson.build +++ b/meson.build @@ -65,6 +65,10 @@ java_sources = [ 'com/breakfastquay/rubberband/RubberBandStretcher.java', ] +java_test_sources = [ + 'com/breakfastquay/rubberband/test/RubberBandTest.java', +] + program_sources = [ 'main/main.cpp', ] @@ -655,7 +659,8 @@ if have_jni # NB the JNI library is not versioned install: true, ) - jar('rubberband', 'com/breakfastquay/rubberband/RubberBandStretcher.java') + jar('rubberband', java_sources) + jar('rubberband-test', java_test_sources) else target_summary += { 'JNI library': false } if not have_java diff --git a/rubberband/RubberBandStretcher.h b/rubberband/RubberBandStretcher.h index 6b883a87..79234f4f 100644 --- a/rubberband/RubberBandStretcher.h +++ b/rubberband/RubberBandStretcher.h @@ -30,7 +30,9 @@ #undef RUBBERBAND_DLLEXPORT #ifdef _MSC_VER +#ifndef RUBBERBAND_STATIC #define RUBBERBAND_DLLEXPORT __declspec(dllexport) +#endif #else #define RUBBERBAND_DLLEXPORT #endif diff --git a/rubberband/rubberband-c.h b/rubberband/rubberband-c.h index 73d1216b..39674824 100644 --- a/rubberband/rubberband-c.h +++ b/rubberband/rubberband-c.h @@ -35,7 +35,9 @@ extern "C" { #undef RB_EXTERN #ifdef _MSC_VER +#ifndef RUBBERBAND_STATIC #define RB_EXTERN extern __declspec(dllexport) +#endif #else #define RB_EXTERN extern #endif diff --git a/src/common/Resampler.cpp b/src/common/Resampler.cpp index 1b213c53..4149c6a5 100644 --- a/src/common/Resampler.cpp +++ b/src/common/Resampler.cpp @@ -192,7 +192,7 @@ D_IPP::D_IPP(Resampler::Quality /* quality */, // elements with indices greater than m_time + length for the // right filter wing for the last element. - m_history = int(m_window * 0.5 * max(1.0, 1.0 / m_factor)) + 1; + m_history = int(m_window * 0.5 * std::max(1.0, 1.0 / m_factor)) + 1; m_state = new IppsResamplingPolyphase_32f *[m_channels]; @@ -305,7 +305,7 @@ D_IPP::resample(float *const BQ_R__ *const BQ_R__ out, { if (ratio > m_factor) { m_factor = ratio; - m_history = int(m_window * 0.5 * max(1.0, 1.0 / m_factor)) + 1; + m_history = int(m_window * 0.5 * std::max(1.0, 1.0 / m_factor)) + 1; } if (m_debugLevel > 2) { @@ -348,7 +348,7 @@ D_IPP::resampleInterleaved(float *const BQ_R__ out, { if (ratio > m_factor) { m_factor = ratio; - m_history = int(m_window * 0.5 * max(1.0, 1.0 / m_factor)) + 1; + m_history = int(m_window * 0.5 * std::max(1.0, 1.0 / m_factor)) + 1; } if (m_debugLevel > 2) { diff --git a/src/common/sysutils.cpp b/src/common/sysutils.cpp index 49e29146..c5779b6b 100644 --- a/src/common/sysutils.cpp +++ b/src/common/sysutils.cpp @@ -152,7 +152,7 @@ system_is_multiprocessor() #ifdef _WIN32 -void gettimeofday(struct timeval *tv, void *tz) +void gettimeofday(struct timeval *tv, void * /* tz */) { union { long long ns100; diff --git a/src/common/sysutils.h b/src/common/sysutils.h index 88b905e4..53a771e6 100644 --- a/src/common/sysutils.h +++ b/src/common/sysutils.h @@ -45,6 +45,19 @@ # define R__ #endif +#ifndef RUBBERBAND_ENABLE_WARNINGS +#if defined(_MSC_VER) +#pragma warning(disable:4127; disable:4244; disable:4267) +#elif defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wconversion" +#elif defined(__clang__) +#pragma clang diagnostic ignored "-Wsign-conversion" +#pragma clang diagnostic ignored "-Wfloat-conversion" +#pragma clang diagnostic ignored "-Wimplicit-float-conversion" +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#endif +#endif + #ifdef __clang__ # define RTENTRY__ __attribute__((annotate("realtime"))) #else diff --git a/src/ext/getopt/getopt.c b/src/ext/getopt/getopt.c index ce9abb3c..1ca7d773 100644 --- a/src/ext/getopt/getopt.c +++ b/src/ext/getopt/getopt.c @@ -35,6 +35,10 @@ #include #include +#ifdef _MSC_VER +#pragma warning (disable: 4131; disable: 4706) +#endif + int opterr = 1, /* if error message should be printed */ optind = 1, /* index into parent argv vector */ optopt, /* character checked for validity */ diff --git a/src/ext/getopt/getopt_long.c b/src/ext/getopt/getopt_long.c index 1f92449a..f5cd2443 100644 --- a/src/ext/getopt/getopt_long.c +++ b/src/ext/getopt/getopt_long.c @@ -54,6 +54,10 @@ #include #include +#ifdef _MSC_VER +#pragma warning (disable: 4131; disable: 4996) +#endif + GETOPT_API extern char opterrmsg[128]; char opterrmsg[128]; /* last error message is stored here */ diff --git a/src/faster/StretcherChannelData.cpp b/src/faster/StretcherChannelData.cpp index 640ddb4a..8cbe4231 100644 --- a/src/faster/StretcherChannelData.cpp +++ b/src/faster/StretcherChannelData.cpp @@ -89,8 +89,7 @@ R2Stretcher::ChannelData::construct(const std::set &sizes, unityResetLow = 16000.f; - for (std::set::const_iterator i = sizes.begin(); - i != sizes.end(); ++i) { + for (i = sizes.begin(); i != sizes.end(); ++i) { ffts[*i] = new FFT(*i); if (sizeof(process_t) == sizeof(double)) { ffts[*i]->initDouble(); diff --git a/src/finer/R3Stretcher.cpp b/src/finer/R3Stretcher.cpp index ea1b2c83..81524b95 100644 --- a/src/finer/R3Stretcher.cpp +++ b/src/finer/R3Stretcher.cpp @@ -1006,7 +1006,7 @@ R3Stretcher::consume(bool final) while (true) { - Profiler profiler("R3Stretcher::consume/loop"); + Profiler profiler2("R3Stretcher::consume/loop"); int readSpace = cd0->inbuf->getReadSpace(); m_log.log(2, "consume: read space", readSpace); diff --git a/src/jni/RubberBandStretcherJNI.cpp b/src/jni/RubberBandStretcherJNI.cpp index e1e6cf95..9cac5fb5 100644 --- a/src/jni/RubberBandStretcherJNI.cpp +++ b/src/jni/RubberBandStretcherJNI.cpp @@ -87,6 +87,22 @@ JNIEXPORT jdouble JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_ JNIEXPORT jdouble JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_getPitchScale (JNIEnv *, jobject); +/* + * Class: com_breakfastquay_rubberband_RubberBandStretcher + * Method: getPreferredStartPad + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_getPreferredStartPad + (JNIEnv *, jobject); + +/* + * Class: com_breakfastquay_rubberband_RubberBandStretcher + * Method: getStartDelay + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_getStartDelay + (JNIEnv *, jobject); + /* * Class: com_breakfastquay_rubberband_RubberBandStretcher * Method: getLatency @@ -151,6 +167,14 @@ JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_set JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_setMaxProcessSize (JNIEnv *, jobject, jint); +/* + * Class: com_breakfastquay_rubberband_RubberBandStretcher + * Method: getProcessSizeLimit + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_getProcessSizeLimit + (JNIEnv *, jobject); + /* * Class: com_breakfastquay_rubberband_RubberBandStretcher * Method: getSamplesRequired @@ -159,6 +183,14 @@ JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_set JNIEXPORT jint JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_getSamplesRequired (JNIEnv *, jobject); +/* + * Class: com_breakfastquay_rubberband_RubberBandStretcher + * Method: setKeyFrameMap + * Signature: ([J[J)V + */ +JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_setKeyFrameMap + (JNIEnv *, jobject, jlongArray, jlongArray); + /* * Class: com_breakfastquay_rubberband_RubberBandStretcher * Method: study @@ -269,6 +301,18 @@ Java_com_breakfastquay_rubberband_RubberBandStretcher_getPitchScale(JNIEnv *env, return getStretcher(env, obj)->getPitchScale(); } +JNIEXPORT jint JNICALL +Java_com_breakfastquay_rubberband_RubberBandStretcher_getPreferredStartPad(JNIEnv *env, jobject obj) +{ + return getStretcher(env, obj)->getPreferredStartPad(); +} + +JNIEXPORT jint JNICALL +Java_com_breakfastquay_rubberband_RubberBandStretcher_getStartDelay(JNIEnv *env, jobject obj) +{ + return getStretcher(env, obj)->getStartDelay(); +} + JNIEXPORT jint JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_getLatency(JNIEnv *env, jobject obj) { @@ -317,12 +361,34 @@ Java_com_breakfastquay_rubberband_RubberBandStretcher_setMaxProcessSize(JNIEnv * getStretcher(env, obj)->setMaxProcessSize(size); } +JNIEXPORT jint JNICALL +Java_com_breakfastquay_rubberband_RubberBandStretcher_getProcessSizeLimit(JNIEnv *env, jobject obj) +{ + return getStretcher(env, obj)->getProcessSizeLimit(); +} + JNIEXPORT jint JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_getSamplesRequired(JNIEnv *env, jobject obj) { return getStretcher(env, obj)->getSamplesRequired(); } +JNIEXPORT void JNICALL +Java_com_breakfastquay_rubberband_RubberBandStretcher_setKeyFrameMap(JNIEnv *env, jobject obj, jlongArray from, jlongArray to) +{ + std::map m; + int flen = env->GetArrayLength(from); + int tlen = env->GetArrayLength(to); + jlong *farr = env->GetLongArrayElements(from, 0); + jlong *tarr = env->GetLongArrayElements(to, 0); + for (int i = 0; i < flen && i < tlen; ++i) { + m[farr[i]] = tarr[i]; + } + env->ReleaseLongArrayElements(from, farr, 0); + env->ReleaseLongArrayElements(to, tarr, 0); + getStretcher(env, obj)->setKeyFrameMap(m); +} + JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_study(JNIEnv *env, jobject obj, jobjectArray data, jint offset, jint n, jboolean final) { diff --git a/src/rubberband-c.cpp b/src/rubberband-c.cpp index e7fd1543..c00ad6c2 100644 --- a/src/rubberband-c.cpp +++ b/src/rubberband-c.cpp @@ -90,17 +90,17 @@ double rubberband_get_formant_scale(const RubberBandState state) unsigned int rubberband_get_preferred_start_pad(const RubberBandState state) { - return state->m_s->getPreferredStartPad(); + return (unsigned int)state->m_s->getPreferredStartPad(); } unsigned int rubberband_get_start_delay(const RubberBandState state) { - return state->m_s->getStartDelay(); + return (unsigned int)state->m_s->getStartDelay(); } unsigned int rubberband_get_latency(const RubberBandState state) { - return state->m_s->getLatency(); + return (unsigned int)state->m_s->getLatency(); } void rubberband_set_transients_option(RubberBandState state, RubberBandOptions options) @@ -135,7 +135,7 @@ void rubberband_set_expected_input_duration(RubberBandState state, unsigned int unsigned int rubberband_get_samples_required(const RubberBandState state) { - return state->m_s->getSamplesRequired(); + return (unsigned int)state->m_s->getSamplesRequired(); } void rubberband_set_max_process_size(RubberBandState state, unsigned int samples) @@ -145,7 +145,7 @@ void rubberband_set_max_process_size(RubberBandState state, unsigned int samples unsigned int rubberband_get_process_size_limit(RubberBandState state) { - return state->m_s->getProcessSizeLimit(); + return (unsigned int)state->m_s->getProcessSizeLimit(); } void rubberband_set_key_frame_map(RubberBandState state, unsigned int keyframecount, unsigned int *from, unsigned int *to) @@ -174,12 +174,12 @@ int rubberband_available(const RubberBandState state) unsigned int rubberband_retrieve(const RubberBandState state, float *const *output, unsigned int samples) { - return state->m_s->retrieve(output, samples); + return (unsigned int)state->m_s->retrieve(output, samples); } unsigned int rubberband_get_channel_count(const RubberBandState state) { - return state->m_s->getChannelCount(); + return (unsigned int)state->m_s->getChannelCount(); } void rubberband_calculate_stretch(RubberBandState state)