Skip to content

Commit

Permalink
Merge from branch rblive
Browse files Browse the repository at this point in the history
  • Loading branch information
cannam committed Oct 3, 2024
2 parents e55f7aa + 28fa720 commit 48e08a5
Show file tree
Hide file tree
Showing 11 changed files with 562 additions and 30 deletions.
10 changes: 9 additions & 1 deletion .build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions .hgignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ playlist-out/*
formant-out-*/
out*.wav
packages/
otherbuilds/docker/Dockerfile
70 changes: 70 additions & 0 deletions com/breakfastquay/rubberband/RubberBandLiveShifter.java
Original file line number Diff line number Diff line change
@@ -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");
}
};

91 changes: 86 additions & 5 deletions com/breakfastquay/rubberband/test/RubberBandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -24,7 +24,7 @@ public static void main(String[] args) {
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" +
Expand Down Expand Up @@ -72,6 +72,9 @@ public static void main(String[] args) {

i0 = 0;

double sqrtotal = 0.0;
int n = 0;

for (int block = 0; block < blocks; ++block) {

for (int c = 0; c < channels; ++c) {
Expand All @@ -98,13 +101,91 @@ public static void main(String[] args) {
}
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");
}

}

1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ jni_sources = [

java_sources = [
'com/breakfastquay/rubberband/RubberBandStretcher.java',
'com/breakfastquay/rubberband/RubberBandLiveShifter.java',
]

java_test_sources = [
Expand Down
39 changes: 39 additions & 0 deletions otherbuilds/docker/Dockerfile.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
FROM ubuntu:22.04
MAINTAINER Chris Cannam <[email protected]>

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 changes: 8 additions & 0 deletions otherbuilds/docker/run.sh
Original file line number Diff line number Diff line change
@@ -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 .

5 changes: 4 additions & 1 deletion rubberband/RubberBandLiveShifter.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ RubberBandLiveShifter
OptionFormantPreserved = 0x01000000,

OptionChannelsApart = 0x00000000,
OptionChannelsTogether = 0x10000000,
OptionChannelsTogether = 0x10000000

// n.b. Options is int, so we must stop before 0x80000000
};
Expand Down Expand Up @@ -293,6 +293,9 @@ RubberBandLiveShifter
* 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.
*/
Expand Down
64 changes: 56 additions & 8 deletions rubberband/rubberband-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 48e08a5

Please sign in to comment.