diff --git a/Makefile b/Makefile index 62e32b68..6438ad1b 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ ifeq ($(ARCH), lin) LDFLAGS += -rdynamic \ -lpthread -lGL -ldl \ $(shell pkg-config --libs gtk+-2.0) \ - -Ldep/lib -lGLEW -lglfw -ljansson -lsamplerate -lcurl -lzip -lrtaudio -lrtmidi + -Ldep/lib -lGLEW -lglfw -ljansson -lspeexdsp -lcurl -lzip -lrtaudio -lrtmidi TARGET = Rack endif @@ -23,7 +23,7 @@ ifeq ($(ARCH), mac) CXXFLAGS += -DAPPLE -stdlib=libc++ LDFLAGS += -stdlib=libc++ -lpthread -ldl \ -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo \ - -Ldep/lib -lGLEW -lglfw -ljansson -lsamplerate -lcurl -lzip -lrtaudio -lrtmidi + -Ldep/lib -lGLEW -lglfw -ljansson -lspeexdsp -lcurl -lzip -lrtaudio -lrtmidi TARGET = Rack BUNDLE = dist/$(TARGET).app endif @@ -34,7 +34,7 @@ ifeq ($(ARCH), win) -Wl,--export-all-symbols,--out-implib,libRack.a -mwindows \ -lgdi32 -lopengl32 -lcomdlg32 -lole32 \ -Ldep/lib -lglew32 -lglfw3dll -lcurl -lzip -lrtaudio -lrtmidi \ - -Wl,-Bstatic -ljansson -lsamplerate + -Wl,-Bstatic -ljansson -lspeexdsp TARGET = Rack.exe OBJECTS = Rack.res endif @@ -109,7 +109,7 @@ ifeq ($(ARCH), mac) cp dep/lib/libGLEW.2.1.0.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/libglfw.3.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/libjansson.4.dylib $(BUNDLE)/Contents/MacOS/ - cp dep/lib/libsamplerate.0.dylib $(BUNDLE)/Contents/MacOS/ + cp dep/lib/libspeexdsp.1.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/libzip.5.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/librtmidi.4.dylib $(BUNDLE)/Contents/MacOS/ @@ -118,7 +118,7 @@ ifeq ($(ARCH), mac) install_name_tool -change /usr/local/lib/libGLEW.2.1.0.dylib @executable_path/libGLEW.2.1.0.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change lib/libglfw.3.dylib @executable_path/libglfw.3.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change $(PWD)/dep/lib/libjansson.4.dylib @executable_path/libjansson.4.dylib $(BUNDLE)/Contents/MacOS/Rack - install_name_tool -change $(PWD)/dep/lib/libsamplerate.0.dylib @executable_path/libsamplerate.0.dylib $(BUNDLE)/Contents/MacOS/Rack + install_name_tool -change $(PWD)/dep/lib/libspeexdsp.1.dylib @executable_path/libspeexdsp.1.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change $(PWD)/dep/lib/libcurl.4.dylib @executable_path/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change $(PWD)/dep/lib/libzip.5.dylib @executable_path/libzip.5.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change $(PWD)/dep/lib/librtmidi.4.dylib @executable_path/librtmidi.4.dylib $(BUNDLE)/Contents/MacOS/Rack @@ -146,7 +146,7 @@ ifeq ($(ARCH), win) cp dep/bin/libcurl-4.dll dist/Rack/ cp dep/bin/libjansson-4.dll dist/Rack/ cp dep/bin/librtmidi-4.dll dist/Rack/ - cp dep/bin/libsamplerate-0.dll dist/Rack/ + cp dep/bin/libspeexdsp.dll dist/Rack/ cp dep/bin/libzip-5.dll dist/Rack/ cp dep/bin/librtaudio.dll dist/Rack/ mkdir -p dist/Rack/plugins @@ -161,7 +161,7 @@ ifeq ($(ARCH), lin) mkdir -p dist/Rack cp -R LICENSE* res dist/Rack/ cp Rack Rack.sh dist/Rack/ - cp dep/lib/libsamplerate.so.0 dist/Rack/ + cp dep/lib/libspeexdsp.so dist/Rack/ cp dep/lib/libjansson.so.4 dist/Rack/ cp dep/lib/libGLEW.so.2.1 dist/Rack/ cp dep/lib/libglfw.so.3 dist/Rack/ diff --git a/dep/Makefile b/dep/Makefile index 9218d608..eff4442e 100755 --- a/dep/Makefile +++ b/dep/Makefile @@ -26,7 +26,7 @@ ifeq ($(ARCH),lin) glew = lib/libGLEW.so glfw = lib/libglfw.so jansson = lib/libjansson.so - libsamplerate = lib/libsamplerate.so + libspeexdsp = lib/libspeexdsp.so libcurl = lib/libcurl.so libzip = lib/libzip.so rtmidi = lib/librtmidi.so @@ -37,7 +37,7 @@ ifeq ($(ARCH),mac) glew = lib/libGLEW.dylib glfw = lib/libglfw.dylib jansson = lib/libjansson.dylib - libsamplerate = lib/libsamplerate.dylib + libspeexdsp = lib/libspeexdsp.dylib libcurl = lib/libcurl.dylib libzip = lib/libzip.dylib rtmidi = lib/librtmidi.dylib @@ -48,7 +48,7 @@ ifeq ($(ARCH),win) glew = bin/glew32.dll glfw = bin/glfw3.dll jansson = bin/libjansson-4.dll - libsamplerate = bin/libsamplerate-0.dll + libspeexdsp = bin/libspeexdsp.dll libcurl = bin/libcurl-4.dll libzip = bin/libzip-5.dll rtmidi = bin/librtmidi-4.dll @@ -71,7 +71,7 @@ endif .NOTPARALLEL: -all: $(glew) $(glfw) $(jansson) $(libsamplerate) $(libcurl) $(libzip) $(rtmidi) $(rtaudio) +all: $(glew) $(glfw) $(jansson) $(libspeexdsp) $(libcurl) $(libzip) $(rtmidi) $(rtaudio) @echo "" @echo "#######################################" @echo "# Built all dependencies successfully #" @@ -99,12 +99,12 @@ $(jansson): $(MAKE) -C jansson-2.10 $(MAKE) -C jansson-2.10 install -$(libsamplerate): - $(WGET) http://www.mega-nerd.com/SRC/libsamplerate-0.1.9.tar.gz - $(UNTAR) libsamplerate-0.1.9.tar.gz - cd libsamplerate-0.1.9 && ./configure --prefix="$(LOCAL)" --disable-fftw --disable-sndfile - $(MAKE) -C libsamplerate-0.1.9/src - $(MAKE) -C libsamplerate-0.1.9/src install +$(libspeexdsp): + $(WGET) https://github.com/xiph/speexdsp/archive/SpeexDSP-1.2rc3.tar.gz + $(UNTAR) SpeexDSP-1.2rc3.tar.gz + cd speexdsp-SpeexDSP-1.2rc3 && ./autogen.sh && ./configure --prefix="$(LOCAL)" + $(MAKE) -C speexdsp-SpeexDSP-1.2rc3 + $(MAKE) -C speexdsp-SpeexDSP-1.2rc3 install $(libcurl): $(WGET) https://github.com/curl/curl/releases/download/curl-7_56_0/curl-7.56.0.tar.gz diff --git a/include/dsp/samplerate.hpp b/include/dsp/samplerate.hpp index 3a87d640..623ba650 100644 --- a/include/dsp/samplerate.hpp +++ b/include/dsp/samplerate.hpp @@ -1,8 +1,7 @@ #pragma once #include -#include -#include +#include #include "frame.hpp" @@ -10,50 +9,45 @@ namespace rack { template struct SampleRateConverter { - SRC_STATE *state; - SRC_DATA data; + SpeexResamplerState *state = NULL; + bool noConversion = true; SampleRateConverter() { int error; - state = src_new(SRC_SINC_FASTEST, CHANNELS, &error); - assert(!error); - - data.src_ratio = 1.0; - data.end_of_input = false; + state = speex_resampler_init(CHANNELS, 44100, 44100, SPEEX_RESAMPLER_QUALITY_DEFAULT, &error); + assert(error == RESAMPLER_ERR_SUCCESS); } ~SampleRateConverter() { - src_delete(state); + speex_resampler_destroy(state); } - /** output_sample_rate / input_sample_rate */ - void setRatio(float r) { - src_set_ratio(state, r); - data.src_ratio = r; + + void setRates(float inRate, float outRate) { + int error = speex_resampler_set_rate(state, inRate, outRate); + assert(error == RESAMPLER_ERR_SUCCESS); + noConversion = inRate == outRate; } - void setRatioSmooth(float r) { - data.src_ratio = r; + + void setRatioSmooth(float ratio) DEPRECATED { + // FIXME: this doesn't do a smooth change -- speex doesn't appear to support that. + const int base = 1000; + setRates(base, ratio * base); } + /** `in` and `out` are interlaced with the number of channels */ void process(const Frame *in, int *inFrames, Frame *out, int *outFrames) { - /* - if (nearf(data.src_ratio, 1.0)) { - int len = mini(*inFrames, *outFrames); + if (noConversion) { + int len = std::min(*inFrames, *outFrames); memcpy(out, in, len * sizeof(Frame)); *inFrames = len; *outFrames = len; return; } - */ - // Old versions of libsamplerate use float* here instead of const float* - data.data_in = (float*) in; - data.input_frames = *inFrames; - data.data_out = (float*) out; - data.output_frames = *outFrames; - src_process(state, &data); - *inFrames = data.input_frames_used; - *outFrames = data.output_frames_gen; + speex_resampler_process_interleaved_float(state, (const float*)in, (unsigned int*)inFrames, (float*)out, (unsigned int*)outFrames); } + void reset() { - src_reset(state); + int error = speex_resampler_reset_mem(state); + assert(error == RESAMPLER_ERR_SUCCESS); } }; diff --git a/src/core/AudioInterface.cpp b/src/core/AudioInterface.cpp index e120362c..b9bdfdca 100644 --- a/src/core/AudioInterface.cpp +++ b/src/core/AudioInterface.cpp @@ -169,7 +169,7 @@ void AudioInterface::step() { // Once full, sample rate convert the input // inputBuffer -> SRC -> inputSrcBuffer if (inputBuffer.full()) { - inputSrc.setRatio(sampleRate / engineGetSampleRate()); + inputSrc.setRates(engineGetSampleRate(), sampleRate); int inLen = inputBuffer.size(); int outLen = inputSrcBuffer.capacity(); inputSrc.process(inputBuffer.startData(), &inLen, inputSrcBuffer.endData(), &outLen); @@ -211,7 +211,7 @@ void AudioInterface::stepStream(const float *input, float *output, int numFrames } // Pass output through sample rate converter - outputSrc.setRatio(engineGetSampleRate() / sampleRate); + outputSrc.setRates(sampleRate, engineGetSampleRate()); int inLen = numFrames; int outLen = outputBuffer.capacity(); outputSrc.process(inputFrames, &inLen, outputBuffer.endData(), &outLen);