M .build.yml +9 -1
@@ 8,11 8,18 @@ packages:
- lv2-dev
- vamp-plugin-sdk
- libboost-test-dev
- - meson
- ninja-build
+ - openjdk-21-jdk
+ - wget
sources:
- hg+https://hg.sr.ht/~breakfastquay/rubberband
tasks:
+ - install-meson: |
+ mkdir -p tmp/meson
+ cd tmp/meson
+ wget https://github.com/mesonbuild/meson/releases/download/1.5.2/meson-1.5.2.tar.gz
+ tar xvf meson-1.5.2.tar.gz
+ sudo ln -s $(pwd)/meson-1.5.2/meson.py /usr/bin/meson
- setup: |
cd rubberband
meson setup build
@@ 24,6 31,7 @@ tasks:
cd rubberband
ninja -C build
meson test -C build
+ java -Djava.library.path=build -cp build/rubberband-test.jar com.breakfastquay.rubberband.test.RubberBandTest
build/rubberband -V
ninja -C build_speex
meson test -C build_speex
M .hgignore +1 -0
@@ 31,3 31,4 @@ playlist-out/*
formant-out-*/
out*.wav
packages/
+otherbuilds/docker/Dockerfile
A => com/breakfastquay/rubberband/RubberBandLiveShifter.java +70 -0
@@ 0,0 1,70 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rubber Band Library
+ An audio time-stretching and pitch-shifting library.
+ Copyright 2007-2022 Particular Programs Ltd.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+
+ Alternatively, if you have a valid commercial licence for the
+ Rubber Band Library obtained by agreement with the copyright
+ holders, you may redistribute and/or modify it under the terms
+ described in that licence.
+
+ If you wish to distribute code using the Rubber Band Library
+ under terms other than those of the GNU General Public License,
+ you must obtain a valid commercial licence before doing so.
+*/
+
+package com.breakfastquay.rubberband;
+
+public class RubberBandLiveShifter
+{
+ public RubberBandLiveShifter(int sampleRate, int channels,
+ int options) {
+ handle = 0;
+ initialise(sampleRate, channels, options);
+ }
+
+ public native void dispose();
+
+ public native void reset();
+
+ public native void setPitchScale(double scale);
+
+ public native int getChannelCount();
+ public native double getPitchScale();
+
+ public native int getStartDelay();
+
+ public native void setFormantOption(int options);
+
+ public native int getBlockSize();
+
+ public native void shift(float[][] input, int inOffset, float[][] output, int outOffset);
+ public void shift(float[][] input, float[][] output) {
+ shift(input, 0, output, 0);
+ }
+
+ private native void initialise(int sampleRate, int channels, int options);
+ private long handle;
+
+ public static final int OptionWindowShort = 0x00000000;
+ public static final int OptionWindowMedium = 0x00100000;
+
+ public static final int OptionFormantShifted = 0x00000000;
+ public static final int OptionFormantPreserved = 0x01000000;
+
+ public static final int OptionChannelsApart = 0x00000000;
+ public static final int OptionChannelsTogether = 0x10000000;
+
+ static {
+ System.loadLibrary("rubberband-jni");
+ }
+};
+
M com/breakfastquay/rubberband/test/RubberBandTest.java +86 -5
@@ 2,14 2,14 @@
package com.breakfastquay.rubberband.test;
import com.breakfastquay.rubberband.RubberBandStretcher;
+import com.breakfastquay.rubberband.RubberBandLiveShifter;
import java.util.TreeMap;
public class RubberBandTest
{
-
- public static void main(String[] args) {
-
+ public static void exerciseStretcher() {
+
int channels = 1;
int rate = 44100;
@@ 24,7 24,7 @@ public class RubberBandTest
stretcher.setTimeRatio(1.5);
stretcher.setPitchScale(0.8);
- System.err.println
+ System.out.println
(String.format("Channel count: %d\n" +
"Time ratio: %f\n" +
"Pitch scale: %f\n" +
@@ 72,6 72,9 @@ public class RubberBandTest
i0 = 0;
+ double sqrtotal = 0.0;
+ int n = 0;
+
for (int block = 0; block < blocks; ++block) {
for (int c = 0; c < channels; ++c) {
@@ 98,13 101,91 @@ public class RubberBandTest
}
int obtained = stretcher.retrieve(buffer, 0, requested);
for (int i = 0; i < obtained; ++i) {
- System.out.println(Float.toString(buffer[0][i]));
+ sqrtotal += (double)(buffer[0][i] * buffer[0][i]);
+ ++n;
}
}
}
+
+ System.out.println
+ (String.format("in = %d, out = %d, rms = %f",
+ blocksize * blocks, n,
+ Math.sqrt(sqrtotal / (double)n)));
stretcher.dispose();
}
+
+ public static void exerciseLiveShifter() {
+
+ int channels = 1;
+ int rate = 44100;
+
+ RubberBandLiveShifter shifter = new RubberBandLiveShifter
+ (rate,
+ channels,
+ 0);
+
+ shifter.setPitchScale(0.8);
+
+ System.out.println
+ (String.format("Channel count: %d\n" +
+ "Pitch scale: %f\n" +
+ "Block size: %d\n" +
+ "Start delay: %d",
+ shifter.getChannelCount(),
+ shifter.getPitchScale(),
+ shifter.getBlockSize(),
+ shifter.getStartDelay()
+ ));
+
+ int blocksize = shifter.getBlockSize();
+ int blocks = 400;
+ double freq = 440.0;
+
+ float[][] inbuf = new float[channels][blocksize];
+ float[][] outbuf = new float[channels][blocksize];
+
+ int i0 = 0;
+
+ double sqrtotal = 0.0;
+ int n = 0;
+
+ for (int block = 0; block < blocks; ++block) {
+
+ for (int c = 0; c < channels; ++c) {
+ for (int i = 0; i < blocksize; ++i) {
+ inbuf[c][i] = (float)Math.sin
+ ((double)i0 * freq * Math.PI * 2.0 / (double)rate);
+ if (i0 % rate == 0) {
+ inbuf[c][i] = 1.f;
+ }
+ ++i0;
+ }
+ }
+
+ shifter.shift(inbuf, outbuf);
+
+ for (int i = 0; i < blocksize; ++i) {
+ sqrtotal += (double)(outbuf[0][i] * outbuf[0][i]);
+ ++n;
+ }
+ }
+
+ System.out.println
+ (String.format("in = %d, out = %d, rms = %f",
+ blocksize * blocks, n,
+ Math.sqrt(sqrtotal / (double)n)));
+
+ shifter.dispose();
+ }
+
+ public static void main(String[] args) {
+ System.out.println("Exercising RubberBandStretcher through JNI...");
+ exerciseStretcher();
+ System.out.println("Exercising RubberBandLiveShifter through JNI...");
+ exerciseLiveShifter();
+ System.out.println("Done");
+ }
}
M meson.build +1 -0
@@ 63,6 63,7 @@ jni_sources = [
java_sources = [
'com/breakfastquay/rubberband/RubberBandStretcher.java',
+ 'com/breakfastquay/rubberband/RubberBandLiveShifter.java',
]
java_test_sources = [
A => otherbuilds/docker/Dockerfile.in +39 -0
@@ 0,0 1,39 @@
+FROM ubuntu:22.04
+MAINTAINER Chris Cannam <cannam@all-day-breakfast.com>
+
+RUN apt-get update && \
+ apt-get install -y \
+ software-properties-common \
+ build-essential \
+ pkg-config \
+ libsamplerate0-dev \
+ libsndfile1-dev \
+ libfftw3-dev \
+ ladspa-sdk \
+ lv2-dev \
+ vamp-plugin-sdk \
+ libboost-test-dev \
+ mercurial \
+ ninja-build \
+ plocate
+
+RUN apt-get install -y \
+ openjdk-21-jdk
+
+WORKDIR /root
+
+ADD https://github.com/mesonbuild/meson/releases/download/1.5.2/meson-1.5.2.tar.gz .
+RUN tar xvf meson-1.5.2.tar.gz
+RUN ln -s $(pwd)/meson-1.5.2/meson.py /usr/bin/meson
+
+RUN hg clone -u [[REVISION]] https://hg.sr.ht/~breakfastquay/rubberband
+
+WORKDIR rubberband
+
+RUN meson setup build
+RUN ninja -C build
+RUN meson test -C build
+
+WORKDIR build
+
+RUN java -Djava.library.path=$(pwd) -cp rubberband-test.jar com.breakfastquay.rubberband.test.RubberBandTest
A => otherbuilds/docker/run.sh +8 -0
@@ 0,0 1,8 @@
+#!/bin/sh
+
+revision=$(hg id | sed 's/[^0-9a-z].*$//')
+
+cat Dockerfile.in | perl -p -e "s/\[\[REVISION\]\]/$revision/g" > Dockerfile
+
+sudo docker build -f Dockerfile .
+
M rubberband/RubberBandLiveShifter.h +4 -1
@@ 102,7 102,7 @@ public:
OptionFormantPreserved = 0x01000000,
OptionChannelsApart = 0x00000000,
- OptionChannelsTogether = 0x10000000,
+ OptionChannelsTogether = 0x10000000
// n.b. Options is int, so we must stop before 0x80000000
};
@@ 293,6 293,9 @@ public:
* array having enough room to store n samples where n is the value
* returned by getBlockSize().
*
+ * The input and output must be separate arrays; they cannot alias
+ * one another or overlap.
+ *
* Sample values are conventionally expected to be in the range
* -1.0f to +1.0f.
*/
M rubberband/rubberband-c.h +56 -8
@@ 48,11 48,13 @@ extern "C" {
* This is a C-linkage interface to the Rubber Band time stretcher.
*
* This is a wrapper interface: the primary interface is in C++ and is
- * defined and documented in RubberBandStretcher.h. The library
- * itself is implemented in C++, and requires C++ standard library
- * support even when using the C-linkage API.
+ * defined and documented in RubberBandStretcher.h and
+ * RubberBandLiveShifter.h. The library itself is implemented in C++,
+ * and requires C++ standard library support even when using the
+ * C-linkage API.
*
- * Please see RubberBandStretcher.h for documentation.
+ * Please see RubberBandStretcher.h and RubberBandLiveShifter.h for
+ * documentation.
*
* If you are writing to the C++ API, do not include this header.
*/
@@ 107,10 109,10 @@ struct RubberBandState_;
typedef struct RubberBandState_ *RubberBandState;
RB_EXTERN RubberBandState rubberband_new(unsigned int sampleRate,
- unsigned int channels,
- RubberBandOptions options,
- double initialTimeRatio,
- double initialPitchScale);
+ unsigned int channels,
+ RubberBandOptions options,
+ double initialTimeRatio,
+ double initialPitchScale);
RB_EXTERN void rubberband_delete(RubberBandState);
@@ 159,6 161,52 @@ RB_EXTERN void rubberband_calculate_stre
RB_EXTERN void rubberband_set_debug_level(RubberBandState, int level);
RB_EXTERN void rubberband_set_default_debug_level(int level);
+
+enum RubberBandLiveOption {
+
+ RubberBandLiveOptionWindowShort = 0x00000000,
+ RubberBandLiveOptionWindowMedium = 0x00100000,
+
+ RubberBandLiveOptionFormantShifted = 0x00000000,
+ RubberBandLiveOptionFormantPreserved = 0x01000000,
+
+ RubberBandLiveOptionChannelsApart = 0x00000000,
+ RubberBandLiveOptionChannelsTogether = 0x10000000
+};
+
+typedef int RubberBandLiveOptions;
+
+struct RubberBandLiveState_;
+typedef struct RubberBandLiveState_ *RubberBandLiveState;
+
+RB_EXTERN RubberBandLiveState rubberband_live_new(unsigned int sampleRate,
+ unsigned int channels,
+ RubberBandOptions options);
+
+RB_EXTERN void rubberband_live_delete(RubberBandLiveState);
+
+RB_EXTERN void rubberband_live_reset(RubberBandLiveState);
+
+RB_EXTERN void rubberband_live_set_pitch_scale(RubberBandLiveState, double scale);
+RB_EXTERN double rubberband_live_get_pitch_scale(const RubberBandLiveState);
+
+RB_EXTERN void rubberband_live_set_formant_scale(RubberBandLiveState, double scale);
+RB_EXTERN double rubberband_live_get_formant_scale(const RubberBandLiveState);
+
+RB_EXTERN unsigned int rubberband_live_get_start_delay(const RubberBandLiveState);
+
+RB_EXTERN void rubberband_live_set_formant_option(RubberBandLiveState, RubberBandOptions options);
+
+RB_EXTERN unsigned int rubberband_live_get_block_size(RubberBandLiveState);
+
+RB_EXTERN void rubberband_live_shift(RubberBandLiveState, const float *const *input, float *const *output);
+
+RB_EXTERN unsigned int rubberband_live_get_channel_count(const RubberBandLiveState);
+
+RB_EXTERN void rubberband_live_set_debug_level(RubberBandLiveState, int level);
+RB_EXTERN void rubberband_live_set_default_debug_level(int level);
+
+
#ifdef __cplusplus
}
#endif
M src/jni/RubberBandStretcherJNI.cpp +207 -15
@@ 22,6 22,7 @@
*/
#include "rubberband/RubberBandStretcher.h"
+#include "rubberband/RubberBandLiveShifter.h"
#include "common/Allocators.h"
@@ 231,6 232,86 @@ JNIEXPORT jint JNICALL Java_com_breakfas
JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandStretcher_initialise
(JNIEnv *, jobject, jint, jint, jint, jdouble, jdouble);
+/*
+ * Class: com_breakfastquay_rubberband_RubberBandLiveShifter
+ * Method: dispose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandLiveShifter_dispose
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_breakfastquay_rubberband_RubberBandLiveShifter
+ * Method: reset
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandLiveShifter_reset
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_breakfastquay_rubberband_RubberBandLiveShifter
+ * Method: setPitchScale
+ * Signature: (D)V
+ */
+JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandLiveShifter_setPitchScale
+ (JNIEnv *, jobject, jdouble);
+
+/*
+ * Class: com_breakfastquay_rubberband_RubberBandLiveShifter
+ * Method: getChannelCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_breakfastquay_rubberband_RubberBandLiveShifter_getChannelCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_breakfastquay_rubberband_RubberBandLiveShifter
+ * Method: getPitchScale
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_breakfastquay_rubberband_RubberBandLiveShifter_getPitchScale
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_breakfastquay_rubberband_RubberBandLiveShifter
+ * Method: getStartDelay
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_breakfastquay_rubberband_RubberBandLiveShifter_getStartDelay
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_breakfastquay_rubberband_RubberBandLiveShifter
+ * Method: setFormantOption
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandLiveShifter_setFormantOption
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_breakfastquay_rubberband_RubberBandLiveShifter
+ * Method: getBlockSize
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_breakfastquay_rubberband_RubberBandLiveShifter_getBlockSize
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_breakfastquay_rubberband_RubberBandLiveShifter
+ * Method: shift
+ * Signature: ([[FI[[FI)V
+ */
+JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandLiveShifter_shift
+(JNIEnv *, jobject, jobjectArray, jint, jobjectArray, jint);
+
+/*
+ * Class: com_breakfastquay_rubberband_RubberBandLiveShifter
+ * Method: initialise
+ * Signature: (III)V
+ */
+JNIEXPORT void JNICALL Java_com_breakfastquay_rubberband_RubberBandLiveShifter_initialise
+ (JNIEnv *, jobject, jint, jint, jint);
+
}
RubberBandStretcher *
@@ 390,45 471,48 @@ Java_com_breakfastquay_rubberband_Rubber
}
JNIEXPORT void JNICALL
-Java_com_breakfastquay_rubberband_RubberBandStretcher_study(JNIEnv *env, jobject obj, jobjectArray data, jint offset, jint n, jboolean final)
+Java_com_breakfastquay_rubberband_RubberBandStretcher_study(JNIEnv *env, jobject obj, jobjectArray input, jint offset, jint n, jboolean final)
{
- int channels = env->GetArrayLength(data);
+ int channels = env->GetArrayLength(input);
float **arr = allocate<float *>(channels);
- float **input = allocate<float *>(channels);
+ float **inbuf = allocate<float *>(channels);
for (int c = 0; c < channels; ++c) {
- jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(data, c);
+ jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(input, c);
arr[c] = env->GetFloatArrayElements(cdata, 0);
- input[c] = arr[c] + offset;
+ inbuf[c] = arr[c] + offset;
}
- getStretcher(env, obj)->study(input, n, final);
+ getStretcher(env, obj)->study(inbuf, n, final);
for (int c = 0; c < channels; ++c) {
- jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(data, c);
+ jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(input, c);
env->ReleaseFloatArrayElements(cdata, arr[c], 0);
}
+
+ deallocate(inbuf);
+ deallocate(arr);
}
JNIEXPORT void JNICALL
-Java_com_breakfastquay_rubberband_RubberBandStretcher_process(JNIEnv *env, jobject obj, jobjectArray data, jint offset, jint n, jboolean final)
+Java_com_breakfastquay_rubberband_RubberBandStretcher_process(JNIEnv *env, jobject obj, jobjectArray input, jint offset, jint n, jboolean final)
{
- int channels = env->GetArrayLength(data);
+ int channels = env->GetArrayLength(input);
float **arr = allocate<float *>(channels);
- float **input = allocate<float *>(channels);
+ float **inbuf = allocate<float *>(channels);
for (int c = 0; c < channels; ++c) {
- jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(data, c);
+ jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(input, c);
arr[c] = env->GetFloatArrayElements(cdata, 0);
- input[c] = arr[c] + offset;
+ inbuf[c] = arr[c] + offset;
}
- getStretcher(env, obj)->process(input, n, final);
+ getStretcher(env, obj)->process(inbuf, n, final);
for (int c = 0; c < channels; ++c) {
- jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(data, c);
+ jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(input, c);
env->ReleaseFloatArrayElements(cdata, arr[c], 0);
}
- deallocate(input);
+ deallocate(inbuf);
deallocate(arr);
}
@@ 456,3 540,111 @@ Java_com_breakfastquay_rubberband_Rubber
return retrieved;
}
+RubberBandLiveShifter *
+getLiveShifter(JNIEnv *env, jobject obj)
+{
+ jclass c = env->GetObjectClass(obj);
+ jfieldID fid = env->GetFieldID(c, "handle", "J");
+ jlong handle = env->GetLongField(obj, fid);
+ return (RubberBandLiveShifter *)handle;
+}
+
+void
+setLiveShifter(JNIEnv *env, jobject obj, RubberBandLiveShifter *stretcher)
+{
+ jclass c = env->GetObjectClass(obj);
+ jfieldID fid = env->GetFieldID(c, "handle", "J");
+ jlong handle = (jlong)stretcher;
+ env->SetLongField(obj, fid, handle);
+}
+
+JNIEXPORT void JNICALL
+Java_com_breakfastquay_rubberband_RubberBandLiveShifter_initialise(JNIEnv *env, jobject obj, jint sampleRate, jint channels, jint options)
+{
+ setLiveShifter(env, obj, new RubberBandLiveShifter
+ (sampleRate, channels, options));
+}
+
+JNIEXPORT void JNICALL
+Java_com_breakfastquay_rubberband_RubberBandLiveShifter_dispose(JNIEnv *env, jobject obj)
+{
+ delete getLiveShifter(env, obj);
+ setLiveShifter(env, obj, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_com_breakfastquay_rubberband_RubberBandLiveShifter_reset(JNIEnv *env, jobject obj)
+{
+ getLiveShifter(env, obj)->reset();
+}
+
+JNIEXPORT void JNICALL
+Java_com_breakfastquay_rubberband_RubberBandLiveShifter_setPitchScale(JNIEnv *env, jobject obj, jdouble scale)
+{
+ getLiveShifter(env, obj)->setPitchScale(scale);
+}
+
+JNIEXPORT jint JNICALL
+Java_com_breakfastquay_rubberband_RubberBandLiveShifter_getChannelCount(JNIEnv *env, jobject obj)
+{
+ return getLiveShifter(env, obj)->getChannelCount();
+}
+
+JNIEXPORT jdouble JNICALL
+Java_com_breakfastquay_rubberband_RubberBandLiveShifter_getPitchScale(JNIEnv *env, jobject obj)
+{
+ return getLiveShifter(env, obj)->getPitchScale();
+}
+
+JNIEXPORT jint JNICALL
+Java_com_breakfastquay_rubberband_RubberBandLiveShifter_getStartDelay(JNIEnv *env, jobject obj)
+{
+ return getLiveShifter(env, obj)->getStartDelay();
+}
+
+JNIEXPORT void JNICALL
+Java_com_breakfastquay_rubberband_RubberBandLiveShifter_setFormantOption(JNIEnv *env, jobject obj, jint options)
+{
+ getLiveShifter(env, obj)->setFormantOption(options);
+}
+
+JNIEXPORT jint JNICALL
+Java_com_breakfastquay_rubberband_RubberBandLiveShifter_getBlockSize(JNIEnv *env, jobject obj)
+{
+ return getLiveShifter(env, obj)->getBlockSize();
+}
+
+JNIEXPORT void JNICALL
+Java_com_breakfastquay_rubberband_RubberBandLiveShifter_shift(JNIEnv *env, jobject obj, jobjectArray input, jint inOffset, jobjectArray output, jint outOffset)
+{
+ int channels = env->GetArrayLength(input);
+ float **inarr = allocate<float *>(channels);
+ float **inbuf = allocate<float *>(channels);
+ float **outarr = allocate<float *>(channels);
+ float **outbuf = allocate<float *>(channels);
+
+ for (int c = 0; c < channels; ++c) {
+ jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(input, c);
+ inarr[c] = env->GetFloatArrayElements(cdata, 0);
+ inbuf[c] = inarr[c] + inOffset;
+ cdata = (jfloatArray)env->GetObjectArrayElement(output, c);
+ outarr[c] = env->GetFloatArrayElements(cdata, 0);
+ outbuf[c] = outarr[c] + outOffset;
+ }
+
+ getLiveShifter(env, obj)->shift(inbuf, outbuf);
+
+ for (int c = 0; c < channels; ++c) {
+ jfloatArray cdata = (jfloatArray)env->GetObjectArrayElement(input, c);
+ env->ReleaseFloatArrayElements(cdata, inarr[c], 0);
+ cdata = (jfloatArray)env->GetObjectArrayElement(output, c);
+ env->ReleaseFloatArrayElements(cdata, outarr[c], 0);
+ }
+
+ deallocate(inbuf);
+ deallocate(inarr);
+ deallocate(outbuf);
+ deallocate(outarr);
+}
+
+
M src/rubberband-c.cpp +81 -0
@@ 23,6 23,7 @@
#include "../rubberband/rubberband-c.h"
#include "../rubberband/RubberBandStretcher.h"
+#include "../rubberband/RubberBandLiveShifter.h"
struct RubberBandState_
{
@@ 197,3 198,83 @@ void rubberband_set_default_debug_level(
RubberBand::RubberBandStretcher::setDefaultDebugLevel(level);
}
+struct RubberBandLiveState_
+{
+ RubberBand::RubberBandLiveShifter *m_s;
+};
+
+RubberBandLiveState rubberband_live_new(unsigned int sampleRate,
+ unsigned int channels,
+ RubberBandOptions options)
+{
+ RubberBandLiveState_ *state = new RubberBandLiveState_();
+ state->m_s = new RubberBand::RubberBandLiveShifter
+ (sampleRate, channels, options);
+ return state;
+}
+
+void rubberband_live_delete(RubberBandLiveState state)
+{
+ delete state->m_s;
+ delete state;
+}
+
+void rubberband_live_reset(RubberBandLiveState state)
+{
+ state->m_s->reset();
+}
+
+void rubberband_live_set_pitch_scale(RubberBandLiveState state, double scale)
+{
+ state->m_s->setPitchScale(scale);
+}
+
+double rubberband_live_get_pitch_scale(const RubberBandLiveState state)
+{
+ return state->m_s->getPitchScale();
+}
+
+void rubberband_live_set_formant_scale(RubberBandLiveState state, double scale)
+{
+ state->m_s->setFormantScale(scale);
+}
+
+double rubberband_live_get_formant_scale(const RubberBandLiveState state)
+{
+ return state->m_s->getFormantScale();
+}
+
+unsigned int rubberband_live_get_start_delay(const RubberBandLiveState state)
+{
+ return (unsigned int)state->m_s->getStartDelay();
+}
+
+void rubberband_live_set_formant_option(RubberBandLiveState state, RubberBandOptions options)
+{
+ state->m_s->setFormantOption(options);
+}
+
+unsigned int rubberband_live_get_block_size(RubberBandLiveState state)
+{
+ return (unsigned int)state->m_s->getBlockSize();
+}
+
+void rubberband_live_shift(RubberBandLiveState state, const float *const *input, float *const *output)
+{
+ state->m_s->shift(input, output);
+}
+
+unsigned int rubberband_live_get_channel_count(const RubberBandLiveState state)
+{
+ return (unsigned int)state->m_s->getChannelCount();
+}
+
+void rubberband_live_set_debug_level(RubberBandLiveState state, int level)
+{
+ state->m_s->setDebugLevel(level);
+}
+
+void rubberband_live_set_default_debug_level(int level)
+{
+ RubberBand::RubberBandStretcher::setDefaultDebugLevel(level);
+}