Merge from branch rblive

This commit is contained in:
Chris Cannam
2024-10-03 09:33:24 +01:00
11 changed files with 562 additions and 30 deletions

View File

@@ -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

View File

@@ -31,3 +31,4 @@ playlist-out/*
formant-out-*/
out*.wav
packages/
otherbuilds/docker/Dockerfile

View File

@@ -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");
}
};

View File

@@ -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");
}
}

View File

@@ -63,6 +63,7 @@ jni_sources = [
java_sources = [
'com/breakfastquay/rubberband/RubberBandStretcher.java',
'com/breakfastquay/rubberband/RubberBandLiveShifter.java',
]
java_test_sources = [

View File

@@ -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

8
otherbuilds/docker/run.sh Executable file
View File

@@ -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 .

View File

@@ -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.
*/

View File

@@ -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_stretch(RubberBandState);
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

View File

@@ -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_breakfastquay_rubberband_RubberBandStretcher_ret
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_RubberBandStretcher_setKeyFrameMap(JNIEnv *env
}
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_RubberBandStretcher_retrieve(JNIEnv *env, jobj
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);
}

View File

@@ -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(int 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);
}