Add live shifter to JNI

This commit is contained in:
Chris Cannam
2024-10-02 18:22:06 +01:00
parent 4353ddd78d
commit 923a196f8f
10 changed files with 410 additions and 20 deletions

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;
@@ -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,88 @@ 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.err.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.err.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.err.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) {
exerciseStretcher();
exerciseLiveShifter();
}
}