From 13cf58a8ee4413e553b057722f2c6b9e0b884951 Mon Sep 17 00:00:00 2001 From: David Braun Date: Mon, 4 Apr 2022 14:47:53 -0700 Subject: [PATCH] fix issue with playback warp processor when warping is disabled. Add new function for resetting warp markers to a steady BPM. Add new function for setting warp markers to a 2D array. --- Builds/LinuxMakefile/Makefile | 4 +- .../DawDreamer.xcodeproj/project.pbxproj | 8 +- .../DawDreamer_DynamicLibrary.vcxproj | 4 +- Builds/VisualStudio2019/resources.rc | 6 +- DawDreamer.jucer | 2 +- JuceLibraryCode/JuceHeader.h | 4 +- README.md | 2 +- Source/AbletonClipInfo.h | 4 + Source/PlaybackWarpProcessor.h | 58 +++++++- Source/source.cpp | 3 +- tests/test_playbackwarp_processor.py | 128 +++++++++++++++++- 11 files changed, 205 insertions(+), 18 deletions(-) diff --git a/Builds/LinuxMakefile/Makefile b/Builds/LinuxMakefile/Makefile index 7753c9d6..6b3385f8 100644 --- a/Builds/LinuxMakefile/Makefile +++ b/Builds/LinuxMakefile/Makefile @@ -35,7 +35,7 @@ ifeq ($(CONFIG),Debug) TARGET_ARCH := endif - JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DPIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==" "-DSAMPLER_SKIP_UI" "-DHAVE_LIBSAMPLERATE" "-DUSE_BUILTIN_FFT" "-DUSE_PTHREADS" "-DBUILD_DAWDREAMER_FAUST" "-DBUILD_DAWDREAMER_RUBBERBAND" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=0.6.0" "-DJUCE_APP_VERSION_HEX=0x600" $(shell pkg-config --cflags alsa freetype2 libcurl) -pthread -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/VST3_SDK -I../../thirdparty/JUCE/modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../JuceLibraryCode/modules -I/usr/include/python3.9 -I../../thirdparty/pybind11/include -I../../thirdparty/faust/architecture -I../../thirdparty/faust/compiler -I../../thirdparty/faust/compiler/utils -I../../thirdparty/libsamplerate/src -I../../thirdparty/libsamplerate/include -I../../thirdparty/rubberband -I../../thirdparty/rubberband/rubberband -I../../thirdparty/rubberband/src/kissfft -I../../thirdparty/rubberband/src -I../../thirdparty/portable_endian/include $(CPPFLAGS) + JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DPIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==" "-DSAMPLER_SKIP_UI" "-DHAVE_LIBSAMPLERATE" "-DUSE_BUILTIN_FFT" "-DUSE_PTHREADS" "-DBUILD_DAWDREAMER_FAUST" "-DBUILD_DAWDREAMER_RUBBERBAND" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=0.6.1" "-DJUCE_APP_VERSION_HEX=0x601" $(shell pkg-config --cflags alsa freetype2 libcurl) -pthread -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/VST3_SDK -I../../thirdparty/JUCE/modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../JuceLibraryCode/modules -I/usr/include/python3.9 -I../../thirdparty/pybind11/include -I../../thirdparty/faust/architecture -I../../thirdparty/faust/compiler -I../../thirdparty/faust/compiler/utils -I../../thirdparty/libsamplerate/src -I../../thirdparty/libsamplerate/include -I../../thirdparty/rubberband -I../../thirdparty/rubberband/rubberband -I../../thirdparty/rubberband/src/kissfft -I../../thirdparty/rubberband/src -I../../thirdparty/portable_endian/include $(CPPFLAGS) JUCE_CPPFLAGS_DYNAMIC_LIBRARY := "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_RTAS=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" JUCE_CFLAGS_DYNAMIC_LIBRARY := -fPIC -fvisibility=hidden JUCE_LDFLAGS_DYNAMIC_LIBRARY := -shared @@ -58,7 +58,7 @@ ifeq ($(CONFIG),Release) TARGET_ARCH := endif - JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DPIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==" "-DSAMPLER_SKIP_UI" "-DHAVE_LIBSAMPLERATE" "-DUSE_BUILTIN_FFT" "-DUSE_PTHREADS" "-DBUILD_DAWDREAMER_FAUST" "-DBUILD_DAWDREAMER_RUBBERBAND" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=0.6.0" "-DJUCE_APP_VERSION_HEX=0x600" $(shell pkg-config --cflags alsa freetype2 libcurl) -pthread -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/VST3_SDK -I../../thirdparty/JUCE/modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../JuceLibraryCode/modules -I/usr/include/python3.9 -I../../thirdparty/pybind11/include -I../../thirdparty/faust/architecture -I../../thirdparty/faust/compiler -I../../thirdparty/faust/compiler/utils -I../../thirdparty/libsamplerate/src -I../../thirdparty/libsamplerate/include -I../../thirdparty/rubberband -I../../thirdparty/rubberband/rubberband -I../../thirdparty/rubberband/src/kissfft -I../../thirdparty/rubberband/src -I../../thirdparty/portable_endian/include $(CPPFLAGS) + JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DPIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==" "-DSAMPLER_SKIP_UI" "-DHAVE_LIBSAMPLERATE" "-DUSE_BUILTIN_FFT" "-DUSE_PTHREADS" "-DBUILD_DAWDREAMER_FAUST" "-DBUILD_DAWDREAMER_RUBBERBAND" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=0.6.1" "-DJUCE_APP_VERSION_HEX=0x601" $(shell pkg-config --cflags alsa freetype2 libcurl) -pthread -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/VST3_SDK -I../../thirdparty/JUCE/modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../JuceLibraryCode/modules -I/usr/include/python3.9 -I../../thirdparty/pybind11/include -I../../thirdparty/faust/architecture -I../../thirdparty/faust/compiler -I../../thirdparty/faust/compiler/utils -I../../thirdparty/libsamplerate/src -I../../thirdparty/libsamplerate/include -I../../thirdparty/rubberband -I../../thirdparty/rubberband/rubberband -I../../thirdparty/rubberband/src/kissfft -I../../thirdparty/rubberband/src -I../../thirdparty/portable_endian/include $(CPPFLAGS) JUCE_CPPFLAGS_DYNAMIC_LIBRARY := "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_RTAS=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" JUCE_CFLAGS_DYNAMIC_LIBRARY := -fPIC -fvisibility=hidden JUCE_LDFLAGS_DYNAMIC_LIBRARY := -shared diff --git a/Builds/MacOSX/DawDreamer.xcodeproj/project.pbxproj b/Builds/MacOSX/DawDreamer.xcodeproj/project.pbxproj index a44d94b3..cef663ba 100644 --- a/Builds/MacOSX/DawDreamer.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/DawDreamer.xcodeproj/project.pbxproj @@ -783,8 +783,8 @@ "BUILD_DAWDREAMER_FAUST", "BUILD_DAWDREAMER_RUBBERBAND", "JUCER_XCODE_MAC_F6D2F4CF=1", - "JUCE_APP_VERSION=0.6.0", - "JUCE_APP_VERSION_HEX=0x600", + "JUCE_APP_VERSION=0.6.1", + "JUCE_APP_VERSION_HEX=0x601", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", @@ -908,8 +908,8 @@ "BUILD_DAWDREAMER_FAUST", "BUILD_DAWDREAMER_RUBBERBAND", "JUCER_XCODE_MAC_F6D2F4CF=1", - "JUCE_APP_VERSION=0.6.0", - "JUCE_APP_VERSION_HEX=0x600", + "JUCE_APP_VERSION=0.6.1", + "JUCE_APP_VERSION_HEX=0x601", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", diff --git a/Builds/VisualStudio2019/DawDreamer_DynamicLibrary.vcxproj b/Builds/VisualStudio2019/DawDreamer_DynamicLibrary.vcxproj index 41c52abf..6bdf9c15 100644 --- a/Builds/VisualStudio2019/DawDreamer_DynamicLibrary.vcxproj +++ b/Builds/VisualStudio2019/DawDreamer_DynamicLibrary.vcxproj @@ -66,7 +66,7 @@ Disabled ProgramDatabase ..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\VST3_SDK;..\..\thirdparty\JUCE\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;$(pythonLocation)\include;..\..\thirdparty\pybind11\include;..\..\thirdparty\faust\architecture;..\..\thirdparty\faust\compiler;..\..\thirdparty\faust\compiler\utils;..\..\thirdparty\libsamplerate\src;..\..\thirdparty\libsamplerate\include;..\..\thirdparty\rubberband;..\..\thirdparty\rubberband\rubberband;..\..\thirdparty\rubberband\src\kissfft;..\..\thirdparty\rubberband\src;..\..\thirdparty\portable_endian\include;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;SAMPLER_SKIP_UI;_WIN32;__SSE__;__SSE2__;BUILD_DAWDREAMER_FAUST;BUILD_DAWDREAMER_RUBBERBAND;NOMINMAX;HAVE_LIBSAMPLERATE;HAVE_KISSFFT;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=0.6.0;JUCE_APP_VERSION_HEX=0x600;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;_LIB;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;SAMPLER_SKIP_UI;_WIN32;__SSE__;__SSE2__;BUILD_DAWDREAMER_FAUST;BUILD_DAWDREAMER_RUBBERBAND;NOMINMAX;HAVE_LIBSAMPLERATE;HAVE_KISSFFT;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=0.6.1;JUCE_APP_VERSION_HEX=0x601;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;_LIB;%(PreprocessorDefinitions) MultiThreadedDebugDLL true NotUsing @@ -116,7 +116,7 @@ copy "..\..\thirdparty\libfaust\win-x64\Debug\bin\faust.dll" "$(p Full ..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\VST3_SDK;..\..\thirdparty\JUCE\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;$(pythonLocation)\include;..\..\thirdparty\pybind11\include;..\..\thirdparty\faust\architecture;..\..\thirdparty\faust\compiler;..\..\thirdparty\faust\compiler\utils;..\..\thirdparty\libsamplerate\src;..\..\thirdparty\libsamplerate\include;..\..\thirdparty\rubberband;..\..\thirdparty\rubberband\rubberband;..\..\thirdparty\rubberband\src\kissfft;..\..\thirdparty\rubberband\src;..\..\thirdparty\portable_endian\include;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;SAMPLER_SKIP_UI;_WIN32;__SSE__;__SSE2__;BUILD_DAWDREAMER_FAUST;BUILD_DAWDREAMER_RUBBERBAND;NOMINMAX;HAVE_LIBSAMPLERATE;HAVE_KISSFFT;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=0.6.0;JUCE_APP_VERSION_HEX=0x600;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;_LIB;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;SAMPLER_SKIP_UI;_WIN32;__SSE__;__SSE2__;BUILD_DAWDREAMER_FAUST;BUILD_DAWDREAMER_RUBBERBAND;NOMINMAX;HAVE_LIBSAMPLERATE;HAVE_KISSFFT;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=0.6.1;JUCE_APP_VERSION_HEX=0x601;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;_LIB;%(PreprocessorDefinitions) MultiThreadedDLL true NotUsing diff --git a/Builds/VisualStudio2019/resources.rc b/Builds/VisualStudio2019/resources.rc index b6a40715..25359650 100644 --- a/Builds/VisualStudio2019/resources.rc +++ b/Builds/VisualStudio2019/resources.rc @@ -9,16 +9,16 @@ #include VS_VERSION_INFO VERSIONINFO -FILEVERSION 0,6,0,0 +FILEVERSION 0,6,1,0 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "FileDescription", "DawDreamer\0" - VALUE "FileVersion", "0.6.0\0" + VALUE "FileVersion", "0.6.1\0" VALUE "ProductName", "DawDreamer\0" - VALUE "ProductVersion", "0.6.0\0" + VALUE "ProductVersion", "0.6.1\0" END END diff --git a/DawDreamer.jucer b/DawDreamer.jucer index 2f2ff2d9..481acdd2 100644 --- a/DawDreamer.jucer +++ b/DawDreamer.jucer @@ -1,6 +1,6 @@ -> warp_markers; int beat_to_sample(double beat, double sr) { diff --git a/Source/PlaybackWarpProcessor.h b/Source/PlaybackWarpProcessor.h index d92ee172..152c79c0 100644 --- a/Source/PlaybackWarpProcessor.h +++ b/Source/PlaybackWarpProcessor.h @@ -58,7 +58,7 @@ class PlaybackWarpProcessor : public ProcessorBase void setTimeRatio(double ratio) { m_time_ratio_if_warp_off = ratio; } - bool getTimeRatio() { + double getTimeRatio() { return m_time_ratio_if_warp_off; } @@ -105,6 +105,60 @@ class PlaybackWarpProcessor : public ProcessorBase return arr; } + void resetWarpMarkers(double bpm) { + m_clipInfo.warp_markers.clear(); + + m_clipInfo.warp_markers.push_back(std::make_pair(0, 0)); + double numSamples = 128; + double beats = bpm / (60. * numSamples / m_sample_rate); + m_clipInfo.warp_markers.push_back(std::make_pair(numSamples, beats)); + } + + void setWarpMarkers(py::array_t input) { + + if (input.ndim() != 2) { + throw std::runtime_error("The warp markers must be two-dimensional and shaped (num_markers, 2)."); + return; + } + + const int numPairs = (int)input.shape(0); + + if (numPairs < 2) { + throw std::runtime_error("The number of warp markers must be greater than one."); + return; + } + + if (input.shape(1) != 2) { + throw std::runtime_error("The dimensions of the passed warp markers are incorrect."); + return; + } + + std::vector> warp_markers; + + double beat, new_beat; + double pos, new_pos; + beat = new_beat = pos = new_pos = -999999.; + + float* input_ptr = (float*)input.data(); + + for (int pair_i = 0; pair_i < numPairs; pair_i++) { + + new_pos = *input_ptr++; + new_beat = *input_ptr++; + + if (new_beat <= beat || new_pos <= pos) { + throw std::runtime_error("The warp markers must be monotonically increasing. new_beat: " + std::to_string(new_beat) + " beat: " + std::to_string(beat) + " new_pos: " + std::to_string(new_pos) + " pos: " + std::to_string(pos)); + } + + pos = new_pos; + beat = new_beat; + + warp_markers.push_back(std::make_pair(pos, beat)); + } + + m_clipInfo.warp_markers = warp_markers; + } + private: class Clip { public: @@ -234,6 +288,7 @@ class PlaybackWarpProcessor : public ProcessorBase else { sampleReadIndex = 0; } + continue; } else { @@ -302,6 +357,7 @@ class PlaybackWarpProcessor : public ProcessorBase setupRubberband(m_sample_rate, m_numChannels); m_clipIndex = 0; + sampleReadIndex = 0; if (m_clipIndex < m_clips.size()) { m_currentClip = m_clips.at(0); diff --git a/Source/source.cpp b/Source/source.cpp index 26475632..06ca9936 100644 --- a/Source/source.cpp +++ b/Source/source.cpp @@ -90,8 +90,9 @@ play the audio in double the amount of time, so it will sound slowed down.") .def_property("loop_end", &PlaybackWarpProcessor::getLoopEnd, &PlaybackWarpProcessor::setLoopEnd, "The loop end position in beats (typically quarter notes) relative to 1.1.1") .def_property("start_marker", &PlaybackWarpProcessor::getStartMarker, &PlaybackWarpProcessor::setStartMarker, "The start position in beats (typically quarter notes) relative to 1.1.1") .def_property("end_marker", &PlaybackWarpProcessor::getEndMarker, &PlaybackWarpProcessor::setEndMarker, "The end position in beats (typically quarter notes) relative to 1.1.1") + .def_property("warp_markers", &PlaybackWarpProcessor::getWarpMarkers, &PlaybackWarpProcessor::setWarpMarkers, "Get/set the warp markers as a 2D array of time positions in seconds and positions in beats.") + .def("reset_warp_markers", &PlaybackWarpProcessor::resetWarpMarkers, arg("bpm"), "Reset the warp markers with a BPM.") .def("set_clip_file", &PlaybackWarpProcessor::loadAbletonClipInfo, arg("asd_file_path"), "Load an Ableton Live file with an \".asd\" extension") - .def_property_readonly("warp_markers", &PlaybackWarpProcessor::getWarpMarkers, "Get the warp markers as a 2D array of time positions in seconds and positions in beats.") .def("set_data", &PlaybackWarpProcessor::setData, arg("data"), "Set the audio as a numpy array shaped (Channels, Samples).") .def("set_clip_positions", &PlaybackWarpProcessor::setClipPositions, arg("clip_positions"), R"pbdoc( Set one or more positions at which the clip should play. diff --git a/tests/test_playbackwarp_processor.py b/tests/test_playbackwarp_processor.py index ca13d5ab..356f70ca 100644 --- a/tests/test_playbackwarp_processor.py +++ b/tests/test_playbackwarp_processor.py @@ -27,6 +27,22 @@ def test_playbackwarp_processor1(): print('drums.loop_end: ', drums.loop_end) print('drums.warp_on: ', drums.warp_on) + warp_markers = drums.warp_markers + + warp1 = warp_markers[0] + warp3 = warp_markers[-1] + warp2 = 0.5*(warp1+warp3) + + warp_markers = np.stack([warp1, warp2, warp3], axis=0) + + assert warp_markers.shape[0] == 3 + assert warp_markers.shape[1] == 2 + + drums.warp_markers = warp_markers + + assert drums.warp_markers.shape[0] == 3 + assert drums.warp_markers.shape[1] == 2 + graph = [ (drums, []), (other, []), @@ -37,14 +53,20 @@ def test_playbackwarp_processor1(): render(engine, file_path=OUTPUT / 'test_playbackwarp_processor1a.wav') + assert(np.mean(np.abs(engine.get_audio())) > .01) + other.transpose = 2. render(engine, file_path=OUTPUT / 'test_playbackwarp_processor1b.wav') + assert(np.mean(np.abs(engine.get_audio())) > .01) + other.set_automation('transpose', make_sine(1., DURATION)) render(engine, file_path=OUTPUT / 'test_playbackwarp_processor1c.wav') + assert(np.mean(np.abs(engine.get_audio())) > .01) + def test_playbackwarp_processor2(): DURATION = 10. @@ -74,6 +96,8 @@ def test_playbackwarp_processor2(): render(engine, file_path=OUTPUT / 'test_playbackwarp_processor2a.wav') + assert(np.mean(np.abs(engine.get_audio())) > .01) + drums.set_clip_positions([[0., 4., 0.]]) drums.start_marker = 0. drums.loop_start = 1. @@ -81,9 +105,111 @@ def test_playbackwarp_processor2(): render(engine, file_path=OUTPUT / 'test_playbackwarp_processor2b.wav') + assert(np.mean(np.abs(engine.get_audio())) > .01) + drums.start_marker = 0. drums.loop_start = 3. drums.loop_end = 4. drums.set_clip_positions([[0., 2., 0.], [3., 9., 3.]]) - render(engine, file_path=OUTPUT / 'test_playbackwarp_processor2c.wav') \ No newline at end of file + render(engine, file_path=OUTPUT / 'test_playbackwarp_processor2c.wav') + + assert(np.mean(np.abs(engine.get_audio())) > .01) + + +def test_playbackwarp_processor3(): + + """ + Test using the playback warp processor without a clip file and therefore without warping. + The BPM of the engine should not affect the output audio. + Looping should work. + The time ratio should have an effect. + """ + + DURATION = 3. + + engine = daw.RenderEngine(SAMPLE_RATE, BUFFER_SIZE) + + drum_audio = load_audio_file(ASSETS / "575854__yellowtree__d-b-funk-loop.wav") + drum_audio = drum_audio[:, int(SAMPLE_RATE*.267):] # manually trim to beginning + + drums = engine.make_playbackwarp_processor("drums", drum_audio) + + drums.time_ratio = .7 + assert drums.time_ratio == .7 + + drums.loop_on = True + assert(drums.loop_on) + + assert not drums.warp_on + + actual_bpm = 108. + num_beats = 2. + drums.loop_end = num_beats*60./actual_bpm + + graph = [ + (drums, []), + ] + + engine.load_graph(graph) + + render(engine, file_path=OUTPUT / 'test_playbackwarp_processor3a.wav', duration=DURATION) + + audio = engine.get_audio() + + assert audio.ndim == 2 + + num_samples = audio.shape[1] + + assert num_samples > 100 + + assert(np.mean(np.abs(audio)) > .01) + + +def test_playbackwarp_processor4(): + + """ + Test using the playback warp processor without a clip file and therefore without warping. + The BPM of the engine should not affect the output audio. + Test that `reset_warp_markers` works with a BPM argument. + """ + + DURATION = 10. + + engine = daw.RenderEngine(SAMPLE_RATE, BUFFER_SIZE) + + drum_audio = load_audio_file(ASSETS / "Music Delta - Disco" / "drums.wav") + drum_audio = drum_audio[:, int(SAMPLE_RATE*.267):] # manually trim to beginning + + drums = engine.make_playbackwarp_processor("drums", drum_audio) + + assert drums.time_ratio == 1. + + drums.loop_on = True + assert(drums.loop_on) + + assert not drums.warp_on + + actual_bpm = 110. + num_beats = 2. + + drums.reset_warp_markers(actual_bpm) + drums.loop_end = num_beats + + graph = [ + (drums, []), + ] + + engine.load_graph(graph) + + render(engine, file_path=OUTPUT / 'test_playbackwarp_processor4a.wav', duration=DURATION) + + audio = engine.get_audio() + + assert audio.ndim == 2 + + num_samples = audio.shape[1] + + assert num_samples > 100 + + assert(np.mean(np.abs(audio)) > .01) \ No newline at end of file