diff --git a/.travis.yml b/.travis.yml index 77731c0e8..47ae06a8f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,9 @@ jobs: script: .travis/script_test.sh - name: "Linux arm64 tests" - arch: arm64 + arch: arm64-graviton2 + group: edge + virt: lxd addons: apt: packages: @@ -54,7 +56,7 @@ jobs: env: - INSTALL_DIR="sfizz-${TRAVIS_BRANCH}-${TRAVIS_OS_NAME}-${TRAVIS_CPU_ARCH}" script: .travis/script_osx.sh - after_success: .travis/prepare_osx.sh + after_success: .travis/prepare_tarball.sh - name: "MOD devices arm" env: @@ -100,7 +102,9 @@ jobs: after_success: .travis/prepare_tarball.sh - name: "Linux arm64 library" - arch: arm64 + arch: arm64-graviton2 + group: edge + virt: lxd env: - INSTALL_DIR="sfizz-${TRAVIS_BRANCH}-${TRAVIS_OS_NAME}-${TRAVIS_CPU_ARCH}" addons: @@ -113,7 +117,9 @@ jobs: after_success: .travis/prepare_tarball.sh - name: "Linux arm64 static plugins" - arch: arm64 + arch: arm64-graviton2 + group: edge + virt: lxd env: - INSTALL_DIR="sfizz-plugins-${TRAVIS_BRANCH}-${TRAVIS_OS_NAME}-${TRAVIS_CPU_ARCH}" - ENABLE_VST_PLUGIN=OFF diff --git a/.travis/before_install.sh b/.travis/before_install.sh deleted file mode 100755 index 28d375f6d..000000000 --- a/.travis/before_install.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -set -ex -. .travis/environment.sh - -cmake_dir="cmake-3.13.0-${TRAVIS_OS_NAME}-${TRAVIS_CPU_ARCH}" -cmake_arc="${cmake_dir}.tar.gz" -cmake_url="https://github.com/sfztools/cmake/releases/download/${TRAVIS_OS_NAME}/${cmake_arc}" - -if [[ ${CROSS_COMPILE} == "mingw32" || ${CROSS_COMPILE} == "mingw64" ]]; then - buildenv bash -c "echo Hello from container" # ensure to start the container - docker cp "$container":/etc/pacman.conf pacman.conf - cat >>pacman.conf <setBackgroundColor(theme->boxBackground); box->setTitleFontColor(theme->titleBoxText); box->setTitleBackgroundColor(theme->titleBoxBackground); - auto font = owned(new CFontDesc("Roboto", fontsize)); + auto font = makeOwned("Roboto", fontsize); box->setTitleFont(font); return box; }; @@ -436,7 +436,7 @@ void Editor::Impl::createFrameContents() lbl->setBackColor(CColor(0x00, 0x00, 0x00, 0x00)); lbl->setFontColor(theme->text); lbl->setHoriAlign(align); - auto font = owned(new CFontDesc("Roboto", fontsize)); + auto font = makeOwned("Roboto", fontsize); lbl->setFont(font); return lbl; }; @@ -463,7 +463,7 @@ void Editor::Impl::createFrameContents() lbl->setBackColor(CColor(0x00, 0x00, 0x00, 0x00)); lbl->setFontColor(theme->text); lbl->setHoriAlign(align); - auto font = owned(new CFontDesc("Roboto", fontsize)); + auto font = makeOwned("Roboto", fontsize); lbl->setFont(font); return lbl; }; @@ -476,7 +476,7 @@ void Editor::Impl::createFrameContents() #if 0 auto createButton = [this](const CRect& bounds, int tag, const char* label, CHoriTxtAlign align, int fontsize) { CTextButton* button = new CTextButton(bounds, this, tag, label); - auto font = owned(new CFontDesc("Roboto", fontsize)); + auto font = makeOwned("Roboto", fontsize); button->setFont(font); button->setTextAlignment(align); return button; @@ -484,7 +484,7 @@ void Editor::Impl::createFrameContents() #endif auto createClickableLabel = [this, &theme](const CRect& bounds, int tag, const char* label, CHoriTxtAlign align, int fontsize) { STextButton* button = new STextButton(bounds, this, tag, label); - auto font = owned(new CFontDesc("Roboto", fontsize)); + auto font = makeOwned("Roboto", fontsize); button->setFont(font); button->setTextAlignment(align); button->setTextColor(theme->text); @@ -499,7 +499,7 @@ void Editor::Impl::createFrameContents() }; auto createValueButton = [this, &theme](const CRect& bounds, int tag, const char* label, CHoriTxtAlign align, int fontsize) { STextButton* button = new STextButton(bounds, this, tag, label); - auto font = owned(new CFontDesc("Roboto", fontsize)); + auto font = makeOwned("Roboto", fontsize); button->setFont(font); button->setTextAlignment(align); button->setTextColor(theme->valueText); @@ -515,7 +515,7 @@ void Editor::Impl::createFrameContents() auto createValueMenu = [this, &theme](const CRect& bounds, int tag, const char*, CHoriTxtAlign align, int fontsize) { SValueMenu* vm = new SValueMenu(bounds, this, tag); vm->setHoriAlign(align); - auto font = owned(new CFontDesc("Roboto", fontsize)); + auto font = makeOwned("Roboto", fontsize); vm->setFont(font); vm->setFontColor(theme->valueText); vm->setBackColor(theme->valueBackground); @@ -526,7 +526,7 @@ void Editor::Impl::createFrameContents() }; auto createGlyphButton = [this, &theme](UTF8StringPtr glyph, const CRect& bounds, int tag, int fontsize) { STextButton* btn = new STextButton(bounds, this, tag, glyph); - btn->setFont(new CFontDesc("Sfizz Fluent System R20", fontsize)); + btn->setFont(makeOwned("Sfizz Fluent System R20", fontsize)); btn->setTextColor(theme->icon); btn->setHoverColor(theme->iconHighlight); btn->setFrameColor(CColor(0x00, 0x00, 0x00, 0x00)); @@ -559,14 +559,14 @@ void Editor::Impl::createFrameContents() }; auto createPiano = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int fontsize) { SPiano* piano = new SPiano(bounds); - auto font = owned(new CFontDesc("Roboto", fontsize)); + auto font = makeOwned("Roboto", fontsize); piano->setFont(font); return piano; }; auto createChevronDropDown = [this, &theme](const CRect& bounds, int, const char*, CHoriTxtAlign, int fontsize) { SActionMenu* menu = new SActionMenu(bounds, this); menu->setTitle(u8"\ue0d7"); - menu->setFont(new CFontDesc("Sfizz Fluent System R20", fontsize)); + menu->setFont(makeOwned("Sfizz Fluent System R20", fontsize)); menu->setFontColor(theme->icon); menu->setHoverColor(theme->iconHighlight); menu->setFrameColor(CColor(0x00, 0x00, 0x00, 0x00)); diff --git a/editor/src/editor/GUIPiano.cpp b/editor/src/editor/GUIPiano.cpp index dd7d6cf58..2c17ddc48 100644 --- a/editor/src/editor/GUIPiano.cpp +++ b/editor/src/editor/GUIPiano.cpp @@ -92,7 +92,7 @@ void SPiano::draw(CDrawContext* dc) CRect textRect( rect.left, dim.labelBounds.top, rect.right, dim.labelBounds.bottom); - dc->setFont(font_); + dc->setFont(font); dc->setFontColor(labelStroke_); std::string text = std::to_string(static_cast(o) - 1); dc->drawString(text.c_str(), textRect, kCenterText); diff --git a/lv2/CMakeLists.txt b/lv2/CMakeLists.txt index a888ca816..743b26d24 100644 --- a/lv2/CMakeLists.txt +++ b/lv2/CMakeLists.txt @@ -105,6 +105,12 @@ endif() # Installation if (NOT MSVC) - install (DIRECTORY ${PROJECT_BINARY_DIR} DESTINATION ${LV2PLUGIN_INSTALL_DIR} + install(DIRECTORY ${PROJECT_BINARY_DIR} DESTINATION ${LV2PLUGIN_INSTALL_DIR} + COMPONENT "lv2") + bundle_dylibs(lv2 + "${LV2PLUGIN_INSTALL_DIR}/${PROJECT_NAME}.lv2/Contents/Binary/sfizz.so" + COMPONENT "lv2") + bundle_dylibs(lv2-ui + "${LV2PLUGIN_INSTALL_DIR}/${PROJECT_NAME}.lv2/Contents/Binary/sfizz_ui.so" COMPONENT "lv2") endif() diff --git a/lv2/sfizz_ui.cpp b/lv2/sfizz_ui.cpp index 70ff76e15..42866eb74 100644 --- a/lv2/sfizz_ui.cpp +++ b/lv2/sfizz_ui.cpp @@ -118,6 +118,26 @@ struct sfizz_ui_t : EditorController, VSTGUIEditorInterface { void uiTouch(EditId id, bool t); }; +#if defined(_WIN32) +static bool fixBundlePath(std::string& path) +{ + // go up some directories until reaching the *.lv2 directory + bool valid = false; + while (!valid && !path.empty()) { + if (path.back() == '\\' || path.back() == '/') + path.pop_back(); + else if (path.size() > 4 && !memcmp(".lv2", path.data() + path.size() - 4, 4)) + valid = true; + else { + path.pop_back(); + while (!path.empty() && path.back() != '\\' && path.back() != '/') + path.pop_back(); + } + } + return valid; +} +#endif + static LV2UI_Handle instantiate(const LV2UI_Descriptor *descriptor, const char *plugin_uri, @@ -178,8 +198,16 @@ instantiate(const LV2UI_Descriptor *descriptor, // name, and appending "Contents/Resources" (not overridable) // * on Windows, the folder is set programmatically // * on macOS, resource files are looked up using CFBundle APIs + #if defined(_WIN32) - IWin32PlatformFrame::setResourceBasePath((std::string(bundle_path) + "\\Contents\\Resources\\").c_str()); + // some hosts give us the DLL path instead of the bundle path, + // so we have to work around that. + std::string realBundlePath { bundle_path }; + if (!fixBundlePath(realBundlePath)) + return nullptr; + + std::string resourcePath = realBundlePath + "\\Contents\\Resources\\"; + IWin32PlatformFrame::setResourceBasePath(resourcePath.c_str()); #endif // makes labels refresh correctly diff --git a/screenshot.png b/screenshot.png index 226c65ba2..464cb9ca8 100644 Binary files a/screenshot.png and b/screenshot.png differ diff --git a/src/sfizz/FilePool.cpp b/src/sfizz/FilePool.cpp index 056c76d66..bb66bb31a 100644 --- a/src/sfizz/FilePool.cpp +++ b/src/sfizz/FilePool.cpp @@ -47,7 +47,29 @@ #endif #include "threadpool/ThreadPool.h" using namespace std::placeholders; -static ThreadPool threadPool { std::thread::hardware_concurrency() > 2 ? std::thread::hardware_concurrency() - 2 : 1 }; + +static std::weak_ptr globalThreadPoolWeakPtr; +static std::mutex globalThreadPoolMutex; + +static std::shared_ptr globalThreadPool() +{ + std::shared_ptr threadPool; + + threadPool = globalThreadPoolWeakPtr.lock(); + if (threadPool) + return threadPool; + + std::lock_guard lock(globalThreadPoolMutex); + threadPool = globalThreadPoolWeakPtr.lock(); + if (threadPool) + return threadPool; + + unsigned numThreads = std::thread::hardware_concurrency(); + numThreads = (numThreads > 2) ? (numThreads - 2) : 1; + threadPool.reset(new ThreadPool(numThreads)); + globalThreadPoolWeakPtr = threadPool; + return threadPool; +} void readBaseFile(sfz::AudioReader& reader, sfz::FileAudioBuffer& output, uint32_t numFrames) { @@ -96,7 +118,7 @@ void streamFromFile(sfz::AudioReader& reader, uint32_t numFrames, sfz::Oversampl } sfz::FilePool::FilePool(sfz::Logger& logger) - : logger(logger) + : logger(logger), threadPool(globalThreadPool()) { loadingJobs.reserve(config::maxVoices); lastUsedFiles.reserve(config::maxVoices); @@ -320,9 +342,9 @@ sfz::FileDataHolder sfz::FilePool::loadFile(const FileId& fileId) noexcept } } -sfz::FileDataHolder sfz::FilePool::getFilePromise(const FileId& fileId) noexcept +sfz::FileDataHolder sfz::FilePool::getFilePromise(const std::shared_ptr& fileId) noexcept { - const auto preloaded = preloadedFiles.find(fileId); + const auto preloaded = preloadedFiles.find(*fileId); if (preloaded == preloadedFiles.end()) { DBG("[sfizz] File not found in the preloaded files: " << fileId); return {}; @@ -359,14 +381,20 @@ void sfz::FilePool::loadingJob(QueuedFileData data) noexcept { raiseCurrentThreadPriority(); + std::shared_ptr id = data.id.lock(); + if (!id) { + // file ID was nulled, it means the region was deleted, ignore + return; + } + const auto loadStartTime = std::chrono::high_resolution_clock::now(); const auto waitDuration = loadStartTime - data.queuedTime; - const fs::path file { rootDirectory / data.id.filename() }; + const fs::path file { rootDirectory / id->filename() }; std::error_code readError; - AudioReaderPtr reader = createAudioReader(file, data.id.isReverse(), &readError); + AudioReaderPtr reader = createAudioReader(file, id->isReverse(), &readError); if (readError) { - DBG("[sfizz] libsndfile errored for " << data.id << " with message " << readError.message()); + DBG("[sfizz] libsndfile errored for " << *id << " with message " << readError.message()); return; } @@ -376,7 +404,7 @@ void sfz::FilePool::loadingJob(QueuedFileData data) noexcept while (currentStatus == FileData::Status::Invalid) { // Spin until the state changes if (spinCounter > 1024) { - DBG("[sfizz] " << data.id << " is stuck on Invalid? Leaving the load"); + DBG("[sfizz] " << *id << " is stuck on Invalid? Leaving the load"); return; } @@ -396,18 +424,21 @@ void sfz::FilePool::loadingJob(QueuedFileData data) noexcept const auto frames = static_cast(reader->frames()); streamFromFile(*reader, frames, oversamplingFactor, data.data->fileData, &data.data->availableFrames); const auto loadDuration = std::chrono::high_resolution_clock::now() - loadStartTime; - logger.logFileTime(waitDuration, loadDuration, frames, data.id.filename()); + logger.logFileTime(waitDuration, loadDuration, frames, id->filename()); data.data->status = FileData::Status::Done; - std::lock_guard guard { lastUsedMutex }; - if (absl::c_find(lastUsedFiles, data.id) == lastUsedFiles.end()) - lastUsedFiles.push_back(data.id); + std::lock_guard guard { garbageAndLastUsedMutex }; + if (absl::c_find(lastUsedFiles, *id) == lastUsedFiles.end()) + lastUsedFiles.push_back(*id); } void sfz::FilePool::clear() { + std::lock_guard guard { garbageAndLastUsedMutex }; emptyFileLoadingQueues(); + garbageToCollect.clear(); + lastUsedFiles.clear(); preloadedFiles.clear(); } @@ -464,23 +495,16 @@ bool is_ready(std::future const& f) void sfz::FilePool::dispatchingJob() noexcept { QueuedFileData queuedData; - while (dispatchFlag) { - dispatchBarrier.wait(); - - if (emptyQueueFlag) { - while (filesToLoad.try_pop(queuedData)) { - // pass - } - semEmptyQueueFinished.post(); - emptyQueueFlag = false; - continue; - } - + while (dispatchBarrier.wait(), dispatchFlag) { std::lock_guard guard { loadingJobsMutex }; - + if (filesToLoad.try_pop(queuedData)) { - loadingJobs.push_back( - threadPool.enqueue([this](const QueuedFileData& data) { loadingJob(data); }, queuedData)); + if (queuedData.id.expired()) { + // file ID was nulled, it means the region was deleted, ignore + } + else + loadingJobs.push_back( + threadPool->enqueue([this](const QueuedFileData& data) { loadingJob(data); }, queuedData)); } // Clear finished jobs @@ -492,29 +516,12 @@ void sfz::FilePool::dispatchingJob() noexcept void sfz::FilePool::garbageJob() noexcept { - while (garbageFlag) { - semGarbageBarrier.wait(); - { - std::lock_guard guard { garbageMutex }; - for (auto& g: garbageToCollect) - g.reset(); - - garbageToCollect.clear(); - } + while (semGarbageBarrier.wait(), garbageFlag) { + std::lock_guard guard { garbageAndLastUsedMutex }; + garbageToCollect.clear(); } } -void sfz::FilePool::emptyFileLoadingQueues() noexcept -{ - ASSERT(dispatchFlag); - emptyQueueFlag = true; - std::error_code ec; - dispatchBarrier.post(ec); - - if (!ec) - semEmptyQueueFinished.wait(); -} - void sfz::FilePool::waitForBackgroundLoading() noexcept { std::lock_guard guard { loadingJobsMutex }; @@ -580,9 +587,8 @@ void sfz::FilePool::setRamLoading(bool loadInRam) noexcept void sfz::FilePool::triggerGarbageCollection() noexcept { - const std::unique_lock lastUsedLock { lastUsedMutex, std::try_to_lock }; - const std::unique_lock garbageLock { garbageMutex, std::try_to_lock }; - if (!lastUsedLock.owns_lock() || !garbageLock.owns_lock()) + const std::unique_lock guard { garbageAndLastUsedMutex, std::try_to_lock }; + if (!guard.owns_lock()) return; const auto now = std::chrono::high_resolution_clock::now(); @@ -590,7 +596,14 @@ void sfz::FilePool::triggerGarbageCollection() noexcept if (garbageToCollect.size() == garbageToCollect.capacity()) return false; - auto& data = preloadedFiles[id]; + auto it = preloadedFiles.find(id); + if (it == preloadedFiles.end()) { + // Getting here means that the preloadedFiles got changed (probably cleared) + // while the lastUsedFiles were untouched. + return true; + } + + sfz::FileData& data = it->second; if (data.status == FileData::Status::Preloaded) return true; diff --git a/src/sfizz/FilePool.h b/src/sfizz/FilePool.h index a44ce9483..410685988 100644 --- a/src/sfizz/FilePool.h +++ b/src/sfizz/FilePool.h @@ -44,6 +44,7 @@ #include #include #include "utility/SpinMutex.h" +class ThreadPool; namespace sfz { using FileAudioBuffer = AudioBuffer& fileId) noexcept; /** * @brief Change the preloading size. This will trigger a full * reload of all samples, so don't call it on the audio thread. @@ -295,7 +296,11 @@ class FilePool { * method on the audio thread as it will spinlock. * */ - void emptyFileLoadingQueues() noexcept; + void emptyFileLoadingQueues() noexcept + { + // nothing to do in this implementation, + // deleting the region and its sample ID take care of it + } /** * @brief Wait for the background loading to finish for all promises * in the queue. @@ -330,9 +335,7 @@ class FilePool { // Signals volatile bool dispatchFlag { true }; volatile bool garbageFlag { true }; - volatile bool emptyQueueFlag { false }; RTSemaphore dispatchBarrier; - RTSemaphore semEmptyQueueFinished; RTSemaphore semGarbageBarrier; // Structures for the background loaders @@ -340,13 +343,13 @@ class FilePool { { using TimePoint = std::chrono::time_point; QueuedFileData() = default; - QueuedFileData(FileId id, FileData* data, TimePoint queuedTime) + QueuedFileData(std::weak_ptr id, FileData* data, TimePoint queuedTime) : id(id), data(data), queuedTime(queuedTime) {} QueuedFileData(const QueuedFileData&) = default; QueuedFileData& operator=(const QueuedFileData&) = default; QueuedFileData(QueuedFileData&&) = default; QueuedFileData& operator=(QueuedFileData&&) = default; - FileId id {}; + std::weak_ptr id; FileData* data { nullptr }; TimePoint queuedTime {}; }; @@ -359,11 +362,12 @@ class FilePool { std::thread dispatchThread { &FilePool::dispatchingJob, this }; std::thread garbageThread { &FilePool::garbageJob, this }; - SpinMutex lastUsedMutex; + SpinMutex garbageAndLastUsedMutex; std::vector lastUsedFiles; - SpinMutex garbageMutex; std::vector garbageToCollect; + std::shared_ptr threadPool; + // Preloaded data absl::flat_hash_map preloadedFiles; absl::flat_hash_map loadedFiles; diff --git a/src/sfizz/Panning.cpp b/src/sfizz/Panning.cpp index f7b96bd9d..5c2cf455b 100644 --- a/src/sfizz/Panning.cpp +++ b/src/sfizz/Panning.cpp @@ -49,10 +49,10 @@ inline void tickPan(const float* pan, float* leftBuffer, float* rightBuffer) void pan(const float* panEnvelope, float* leftBuffer, float* rightBuffer, unsigned size) noexcept { - const auto sentinel = panEnvelope + size; + const auto* sentinel = panEnvelope + size; #if SFIZZ_HAVE_NEON - const auto firstAligned = prevAligned(panEnvelope + TypeAlignment - 1); + const auto* firstAligned = prevAligned(panEnvelope + TypeAlignment - 1); if (willAlign(panEnvelope, leftBuffer, rightBuffer) && (firstAligned < sentinel)) { while (panEnvelope < firstAligned) { @@ -63,7 +63,7 @@ void pan(const float* panEnvelope, float* leftBuffer, float* rightBuffer, unsign uint32_t indices[TypeAlignment]; float leftPan[TypeAlignment]; float rightPan[TypeAlignment]; - const auto lastAligned = prevAligned(sentinel); + const auto* lastAligned = prevAligned(sentinel); while (panEnvelope < lastAligned) { float32x4_t mmPan = vld1q_f32(panEnvelope); mmPan = vaddq_f32(mmPan, vdupq_n_f32(1.0f)); @@ -112,10 +112,10 @@ inline void tickWidth(const float* width, float* leftBuffer, float* rightBuffer) void width(const float* widthEnvelope, float* leftBuffer, float* rightBuffer, unsigned size) noexcept { - const auto sentinel = widthEnvelope + size; + const auto* sentinel = widthEnvelope + size; #if SFIZZ_HAVE_NEON - const auto firstAligned = prevAligned(widthEnvelope + TypeAlignment - 1); + const auto* firstAligned = prevAligned(widthEnvelope + TypeAlignment - 1); if (willAlign(widthEnvelope, leftBuffer, rightBuffer) && firstAligned < sentinel) { while (widthEnvelope < firstAligned) { @@ -126,7 +126,7 @@ void width(const float* widthEnvelope, float* leftBuffer, float* rightBuffer, un uint32_t indices[TypeAlignment]; float coeff1[TypeAlignment]; float coeff2[TypeAlignment]; - const auto lastAligned = prevAligned(sentinel); + const auto* lastAligned = prevAligned(sentinel); while (widthEnvelope < lastAligned) { float32x4_t mmWidth = vld1q_f32(widthEnvelope); mmWidth = vaddq_f32(mmWidth, vdupq_n_f32(1.0f)); diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index 810b0d79f..71eb7ca69 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -75,7 +75,7 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode) else filename = absl::StrCat(defaultPath, absl::StrReplaceAll(trimmedSample, { { "\\", "/" } })); - sampleId = FileId(std::move(filename), sampleId.isReverse()); + *sampleId = FileId(std::move(filename), sampleId->isReverse()); } break; case hash("sample_quality"): @@ -88,7 +88,7 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode) } break; case hash("direction"): - sampleId = sampleId.reversed(opcode.value == "reverse"); + *sampleId = sampleId->reversed(opcode.value == "reverse"); break; case hash("delay"): setValueFromOpcode(opcode, delay, Default::delayRange); diff --git a/src/sfizz/Region.h b/src/sfizz/Region.h index 8cf68067e..2f0f7f0be 100644 --- a/src/sfizz/Region.h +++ b/src/sfizz/Region.h @@ -78,7 +78,7 @@ struct Region { * @return true * @return false */ - bool isGenerator() const noexcept { return sampleId.filename().size() > 0 ? sampleId.filename()[0] == '*' : false; } + bool isGenerator() const noexcept { return sampleId->filename().size() > 0 ? sampleId->filename()[0] == '*' : false; } /** * @brief Is an oscillator (generator or wavetable)? * @@ -308,7 +308,7 @@ struct Region { const NumericId id; // Sound source: sample playback - FileId sampleId {}; // Sample + std::shared_ptr sampleId { new FileId }; // Sample absl::optional sampleQuality {}; float delay { Default::delay }; // delay float delayRandom { Default::delayRandom }; // delay_random diff --git a/src/sfizz/SIMDHelpers.h b/src/sfizz/SIMDHelpers.h index a7b9a08ca..fc5e23379 100644 --- a/src/sfizz/SIMDHelpers.h +++ b/src/sfizz/SIMDHelpers.h @@ -663,10 +663,10 @@ void sfzInterpolationCast(absl::Span floatJumps, absl::Span jumps, SFIZZ_CHECK(jumps.size() >= floatJumps.size()); SFIZZ_CHECK(jumps.size() == coeffs.size()); - auto floatJump = floatJumps.data(); - auto jump = jumps.data(); - auto coeff = coeffs.data(); - const auto sentinel = floatJump + min(floatJumps.size(), jumps.size(), coeffs.size()); + auto* floatJump = floatJumps.data(); + auto* jump = jumps.data(); + auto* coeff = coeffs.data(); + const auto* sentinel = floatJump + min(floatJumps.size(), jumps.size(), coeffs.size()); while (floatJump < sentinel) _internals::snippetSFZInterpolationCast(floatJump, jump, coeff); diff --git a/src/sfizz/StringViewHelpers.h b/src/sfizz/StringViewHelpers.h index 2907c6ea9..11026f34d 100644 --- a/src/sfizz/StringViewHelpers.h +++ b/src/sfizz/StringViewHelpers.h @@ -12,6 +12,7 @@ #pragma once #include "absl/strings/string_view.h" +#include /** * @brief Removes the whitespace on a string_view in place @@ -45,6 +46,18 @@ inline absl::string_view trim(absl::string_view s) constexpr uint64_t Fnv1aBasis = 0x811C9DC5; constexpr uint64_t Fnv1aPrime = 0x01000193; +/** + * @brief Hash a single byte. + * + * @param s the input string to be hashed + * @param h the hashing seed to use + * @return uint64_t + */ +constexpr uint64_t hashByte(uint8_t byte, uint64_t h = Fnv1aBasis) +{ + return (h ^ byte) * Fnv1aPrime; +} + /** * @brief Compile-time hashing function to be used mostly with switch/case statements. * @@ -56,7 +69,7 @@ constexpr uint64_t Fnv1aPrime = 0x01000193; */ constexpr uint64_t hash(absl::string_view s, uint64_t h = Fnv1aBasis) { - return (s.length() == 0) ? h : hash( { s.data() + 1, s.length() - 1 }, (h ^ s.front()) * Fnv1aPrime ); + return (s.length() == 0) ? h : hash({ s.data() + 1, s.length() - 1 }, hashByte(s.front(), h)); } /** @@ -73,7 +86,7 @@ constexpr uint64_t hashNoAmpersand(absl::string_view s, uint64_t h = Fnv1aBasis) return (s.length() == 0) ? h : ( (s.front() == '&') ? hashNoAmpersand( { s.data() + 1, s.length() - 1 }, h ) - : hashNoAmpersand( { s.data() + 1, s.length() - 1 }, (h ^ s.front()) * Fnv1aPrime ) + : hashNoAmpersand( { s.data() + 1, s.length() - 1 }, hashByte(s.front(), h) ) ); } diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 0f11bba46..f947331f5 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -192,7 +192,8 @@ void sfz::Synth::buildRegion(const std::vector& regionOpcodes) void sfz::Synth::clear() { - const std::lock_guard disableCallback { callbackGuard }; + // Clear the background queues before removing everyone + resources.filePool.waitForBackgroundLoading(); for (auto& voice : voices) voice->reset(); @@ -470,10 +471,10 @@ void sfz::Synth::handleEffectOpcodes(const std::vector& rawMembers) bool sfz::Synth::loadSfzFile(const fs::path& file) { - clear(); - const std::lock_guard disableCallback { callbackGuard }; + clear(); + std::error_code ec; fs::path realFile = fs::canonical(file, ec); @@ -491,9 +492,10 @@ bool sfz::Synth::loadSfzFile(const fs::path& file) bool sfz::Synth::loadSfzString(const fs::path& path, absl::string_view text) { + const std::lock_guard disableCallback { callbackGuard }; + clear(); - const std::lock_guard disableCallback { callbackGuard }; parser.parseString(path, text); if (parser.getErrorCount() > 0) return false; @@ -514,7 +516,7 @@ void sfz::Synth::finalizeSfzLoad() size_t currentRegionCount = regions.size(); auto removeCurrentRegion = [this, ¤tRegionIndex, ¤tRegionCount]() { - DBG("Removing the region with sample " << regions[currentRegionIndex]->sampleId); + DBG("Removing the region with sample " << *regions[currentRegionIndex]->sampleId); regions.erase(regions.begin() + currentRegionIndex); --currentRegionCount; }; @@ -534,12 +536,12 @@ void sfz::Synth::finalizeSfzLoad() absl::optional fileInformation; if (!region->isGenerator()) { - if (!resources.filePool.checkSampleId(region->sampleId)) { + if (!resources.filePool.checkSampleId(*region->sampleId)) { removeCurrentRegion(); continue; } - fileInformation = resources.filePool.getFileInformation(region->sampleId); + fileInformation = resources.filePool.getFileInformation(*region->sampleId); if (!fileInformation) { removeCurrentRegion(); continue; @@ -583,11 +585,11 @@ void sfz::Synth::finalizeSfzLoad() return Default::offsetCCRange.clamp(sumOffsetCC); }(); - if (!resources.filePool.preloadFile(region->sampleId, maxOffset)) + if (!resources.filePool.preloadFile(*region->sampleId, maxOffset)) removeCurrentRegion(); } else if (!region->isGenerator()) { - if (!resources.wavePool.createFileWave(resources.filePool, std::string(region->sampleId.filename()))) { + if (!resources.wavePool.createFileWave(resources.filePool, std::string(region->sampleId->filename()))) { removeCurrentRegion(); continue; } diff --git a/src/sfizz/Synth.h b/src/sfizz/Synth.h index 350e98bf0..d1db8a933 100644 --- a/src/sfizz/Synth.h +++ b/src/sfizz/Synth.h @@ -683,6 +683,7 @@ class Synth final : public Voice::StateListener, public Parser::Listener { * @brief Remove all regions, resets all voices and clears everything * to bring back the synth in its original state. * + * The callback mutex should be taken to call this function. */ void clear(); diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 2069d9b72..3b2ee301f 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -64,9 +64,9 @@ void sfz::Voice::startVoice(Region* region, int delay, const TriggerEvent& event if (region->isOscillator()) { const WavetableMulti* wave = nullptr; if (!region->isGenerator()) - wave = resources.wavePool.getFileWave(region->sampleId.filename()); + wave = resources.wavePool.getFileWave(region->sampleId->filename()); else { - switch (hash(region->sampleId.filename())) { + switch (hash(region->sampleId->filename())) { default: case hash("*silence"): break; @@ -658,7 +658,7 @@ void sfz::Voice::fillWithData(AudioSpan buffer) noexcept DBG("[sfizz] Underflow: source available samples " << source.getNumFrames() << "/" << currentPromise->information.end - << " for sample " << region->sampleId); + << " for sample " << *region->sampleId); } #endif if (!region->flexAmpEG) { @@ -891,13 +891,13 @@ void sfz::Voice::fillWithGenerator(AudioSpan buffer) noexcept const auto leftSpan = buffer.getSpan(0); const auto rightSpan = buffer.getSpan(1); - if (region->sampleId.filename() == "*noise") { + if (region->sampleId->filename() == "*noise") { auto gen = [&]() { return uniformNoiseDist(Random::randomGenerator); }; absl::c_generate(leftSpan, gen); absl::c_generate(rightSpan, gen); - } else if (region->sampleId.filename() == "*gnoise") { + } else if (region->sampleId->filename() == "*gnoise") { // You need to wrap in a lambda, otherwise generate will // make a copy of the gaussian distribution *along with its state* // leading to periodic behavior.... @@ -1092,10 +1092,11 @@ void sfz::Voice::updateLoopInformation() noexcept if (!region->shouldLoop()) return; const auto& info = currentPromise->information; + const auto factor = resources.filePool.getOversamplingFactor(); const auto rate = info.sampleRate; - loop.end = static_cast(info.loopEnd); - loop.start = static_cast(info.loopBegin); + loop.end = static_cast(region->loopEnd(factor)); + loop.start = static_cast(region->loopStart(factor)); loop.size = loop.end + 1 - loop.start; loop.xfSize = static_cast(lroundPositive(region->loopCrossfade * rate)); loop.xfOutStart = loop.end + 1 - loop.xfSize; diff --git a/src/sfizz/sfizz_wrapper.cpp b/src/sfizz/sfizz_wrapper.cpp index 3e103b2eb..8dffaf6a8 100644 --- a/src/sfizz/sfizz_wrapper.cpp +++ b/src/sfizz/sfizz_wrapper.cpp @@ -21,55 +21,55 @@ sfizz_synth_t* sfizz_create_synth() bool sfizz_load_file(sfizz_synth_t* synth, const char* path) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->loadSfzFile(path); } bool sfizz_load_string(sfizz_synth_t* synth, const char* path, const char* text) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->loadSfzString(path, text); } bool sfizz_load_scala_file(sfizz_synth_t* synth, const char* path) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->loadScalaFile(path); } bool sfizz_load_scala_string(sfizz_synth_t* synth, const char* text) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->loadScalaString(text); } void sfizz_set_scala_root_key(sfizz_synth_t* synth, int root_key) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->setScalaRootKey(root_key); } int sfizz_get_scala_root_key(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getScalaRootKey(); } void sfizz_set_tuning_frequency(sfizz_synth_t* synth, float frequency) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->setTuningFrequency(frequency); } float sfizz_get_tuning_frequency(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getTuningFrequency(); } void sfizz_load_stretch_tuning_by_ratio(sfizz_synth_t* synth, float ratio) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->loadStretchTuningByRatio(ratio); } @@ -80,105 +80,105 @@ void sfizz_free(sfizz_synth_t* synth) int sfizz_get_num_regions(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getNumRegions(); } int sfizz_get_num_groups(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getNumGroups(); } int sfizz_get_num_masters(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getNumMasters(); } int sfizz_get_num_curves(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getNumCurves(); } char* sfizz_export_midnam(sfizz_synth_t* synth, const char* model) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return strdup(self->exportMidnam(model ? model : "").c_str()); } size_t sfizz_get_num_preloaded_samples(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getNumPreloadedSamples(); } int sfizz_get_num_active_voices(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getNumActiveVoices(); } void sfizz_set_samples_per_block(sfizz_synth_t* synth, int samples_per_block) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->setSamplesPerBlock(samples_per_block); } void sfizz_set_sample_rate(sfizz_synth_t* synth, float sample_rate) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->setSampleRate(sample_rate); } void sfizz_send_note_on(sfizz_synth_t* synth, int delay, int note_number, char velocity) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->noteOn(delay, note_number, velocity); } void sfizz_send_note_off(sfizz_synth_t* synth, int delay, int note_number, char velocity) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->noteOff(delay, note_number, velocity); } void sfizz_send_cc(sfizz_synth_t* synth, int delay, int cc_number, char cc_value) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->cc(delay, cc_number, cc_value); } void sfizz_send_hdcc(sfizz_synth_t* synth, int delay, int cc_number, float norm_value) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->hdcc(delay, cc_number, norm_value); } void sfizz_send_pitch_wheel(sfizz_synth_t* synth, int delay, int pitch) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->pitchWheel(delay, pitch); } void sfizz_send_aftertouch(sfizz_synth_t* synth, int delay, char aftertouch) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->aftertouch(delay, aftertouch); } void sfizz_send_tempo(sfizz_synth_t* synth, int delay, float seconds_per_quarter) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->tempo(delay, seconds_per_quarter); } void sfizz_send_time_signature(sfizz_synth_t* synth, int delay, int beats_per_bar, int beat_unit) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->timeSignature(delay, beats_per_bar, beat_unit); } void sfizz_send_time_position(sfizz_synth_t* synth, int delay, int bar, float bar_beat) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->timePosition(delay, bar, bar_beat); } void sfizz_send_playback_state(sfizz_synth_t* synth, int delay, int playback_state) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->playbackState(delay, playback_state); } void sfizz_render_block(sfizz_synth_t* synth, float** channels, int num_channels, int num_frames) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); // Only stereo output is supported for now ASSERT(num_channels == 2); UNUSED(num_channels); @@ -187,24 +187,24 @@ void sfizz_render_block(sfizz_synth_t* synth, float** channels, int num_channels unsigned int sfizz_get_preload_size(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getPreloadSize(); } void sfizz_set_preload_size(sfizz_synth_t* synth, unsigned int preload_size) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->setPreloadSize(preload_size); } sfizz_oversampling_factor_t sfizz_get_oversampling_factor(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return static_cast(self->getOversamplingFactor()); } bool sfizz_set_oversampling_factor(sfizz_synth_t* synth, sfizz_oversampling_factor_t oversampling) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); using sfz::Oversampling; switch(oversampling) { @@ -227,67 +227,67 @@ bool sfizz_set_oversampling_factor(sfizz_synth_t* synth, sfizz_oversampling_fact int sfizz_get_sample_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getSampleQuality(static_cast(mode)); } void sfizz_set_sample_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode, int quality) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->setSampleQuality(static_cast(mode), quality); } void sfizz_set_volume(sfizz_synth_t* synth, float volume) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->setVolume(volume); } float sfizz_get_volume(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getVolume(); } void sfizz_set_num_voices(sfizz_synth_t* synth, int num_voices) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->setNumVoices(num_voices); } int sfizz_get_num_voices(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getNumVoices(); } int sfizz_get_num_buffers(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getAllocatedBuffers(); } int sfizz_get_num_bytes(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getAllocatedBytes(); } void sfizz_enable_freewheeling(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->enableFreeWheeling(); } void sfizz_disable_freewheeling(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->disableFreeWheeling(); } char* sfizz_get_unknown_opcodes(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); const auto unknownOpcodes = self->getUnknownOpcodes(); size_t totalLength = 0; for (auto& opcode: unknownOpcodes) @@ -309,61 +309,61 @@ char* sfizz_get_unknown_opcodes(sfizz_synth_t* synth) bool sfizz_should_reload_file(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->shouldReloadFile(); } bool sfizz_should_reload_scala(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->shouldReloadScala(); } void sfizz_enable_logging(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->enableLogging(); } void sfizz_set_logging_prefix(sfizz_synth_t* synth, const char* prefix) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->setLoggingPrefix(prefix); } void sfizz_disable_logging(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->disableLogging(); } void sfizz_all_sound_off(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->allSoundOff(); } void sfizz_add_external_definitions(sfizz_synth_t* synth, const char* id, const char* value) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->getParser().addExternalDefinition(id, value); } void sfizz_clear_external_definitions(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); self->getParser().clearExternalDefinitions(); } unsigned int sfizz_get_num_key_labels(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getKeyLabels().size(); } int sfizz_get_key_label_number(sfizz_synth_t* synth, int label_index) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); const auto keyLabels = self->getKeyLabels(); if (label_index < 0) return SFIZZ_OUT_OF_BOUNDS_LABEL_INDEX; @@ -381,7 +381,7 @@ int sfizz_get_key_label_number(sfizz_synth_t* synth, int label_index) const char * sfizz_get_key_label_text(sfizz_synth_t* synth, int label_index) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); const auto keyLabels = self->getKeyLabels(); if (label_index < 0) return NULL; @@ -394,13 +394,13 @@ const char * sfizz_get_key_label_text(sfizz_synth_t* synth, int label_index) unsigned int sfizz_get_num_cc_labels(sfizz_synth_t* synth) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); return self->getCCLabels().size(); } int sfizz_get_cc_label_number(sfizz_synth_t* synth, int label_index) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); const auto ccLabels = self->getCCLabels(); if (label_index < 0) return SFIZZ_OUT_OF_BOUNDS_LABEL_INDEX; @@ -418,7 +418,7 @@ int sfizz_get_cc_label_number(sfizz_synth_t* synth, int label_index) const char * sfizz_get_cc_label_text(sfizz_synth_t* synth, int label_index) { - auto self = reinterpret_cast(synth); + auto* self = reinterpret_cast(synth); const auto ccLabels = self->getCCLabels(); if (label_index < 0) return NULL; diff --git a/src/sfizz/simd/HelpersAVX.cpp b/src/sfizz/simd/HelpersAVX.cpp index 8fff4dc87..3b9198272 100644 --- a/src/sfizz/simd/HelpersAVX.cpp +++ b/src/sfizz/simd/HelpersAVX.cpp @@ -18,7 +18,7 @@ constexpr unsigned ByteAlignment = TypeAlignment * sizeof(Type); void gain1AVX(float gain, const float* input, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_AVX const auto* lastAligned = prevAligned(sentinel); @@ -38,7 +38,7 @@ void gain1AVX(float gain, const float* input, float* output, unsigned size) noex void gainAVX(const float* gain, const float* input, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_AVX const auto* lastAligned = prevAligned(sentinel); diff --git a/src/sfizz/simd/HelpersSSE.cpp b/src/sfizz/simd/HelpersSSE.cpp index 4f8daf25b..3a9d65c4a 100644 --- a/src/sfizz/simd/HelpersSSE.cpp +++ b/src/sfizz/simd/HelpersSSE.cpp @@ -19,7 +19,7 @@ constexpr unsigned ByteAlignment = TypeAlignment * sizeof(Type); void readInterleavedSSE(const float* input, float* outputLeft, float* outputRight, unsigned inputSize) noexcept { - const auto sentinel = input + inputSize - 1; + const auto* sentinel = input + inputSize - 1; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(input + inputSize - TypeAlignment); @@ -56,7 +56,7 @@ void readInterleavedSSE(const float* input, float* outputLeft, float* outputRigh void writeInterleavedSSE(const float* inputLeft, const float* inputRight, float* output, unsigned outputSize) noexcept { - const auto sentinel = output + outputSize - 1; + const auto* sentinel = output + outputSize - 1; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(output + outputSize - TypeAlignment); @@ -84,7 +84,7 @@ void writeInterleavedSSE(const float* inputLeft, const float* inputRight, float* void gain1SSE(float gain, const float* input, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -104,7 +104,7 @@ void gain1SSE(float gain, const float* input, float* output, unsigned size) noex void gainSSE(const float* gain, const float* input, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -123,7 +123,7 @@ void gainSSE(const float* gain, const float* input, float* output, unsigned size void divideSSE(const float* input, const float* divisor, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -142,7 +142,7 @@ void divideSSE(const float* input, const float* divisor, float* output, unsigned void multiplyAddSSE(const float* gain, const float* input, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -163,7 +163,7 @@ void multiplyAddSSE(const float* gain, const float* input, float* output, unsign void multiplyAdd1SSE(float gain, const float* input, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -185,7 +185,7 @@ void multiplyAdd1SSE(float gain, const float* input, float* output, unsigned siz void multiplyMulSSE(const float* gain, const float* input, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -206,7 +206,7 @@ void multiplyMulSSE(const float* gain, const float* input, float* output, unsign void multiplyMul1SSE(float gain, const float* input, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -228,7 +228,7 @@ void multiplyMul1SSE(float gain, const float* input, float* output, unsigned siz float linearRampSSE(float* output, float start, float step, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -257,7 +257,7 @@ float linearRampSSE(float* output, float start, float step, unsigned size) noexc float multiplicativeRampSSE(float* output, float start, float step, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -286,7 +286,7 @@ float multiplicativeRampSSE(float* output, float start, float step, unsigned siz void addSSE(const float* input, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -305,7 +305,7 @@ void addSSE(const float* input, float* output, unsigned size) noexcept void add1SSE(float value, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -325,7 +325,7 @@ void add1SSE(float value, float* output, unsigned size) noexcept void subtractSSE(const float* input, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -344,7 +344,7 @@ void subtractSSE(const float* input, float* output, unsigned size) noexcept void subtract1SSE(float value, float* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -365,7 +365,7 @@ void subtract1SSE(float value, float* output, unsigned size) noexcept void copySSE(const float* input, float* output, unsigned size) noexcept { // The sentinel is the input here - const auto sentinel = input + size; + const auto* sentinel = input + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -383,7 +383,7 @@ void copySSE(const float* input, float* output, unsigned size) noexcept float meanSSE(const float* vector, unsigned size) noexcept { - const auto sentinel = vector + size; + const auto* sentinel = vector + size; float result { 0.0f }; if (size == 0) @@ -415,7 +415,7 @@ float meanSSE(const float* vector, unsigned size) noexcept float sumSquaresSSE(const float* vector, unsigned size) noexcept { - const auto sentinel = vector + size; + const auto* sentinel = vector + size; float result { 0.0f }; if (size == 0) @@ -455,7 +455,7 @@ void cumsumSSE(const float* input, float* output, unsigned size) noexcept if (size == 0) return; - const auto sentinel = output + size; + const auto* sentinel = output + size; *output++ = *input++; #if SFIZZ_HAVE_SSE2 @@ -488,7 +488,7 @@ void diffSSE(const float* input, float* output, unsigned size) noexcept if (size == 0) return; - const auto sentinel = output + size; + const auto* sentinel = output + size; *output++ = *input++; #if SFIZZ_HAVE_SSE2 @@ -521,7 +521,7 @@ void clampAllSSE(float* input, float low, float high, unsigned size) noexcept if (size == 0) return; - const auto sentinel = input + size; + const auto* sentinel = input + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); @@ -555,7 +555,7 @@ bool allWithinSSE(const float* input, float low, float high, unsigned size) noex if (low > high) std::swap(low, high); - const auto sentinel = input + size; + const auto* sentinel = input + size; #if SFIZZ_HAVE_SSE2 const auto* lastAligned = prevAligned(sentinel); diff --git a/src/sfizz/simd/HelpersScalar.h b/src/sfizz/simd/HelpersScalar.h index 33c4af3f1..83b378670 100644 --- a/src/sfizz/simd/HelpersScalar.h +++ b/src/sfizz/simd/HelpersScalar.h @@ -10,7 +10,7 @@ template inline void readInterleavedScalar(const T* input, T* outputLeft, T* outputRight, unsigned inputSize) noexcept { - const auto sentinel = input + inputSize - 1; + const auto* sentinel = input + inputSize - 1; while (input < sentinel) { *outputLeft++ = *input++; *outputRight++ = *input++; @@ -20,7 +20,7 @@ inline void readInterleavedScalar(const T* input, T* outputLeft, T* outputRight, template inline void writeInterleavedScalar(const T* inputLeft, const T* inputRight, T* output, unsigned outputSize) noexcept { - const auto sentinel = output + outputSize - 1; + const auto* sentinel = output + outputSize - 1; while (output < sentinel) { *output++ = *inputLeft++; *output++ = *inputRight++; @@ -30,7 +30,7 @@ inline void writeInterleavedScalar(const T* inputLeft, const T* inputRight, T* o template inline void gain1Scalar(T gain, const T* input, T* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) *output++ = gain * (*input++); } @@ -38,7 +38,7 @@ inline void gain1Scalar(T gain, const T* input, T* output, unsigned size) noexce template inline void gainScalar(const T* gain, const T* input, T* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) *output++ = (*gain++) * (*input++); } @@ -46,7 +46,7 @@ inline void gainScalar(const T* gain, const T* input, T* output, unsigned size) template inline void divideScalar(const T* input, const T* divisor, T* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) *output++ = (*input++) / (*divisor++); } @@ -54,7 +54,7 @@ inline void divideScalar(const T* input, const T* divisor, T* output, unsigned s template inline void multiplyAddScalar(const T* gain, const T* input, T* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) *output++ += (*gain++) * (*input++); } @@ -62,7 +62,7 @@ inline void multiplyAddScalar(const T* gain, const T* input, T* output, unsigned template inline void multiplyAdd1Scalar(T gain, const T* input, T* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) *output++ += gain * (*input++); } @@ -70,7 +70,7 @@ inline void multiplyAdd1Scalar(T gain, const T* input, T* output, unsigned size) template inline void multiplyMulScalar(const T* gain, const T* input, T* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) *output++ *= (*gain++) * (*input++); } @@ -78,7 +78,7 @@ inline void multiplyMulScalar(const T* gain, const T* input, T* output, unsigned template inline void multiplyMul1Scalar(T gain, const T* input, T* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) *output++ *= gain * (*input++); } @@ -86,7 +86,7 @@ inline void multiplyMul1Scalar(T gain, const T* input, T* output, unsigned size) template T linearRampScalar(T* output, T start, T step, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) { *output++ = start; start += step; @@ -97,7 +97,7 @@ T linearRampScalar(T* output, T start, T step, unsigned size) noexcept template T multiplicativeRampScalar(T* output, T start, T step, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) { *output++ = start; start *= step; @@ -108,7 +108,7 @@ T multiplicativeRampScalar(T* output, T start, T step, unsigned size) noexcept template inline void addScalar(const T* input, T* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) *output++ += *input++; } @@ -116,7 +116,7 @@ inline void addScalar(const T* input, T* output, unsigned size) noexcept template inline void add1Scalar(T value, T* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) *output++ += value; } @@ -124,7 +124,7 @@ inline void add1Scalar(T value, T* output, unsigned size) noexcept template inline void subtractScalar(const T* input, T* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) *output++ -= *input++; } @@ -132,7 +132,7 @@ inline void subtractScalar(const T* input, T* output, unsigned size) noexcept template inline void subtract1Scalar(T value, T* output, unsigned size) noexcept { - const auto sentinel = output + size; + const auto* sentinel = output + size; while (output < sentinel) *output++ -= value; } @@ -150,7 +150,7 @@ T meanScalar(const T* vector, unsigned size) noexcept if (size == 0) return result; - const auto sentinel = vector + size; + const auto* sentinel = vector + size; while (vector < sentinel) result += *vector++; @@ -164,7 +164,7 @@ T sumSquaresScalar(const T* vector, unsigned size) noexcept if (size == 0) return result; - const auto sentinel = vector + size; + const auto* sentinel = vector + size; while (vector < sentinel) { result += (*vector) * (*vector); vector++; @@ -179,7 +179,7 @@ void cumsumScalar(const T* input, T* output, unsigned size) noexcept if (size == 0) return; - const auto sentinel = output + size; + const auto* sentinel = output + size; *output++ = *input++; while (output < sentinel) { @@ -194,7 +194,7 @@ void diffScalar(const T* input, T* output, unsigned size) noexcept if (size == 0) return; - const auto sentinel = output + size; + const auto* sentinel = output + size; *output++ = *input++; while (output < sentinel) { @@ -209,7 +209,7 @@ void clampAllScalar(T* input, T low, T high, unsigned size ) noexcept if (size == 0) return; - const auto sentinel = input + size; + const auto* sentinel = input + size; while (input < sentinel) { const float clampedAbove = *input > high ? high : *input; *input = clampedAbove < low ? low : clampedAbove; @@ -226,7 +226,7 @@ bool allWithinScalar(const T* input, T low, T high, unsigned size ) noexcept if (low > high) std::swap(low, high); - const auto sentinel = input + size; + const auto* sentinel = input + size; while (input < sentinel) { if (*input < low || *input > high) return false; diff --git a/tests/FilesT.cpp b/tests/FilesT.cpp index 333602391..5f524b647 100644 --- a/tests/FilesT.cpp +++ b/tests/FilesT.cpp @@ -23,7 +23,7 @@ TEST_CASE("[Files] Single region (regions_one.sfz)") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Regions/regions_one.sfz"); REQUIRE(synth.getNumRegions() == 1); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "dummy.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "dummy.wav"); } @@ -32,9 +32,9 @@ TEST_CASE("[Files] Multiple regions (regions_many.sfz)") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Regions/regions_many.sfz"); REQUIRE(synth.getNumRegions() == 3); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "dummy.wav"); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == "dummy.1.wav"); - REQUIRE(synth.getRegionView(2)->sampleId.filename() == "dummy.2.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "dummy.wav"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == "dummy.1.wav"); + REQUIRE(synth.getRegionView(2)->sampleId->filename() == "dummy.2.wav"); } TEST_CASE("[Files] Basic opcodes (regions_opcodes.sfz)") @@ -58,8 +58,8 @@ TEST_CASE("[Files] (regions_bad.sfz)") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Regions/regions_bad.sfz"); REQUIRE(synth.getNumRegions() == 2); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "dummy.wav"); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == "dummy.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "dummy.wav"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == "dummy.wav"); } TEST_CASE("[Files] Local include") @@ -67,7 +67,7 @@ TEST_CASE("[Files] Local include") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/root_local.sfz"); REQUIRE(synth.getNumRegions() == 1); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "dummy.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "dummy.wav"); } TEST_CASE("[Files] Multiple includes") @@ -75,8 +75,8 @@ TEST_CASE("[Files] Multiple includes") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/multiple_includes.sfz"); REQUIRE(synth.getNumRegions() == 2); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "dummy.wav"); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == "dummy2.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "dummy.wav"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == "dummy2.wav"); } TEST_CASE("[Files] Multiple includes with comments") @@ -84,8 +84,8 @@ TEST_CASE("[Files] Multiple includes with comments") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/multiple_includes_with_comments.sfz"); REQUIRE(synth.getNumRegions() == 2); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "dummy.wav"); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == "dummy2.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "dummy.wav"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == "dummy2.wav"); } TEST_CASE("[Files] Subdir include") @@ -93,7 +93,7 @@ TEST_CASE("[Files] Subdir include") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/root_subdir.sfz"); REQUIRE(synth.getNumRegions() == 1); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "dummy_subdir.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "dummy_subdir.wav"); } TEST_CASE("[Files] Subdir include Win") @@ -101,7 +101,7 @@ TEST_CASE("[Files] Subdir include Win") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/root_subdir_win.sfz"); REQUIRE(synth.getNumRegions() == 1); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "dummy_subdir.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "dummy_subdir.wav"); } TEST_CASE("[Files] Recursive include (with include guard)") @@ -111,8 +111,8 @@ TEST_CASE("[Files] Recursive include (with include guard)") parser.setRecursiveIncludeGuardEnabled(true); synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/root_recursive.sfz"); REQUIRE(synth.getNumRegions() == 2); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "dummy_recursive2.wav"); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == "dummy_recursive1.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "dummy_recursive2.wav"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == "dummy_recursive1.wav"); } TEST_CASE("[Files] Include loops (with include guard)") @@ -122,8 +122,8 @@ TEST_CASE("[Files] Include loops (with include guard)") parser.setRecursiveIncludeGuardEnabled(true); synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Includes/root_loop.sfz"); REQUIRE(synth.getNumRegions() == 2); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "dummy_loop2.wav"); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == "dummy_loop1.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "dummy_loop2.wav"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == "dummy_loop1.wav"); } TEST_CASE("[Files] Define test") @@ -209,28 +209,28 @@ TEST_CASE("[Files] Full hierarchy with antislashes") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/basic_hierarchy.sfz"); REQUIRE(synth.getNumRegions() == 8); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "Regions/dummy.wav"); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == "Regions/dummy.1.wav"); - REQUIRE(synth.getRegionView(2)->sampleId.filename() == "Regions/dummy.wav"); - REQUIRE(synth.getRegionView(3)->sampleId.filename() == "Regions/dummy.1.wav"); - REQUIRE(synth.getRegionView(4)->sampleId.filename() == "Regions/dummy.wav"); - REQUIRE(synth.getRegionView(5)->sampleId.filename() == "Regions/dummy.1.wav"); - REQUIRE(synth.getRegionView(6)->sampleId.filename() == "Regions/dummy.wav"); - REQUIRE(synth.getRegionView(7)->sampleId.filename() == "Regions/dummy.1.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "Regions/dummy.wav"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == "Regions/dummy.1.wav"); + REQUIRE(synth.getRegionView(2)->sampleId->filename() == "Regions/dummy.wav"); + REQUIRE(synth.getRegionView(3)->sampleId->filename() == "Regions/dummy.1.wav"); + REQUIRE(synth.getRegionView(4)->sampleId->filename() == "Regions/dummy.wav"); + REQUIRE(synth.getRegionView(5)->sampleId->filename() == "Regions/dummy.1.wav"); + REQUIRE(synth.getRegionView(6)->sampleId->filename() == "Regions/dummy.wav"); + REQUIRE(synth.getRegionView(7)->sampleId->filename() == "Regions/dummy.1.wav"); } { Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/basic_hierarchy_antislash.sfz"); REQUIRE(synth.getNumRegions() == 8); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "Regions/dummy.wav"); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == "Regions/dummy.1.wav"); - REQUIRE(synth.getRegionView(2)->sampleId.filename() == "Regions/dummy.wav"); - REQUIRE(synth.getRegionView(3)->sampleId.filename() == "Regions/dummy.1.wav"); - REQUIRE(synth.getRegionView(4)->sampleId.filename() == "Regions/dummy.wav"); - REQUIRE(synth.getRegionView(5)->sampleId.filename() == "Regions/dummy.1.wav"); - REQUIRE(synth.getRegionView(6)->sampleId.filename() == "Regions/dummy.wav"); - REQUIRE(synth.getRegionView(7)->sampleId.filename() == "Regions/dummy.1.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "Regions/dummy.wav"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == "Regions/dummy.1.wav"); + REQUIRE(synth.getRegionView(2)->sampleId->filename() == "Regions/dummy.wav"); + REQUIRE(synth.getRegionView(3)->sampleId->filename() == "Regions/dummy.1.wav"); + REQUIRE(synth.getRegionView(4)->sampleId->filename() == "Regions/dummy.wav"); + REQUIRE(synth.getRegionView(5)->sampleId->filename() == "Regions/dummy.1.wav"); + REQUIRE(synth.getRegionView(6)->sampleId->filename() == "Regions/dummy.wav"); + REQUIRE(synth.getRegionView(7)->sampleId->filename() == "Regions/dummy.1.wav"); } } @@ -249,10 +249,10 @@ TEST_CASE("[Files] Pizz basic") REQUIRE(synth.getRegionView(1)->randRange == Range(0.25, 0.5)); REQUIRE(synth.getRegionView(2)->randRange == Range(0.5, 0.75)); REQUIRE(synth.getRegionView(3)->randRange == Range(0.75, 1.0)); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == R"(../Samples/pizz/a0_vl4_rr1.wav)"); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == R"(../Samples/pizz/a0_vl4_rr2.wav)"); - REQUIRE(synth.getRegionView(2)->sampleId.filename() == R"(../Samples/pizz/a0_vl4_rr3.wav)"); - REQUIRE(synth.getRegionView(3)->sampleId.filename() == R"(../Samples/pizz/a0_vl4_rr4.wav)"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == R"(../Samples/pizz/a0_vl4_rr1.wav)"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == R"(../Samples/pizz/a0_vl4_rr2.wav)"); + REQUIRE(synth.getRegionView(2)->sampleId->filename() == R"(../Samples/pizz/a0_vl4_rr3.wav)"); + REQUIRE(synth.getRegionView(3)->sampleId->filename() == R"(../Samples/pizz/a0_vl4_rr4.wav)"); } TEST_CASE("[Files] Channels (channels.sfz)") @@ -260,9 +260,9 @@ TEST_CASE("[Files] Channels (channels.sfz)") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/channels.sfz"); REQUIRE(synth.getNumRegions() == 2); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "mono_sample.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "mono_sample.wav"); REQUIRE(!synth.getRegionView(0)->isStereo()); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == "stereo_sample.wav"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == "stereo_sample.wav"); REQUIRE(synth.getRegionView(1)->isStereo()); } @@ -277,7 +277,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") // generator only region = synth.getRegionView(regionNumber++); - REQUIRE(region->sampleId.filename() == "*sine"); + REQUIRE(region->sampleId->filename() == "*sine"); REQUIRE(!region->isStereo()); REQUIRE(region->isGenerator()); REQUIRE(region->isOscillator()); @@ -285,7 +285,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") // generator with multi region = synth.getRegionView(regionNumber++); - REQUIRE(region->sampleId.filename() == "*sine"); + REQUIRE(region->sampleId->filename() == "*sine"); REQUIRE(region->isStereo()); REQUIRE(region->isGenerator()); REQUIRE(region->isOscillator()); @@ -293,7 +293,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") // explicit wavetable region = synth.getRegionView(regionNumber++); - REQUIRE(region->sampleId.filename() == "ramp_wave.wav"); + REQUIRE(region->sampleId->filename() == "ramp_wave.wav"); REQUIRE(!region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(region->isOscillator()); @@ -301,7 +301,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") // explicit wavetable with multi region = synth.getRegionView(regionNumber++); - REQUIRE(region->sampleId.filename() == "ramp_wave.wav"); + REQUIRE(region->sampleId->filename() == "ramp_wave.wav"); REQUIRE(region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(region->isOscillator()); @@ -309,7 +309,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") // explicit disabled wavetable region = synth.getRegionView(regionNumber++); - REQUIRE(region->sampleId.filename() == "ramp_wave.wav"); + REQUIRE(region->sampleId->filename() == "ramp_wave.wav"); REQUIRE(!region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(!region->isOscillator()); @@ -317,7 +317,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") // explicit disabled wavetable with multi region = synth.getRegionView(regionNumber++); - REQUIRE(region->sampleId.filename() == "ramp_wave.wav"); + REQUIRE(region->sampleId->filename() == "ramp_wave.wav"); REQUIRE(!region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(!region->isOscillator()); @@ -325,7 +325,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") // implicit wavetable (sound file < 3000 frames) region = synth.getRegionView(regionNumber++); - REQUIRE(region->sampleId.filename() == "ramp_wave.wav"); + REQUIRE(region->sampleId->filename() == "ramp_wave.wav"); REQUIRE(!region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(region->isOscillator()); @@ -333,7 +333,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") // implicit non-wavetable (sound file >= 3000 frames) region = synth.getRegionView(regionNumber++); - REQUIRE(region->sampleId.filename() == "snare.wav"); + REQUIRE(region->sampleId->filename() == "snare.wav"); REQUIRE(!region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(!region->isOscillator()); @@ -341,7 +341,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") // generator with multi=1 (single) region = synth.getRegionView(regionNumber++); - REQUIRE(region->sampleId.filename() == "*sine"); + REQUIRE(region->sampleId->filename() == "*sine"); REQUIRE(!region->isStereo()); REQUIRE(region->isGenerator()); REQUIRE(region->isOscillator()); @@ -349,7 +349,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") // generator with multi=2 (ring modulation) region = synth.getRegionView(regionNumber++); - REQUIRE(region->sampleId.filename() == "*sine"); + REQUIRE(region->sampleId->filename() == "*sine"); REQUIRE(!region->isStereo()); REQUIRE(region->isGenerator()); REQUIRE(region->isOscillator()); @@ -424,7 +424,7 @@ TEST_CASE("[Files] Specific bug: relative path with backslashes") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/SpecificBugs/win_backslashes.sfz"); REQUIRE(synth.getNumRegions() == 1); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == R"(Xylo/Subfolder/closedhat.wav)"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == R"(Xylo/Subfolder/closedhat.wav)"); } TEST_CASE("[Files] Default path") @@ -432,10 +432,10 @@ TEST_CASE("[Files] Default path") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/default_path.sfz"); REQUIRE(synth.getNumRegions() == 4); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == R"(DefaultPath/SubPath1/sample1.wav)"); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == R"(DefaultPath/SubPath2/sample2.wav)"); - REQUIRE(synth.getRegionView(2)->sampleId.filename() == R"(DefaultPath/SubPath1/sample1.wav)"); - REQUIRE(synth.getRegionView(3)->sampleId.filename() == R"(DefaultPath/SubPath2/sample2.wav)"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == R"(DefaultPath/SubPath1/sample1.wav)"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == R"(DefaultPath/SubPath2/sample2.wav)"); + REQUIRE(synth.getRegionView(2)->sampleId->filename() == R"(DefaultPath/SubPath1/sample1.wav)"); + REQUIRE(synth.getRegionView(3)->sampleId->filename() == R"(DefaultPath/SubPath2/sample2.wav)"); } TEST_CASE("[Files] Default path reset when calling loadSfzFile again") @@ -445,7 +445,7 @@ TEST_CASE("[Files] Default path reset when calling loadSfzFile again") REQUIRE(synth.getNumRegions() == 4); synth.loadSfzFile(fs::current_path() / "tests/TestFiles/default_path_reset.sfz"); REQUIRE(synth.getNumRegions() == 1); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == R"(DefaultPath/SubPath2/sample2.wav)"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == R"(DefaultPath/SubPath2/sample2.wav)"); } TEST_CASE("[Files] Default path is ignored for generators") @@ -453,7 +453,7 @@ TEST_CASE("[Files] Default path is ignored for generators") Synth synth; synth.loadSfzFile(fs::current_path() / "tests/TestFiles/default_path_generator.sfz"); REQUIRE(synth.getNumRegions() == 1); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == R"(*sine)"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == R"(*sine)"); } TEST_CASE("[Files] Set CC applies properly") @@ -616,10 +616,10 @@ TEST_CASE("[Files] Case sentitiveness") Synth synth; synth.loadSfzFile(sfzFilePath); REQUIRE(synth.getNumRegions() == 4); - REQUIRE(synth.getRegionView(0)->sampleId.filename() == "dummy1.wav"); - REQUIRE(synth.getRegionView(1)->sampleId.filename() == "Regions/dummy.wav"); - REQUIRE(synth.getRegionView(2)->sampleId.filename() == "Regions/dummy.wav"); - REQUIRE(synth.getRegionView(3)->sampleId.filename() == "Regions/dummy.wav"); + REQUIRE(synth.getRegionView(0)->sampleId->filename() == "dummy1.wav"); + REQUIRE(synth.getRegionView(1)->sampleId->filename() == "Regions/dummy.wav"); + REQUIRE(synth.getRegionView(2)->sampleId->filename() == "Regions/dummy.wav"); + REQUIRE(synth.getRegionView(3)->sampleId->filename() == "Regions/dummy.wav"); } } diff --git a/tests/RegionT.cpp b/tests/RegionT.cpp index 945ae0bfc..f15bd2860 100644 --- a/tests/RegionT.cpp +++ b/tests/RegionT.cpp @@ -23,18 +23,18 @@ TEST_CASE("[Region] Parsing opcodes") SECTION("sample") { - REQUIRE(region.sampleId.filename() == ""); + REQUIRE(region.sampleId->filename() == ""); region.parseOpcode({ "sample", "dummy.wav" }); - REQUIRE(region.sampleId.filename() == "dummy.wav"); + REQUIRE(region.sampleId->filename() == "dummy.wav"); } SECTION("direction") { - REQUIRE(!region.sampleId.isReverse()); + REQUIRE(!region.sampleId->isReverse()); region.parseOpcode({ "direction", "reverse" }); - REQUIRE(region.sampleId.isReverse()); + REQUIRE(region.sampleId->isReverse()); region.parseOpcode({ "direction", "forward" }); - REQUIRE(!region.sampleId.isReverse()); + REQUIRE(!region.sampleId->isReverse()); } SECTION("delay") diff --git a/tests/SynthT.cpp b/tests/SynthT.cpp index b7a7d1af4..868cd7cae 100644 --- a/tests/SynthT.cpp +++ b/tests/SynthT.cpp @@ -698,13 +698,13 @@ TEST_CASE("[Synth] Release (basic behavior with sample)") )"); synth.noteOn(0, 62, 85); REQUIRE( numPlayingVoices(synth) == 1 ); - REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId.filename() == "*sine" ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "*sine" ); synth.noteOff(0, 62, 85); REQUIRE( numPlayingVoices(synth) == 1 ); - REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId.filename() == "closedhat.wav" ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "closedhat.wav" ); synth.renderBlock(buffer); REQUIRE( numPlayingVoices(synth) == 1 ); - REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId.filename() == "closedhat.wav" ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "closedhat.wav" ); } TEST_CASE("[Synth] Release key (basic behavior with sample)") @@ -720,7 +720,7 @@ TEST_CASE("[Synth] Release key (basic behavior with sample)") REQUIRE( numPlayingVoices(synth) == 1 ); synth.renderBlock(buffer); REQUIRE( numPlayingVoices(synth) == 1 ); - REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId.filename() == "closedhat.wav" ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "closedhat.wav" ); } TEST_CASE("[Synth] Release key (pedal)") @@ -1338,15 +1338,15 @@ TEST_CASE("[Synth] Off by with CC switches") )"); synth.noteOn(0, 60, 85); REQUIRE( numPlayingVoices(synth) == 1 ); - REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId.filename() == "*saw" ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "*saw" ); synth.cc(0, 4, 127); synth.noteOn(0, 60, 85); REQUIRE( numPlayingVoices(synth) == 1 ); - REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId.filename() == "*triangle" ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "*triangle" ); synth.cc(0, 4, 0); synth.noteOn(0, 60, 85); REQUIRE( numPlayingVoices(synth) == 1 ); - REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId.filename() == "*saw" ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "*saw" ); } TEST_CASE("[Synth] Initial values of CC") diff --git a/vst/CMakeLists.txt b/vst/CMakeLists.txt index cddf56b2c..b5db24958 100644 --- a/vst/CMakeLists.txt +++ b/vst/CMakeLists.txt @@ -118,9 +118,12 @@ endif() # Installation if (NOT MSVC) - install (DIRECTORY "${PROJECT_BINARY_DIR}/${VSTPLUGIN_BUNDLE_NAME}" + install(DIRECTORY "${PROJECT_BINARY_DIR}/${VSTPLUGIN_BUNDLE_NAME}" DESTINATION "${VSTPLUGIN_INSTALL_DIR}" COMPONENT "vst") + bundle_dylibs(vst + "${VSTPLUGIN_INSTALL_DIR}/${VSTPLUGIN_BUNDLE_NAME}/Contents/MacOS/sfizz" + COMPONENT "vst") endif() # --- Audio Unit wrapper --- # @@ -252,7 +255,7 @@ elseif(SFIZZ_AU) DESTINATION "${PROJECT_BINARY_DIR}/${AUPLUGIN_BUNDLE_NAME}") # Add the resource fork - if (FALSE) # optional, disabled because broken on CI + if (TRUE) execute_process(COMMAND "xcrun" "--find" "Rez" OUTPUT_VARIABLE OSX_REZ_COMMAND OUTPUT_STRIP_TRAILING_WHITESPACE) file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include") @@ -275,13 +278,6 @@ elseif(SFIZZ_AU) "${VST3SDK_BASEDIR}/public.sdk/source/vst/auwrapper/auresource.r") endif() - # Copy VST3 in the bundle - add_custom_command(TARGET ${VSTPLUGIN_PRJ_NAME} POST_BUILD COMMAND - "${CMAKE_COMMAND}" "-E" - "copy_directory" - "${PROJECT_BINARY_DIR}/${VSTPLUGIN_BUNDLE_NAME}" - "${PROJECT_BINARY_DIR}/${AUPLUGIN_BUNDLE_NAME}/Contents/Resources/plugin.vst3") - if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") target_compile_options(${AUPLUGIN_PRJ_NAME} PRIVATE "-Wno-extra" @@ -300,5 +296,14 @@ elseif(SFIZZ_AU) install(DIRECTORY "${PROJECT_BINARY_DIR}/${AUPLUGIN_BUNDLE_NAME}" DESTINATION "${AUPLUGIN_INSTALL_DIR}" COMPONENT "au") + install(DIRECTORY "${PROJECT_BINARY_DIR}/${VSTPLUGIN_BUNDLE_NAME}/" + DESTINATION "${AUPLUGIN_INSTALL_DIR}/${AUPLUGIN_BUNDLE_NAME}/Contents/Resources/plugin.vst3" + COMPONENT "au") + bundle_dylibs(au + "${AUPLUGIN_INSTALL_DIR}/${AUPLUGIN_BUNDLE_NAME}/Contents/MacOS/sfizz" + COMPONENT "au") + bundle_dylibs(au-vst + "${AUPLUGIN_INSTALL_DIR}/${AUPLUGIN_BUNDLE_NAME}/Contents/Resources/plugin.vst3/Contents/MacOS/sfizz" + COMPONENT "au") endif() endif() diff --git a/vst/external/VST_SDK/VST3_SDK/public.sdk b/vst/external/VST_SDK/VST3_SDK/public.sdk index ff836e8c0..b63097ebc 160000 --- a/vst/external/VST_SDK/VST3_SDK/public.sdk +++ b/vst/external/VST_SDK/VST3_SDK/public.sdk @@ -1 +1 @@ -Subproject commit ff836e8c02bd28c902f5e3e75353a86f65008a77 +Subproject commit b63097ebce2105845aa97d04808fca4dfd51307c