Cosmetics
This commit is contained in:
parent
8e8ea4f420
commit
5fd7cab909
37 changed files with 1428 additions and 1527 deletions
|
|
@ -1,11 +1,10 @@
|
||||||
#include "Globals.h"
|
|
||||||
#include "SIMDHelpers.h"
|
|
||||||
#include "Helpers.h"
|
|
||||||
#include "ADSREnvelope.h"
|
#include "ADSREnvelope.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "Helpers.h"
|
||||||
|
#include "SIMDHelpers.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz {
|
||||||
{
|
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
void ADSREnvelope<Type>::reset(int attack, int release, Type sustain, int delay, int decay, int hold, Type start, Type depth) noexcept
|
void ADSREnvelope<Type>::reset(int attack, int release, Type sustain, int delay, int decay, int hold, Type start, Type depth) noexcept
|
||||||
|
|
@ -35,14 +34,12 @@ void ADSREnvelope<Type>::reset(int attack, int release, Type sustain, int delay,
|
||||||
template <class Type>
|
template <class Type>
|
||||||
Type ADSREnvelope<Type>::getNextValue() noexcept
|
Type ADSREnvelope<Type>::getNextValue() noexcept
|
||||||
{
|
{
|
||||||
if (shouldRelease && releaseDelay-- == 0)
|
if (shouldRelease && releaseDelay-- == 0) {
|
||||||
{
|
|
||||||
currentState = State::Release;
|
currentState = State::Release;
|
||||||
step = std::exp((std::log(config::virtuallyZero) - std::log(currentValue)) / (release > 0 ? release : 1));
|
step = std::exp((std::log(config::virtuallyZero) - std::log(currentValue)) / (release > 0 ? release : 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(currentState)
|
switch (currentState) {
|
||||||
{
|
|
||||||
case State::Delay:
|
case State::Delay:
|
||||||
if (delay-- > 0)
|
if (delay-- > 0)
|
||||||
return start;
|
return start;
|
||||||
|
|
@ -51,8 +48,7 @@ Type ADSREnvelope<Type>::getNextValue() noexcept
|
||||||
step = (1.0 - currentValue) / (attack > 0 ? attack : 1);
|
step = (1.0 - currentValue) / (attack > 0 ? attack : 1);
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case State::Attack:
|
case State::Attack:
|
||||||
if (attack-- > 0)
|
if (attack-- > 0) {
|
||||||
{
|
|
||||||
currentValue += step;
|
currentValue += step;
|
||||||
return currentValue;
|
return currentValue;
|
||||||
}
|
}
|
||||||
|
|
@ -68,8 +64,7 @@ Type ADSREnvelope<Type>::getNextValue() noexcept
|
||||||
currentState = State::Decay;
|
currentState = State::Decay;
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case State::Decay:
|
case State::Decay:
|
||||||
if (decay-- > 0)
|
if (decay-- > 0) {
|
||||||
{
|
|
||||||
currentValue *= step;
|
currentValue *= step;
|
||||||
return currentValue;
|
return currentValue;
|
||||||
}
|
}
|
||||||
|
|
@ -80,8 +75,7 @@ Type ADSREnvelope<Type>::getNextValue() noexcept
|
||||||
case State::Sustain:
|
case State::Sustain:
|
||||||
return currentValue;
|
return currentValue;
|
||||||
case State::Release:
|
case State::Release:
|
||||||
if (release-- > 0)
|
if (release-- > 0) {
|
||||||
{
|
|
||||||
currentValue *= step;
|
currentValue *= step;
|
||||||
return currentValue;
|
return currentValue;
|
||||||
}
|
}
|
||||||
|
|
@ -100,8 +94,7 @@ void ADSREnvelope<Type>::getBlock(absl::Span<Type> output) noexcept
|
||||||
auto originalSpan = output;
|
auto originalSpan = output;
|
||||||
auto remainingSamples = static_cast<int>(output.size());
|
auto remainingSamples = static_cast<int>(output.size());
|
||||||
int length;
|
int length;
|
||||||
switch(currentState)
|
switch (currentState) {
|
||||||
{
|
|
||||||
case State::Delay:
|
case State::Delay:
|
||||||
length = min(remainingSamples, delay);
|
length = min(remainingSamples, delay);
|
||||||
::fill<Type>(output, currentValue);
|
::fill<Type>(output, currentValue);
|
||||||
|
|
@ -171,11 +164,9 @@ void ADSREnvelope<Type>::getBlock(absl::Span<Type> output) noexcept
|
||||||
}
|
}
|
||||||
::fill<Type>(output, currentValue);
|
::fill<Type>(output, currentValue);
|
||||||
|
|
||||||
if (shouldRelease)
|
if (shouldRelease) {
|
||||||
{
|
|
||||||
remainingSamples = static_cast<int>(originalSpan.size());
|
remainingSamples = static_cast<int>(originalSpan.size());
|
||||||
if (releaseDelay > remainingSamples)
|
if (releaseDelay > remainingSamples) {
|
||||||
{
|
|
||||||
releaseDelay -= remainingSamples;
|
releaseDelay -= remainingSamples;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -191,13 +182,11 @@ void ADSREnvelope<Type>::getBlock(absl::Span<Type> output) noexcept
|
||||||
originalSpan.remove_prefix(length);
|
originalSpan.remove_prefix(length);
|
||||||
release -= length;
|
release -= length;
|
||||||
|
|
||||||
if (release == 0)
|
if (release == 0) {
|
||||||
{
|
|
||||||
currentValue = 0.0;
|
currentValue = 0.0;
|
||||||
currentState = State::Done;
|
currentState = State::Done;
|
||||||
::fill<Type>(originalSpan, 0.0);
|
::fill<Type>(originalSpan, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <class Type>
|
template <class Type>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <absl/types/span.h>
|
|
||||||
#include "Helpers.h"
|
#include "Helpers.h"
|
||||||
namespace sfz
|
#include <absl/types/span.h>
|
||||||
{
|
namespace sfz {
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
class ADSREnvelope
|
class ADSREnvelope {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
ADSREnvelope() = default;
|
ADSREnvelope() = default;
|
||||||
void reset(int attack, int release, Type sustain = 1.0, int delay = 0, int decay = 0, int hold = 0, Type start = 0.0, Type depth = 1) noexcept;
|
void reset(int attack, int release, Type sustain = 1.0, int delay = 0, int decay = 0, int hold = 0, Type start = 0.0, Type depth = 1) noexcept;
|
||||||
|
|
@ -14,10 +12,16 @@ public:
|
||||||
void getBlock(absl::Span<Type> output) noexcept;
|
void getBlock(absl::Span<Type> output) noexcept;
|
||||||
void startRelease(int releaseDelay) noexcept;
|
void startRelease(int releaseDelay) noexcept;
|
||||||
bool isSmoothing() noexcept;
|
bool isSmoothing() noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class State
|
enum class State {
|
||||||
{
|
Delay,
|
||||||
Delay, Attack, Hold, Decay, Sustain, Release, Done
|
Attack,
|
||||||
|
Hold,
|
||||||
|
Decay,
|
||||||
|
Sustain,
|
||||||
|
Release,
|
||||||
|
Done
|
||||||
};
|
};
|
||||||
State currentState { State::Done };
|
State currentState { State::Done };
|
||||||
Type currentValue { 0.0 };
|
Type currentValue { 0.0 };
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,7 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
template <class Type, unsigned int Alignment = SIMDConfig::defaultAlignment>
|
template <class Type, unsigned int Alignment = SIMDConfig::defaultAlignment>
|
||||||
class Buffer
|
class Buffer {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
using value_type = std::remove_cv_t<Type>;
|
using value_type = std::remove_cv_t<Type>;
|
||||||
using pointer = value_type*;
|
using pointer = value_type*;
|
||||||
|
|
@ -31,16 +30,14 @@ public:
|
||||||
}
|
}
|
||||||
bool resize(size_t newSize)
|
bool resize(size_t newSize)
|
||||||
{
|
{
|
||||||
if (newSize == 0)
|
if (newSize == 0) {
|
||||||
{
|
|
||||||
clear();
|
clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tempSize = newSize + 2 * AlignmentMask; // To ensure that we have leeway at the beginning and at the end
|
auto tempSize = newSize + 2 * AlignmentMask; // To ensure that we have leeway at the beginning and at the end
|
||||||
auto* newData = paddedData != nullptr ? std::realloc(paddedData, tempSize * sizeof(value_type)) : std::malloc(tempSize * sizeof(value_type));
|
auto* newData = paddedData != nullptr ? std::realloc(paddedData, tempSize * sizeof(value_type)) : std::malloc(tempSize * sizeof(value_type));
|
||||||
if (newData == nullptr)
|
if (newData == nullptr) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,8 +70,7 @@ public:
|
||||||
|
|
||||||
Buffer(const Buffer<Type>& other)
|
Buffer(const Buffer<Type>& other)
|
||||||
{
|
{
|
||||||
if (resize(other.size()))
|
if (resize(other.size())) {
|
||||||
{
|
|
||||||
std::memcpy(this->data(), other.data(), other.size() * sizeof(value_type));
|
std::memcpy(this->data(), other.data(), other.size() * sizeof(value_type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -91,8 +87,7 @@ public:
|
||||||
|
|
||||||
Buffer<Type>& operator=(const Buffer<Type>& other)
|
Buffer<Type>& operator=(const Buffer<Type>& other)
|
||||||
{
|
{
|
||||||
if (this != &other)
|
if (this != &other) {
|
||||||
{
|
|
||||||
if (resize(other.size()))
|
if (resize(other.size()))
|
||||||
std::memcpy(this->data(), other.data(), other.size() * sizeof(value_type));
|
std::memcpy(this->data(), other.data(), other.size() * sizeof(value_type));
|
||||||
}
|
}
|
||||||
|
|
@ -101,8 +96,7 @@ public:
|
||||||
|
|
||||||
Buffer<Type>& operator=(Buffer<Type>&& other)
|
Buffer<Type>& operator=(Buffer<Type>&& other)
|
||||||
{
|
{
|
||||||
if (this != &other)
|
if (this != &other) {
|
||||||
{
|
|
||||||
std::free(paddedData);
|
std::free(paddedData);
|
||||||
largerSize = std::exchange(other.largerSize, 0);
|
largerSize = std::exchange(other.largerSize, 0);
|
||||||
alignedSize = std::exchange(other.alignedSize, 0);
|
alignedSize = std::exchange(other.alignedSize, 0);
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <map>
|
|
||||||
#include "Helpers.h"
|
#include "Helpers.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz {
|
||||||
{
|
|
||||||
template <class ValueType>
|
template <class ValueType>
|
||||||
class CCMap
|
class CCMap {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
CCMap() = delete;
|
CCMap() = delete;
|
||||||
CCMap(const ValueType& defaultValue) : defaultValue(defaultValue) { }
|
CCMap(const ValueType& defaultValue)
|
||||||
|
: defaultValue(defaultValue)
|
||||||
|
{
|
||||||
|
}
|
||||||
CCMap(CCMap&&) = default;
|
CCMap(CCMap&&) = default;
|
||||||
CCMap(const CCMap&) = default;
|
CCMap(const CCMap&) = default;
|
||||||
~CCMap() = default;
|
~CCMap() = default;
|
||||||
|
|
@ -17,12 +18,9 @@ public:
|
||||||
const ValueType& getWithDefault(int index) const noexcept
|
const ValueType& getWithDefault(int index) const noexcept
|
||||||
{
|
{
|
||||||
auto it = container.find(index);
|
auto it = container.find(index);
|
||||||
if (it == end(container))
|
if (it == end(container)) {
|
||||||
{
|
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "StereoBuffer.h"
|
|
||||||
#include "Defaults.h"
|
#include "Defaults.h"
|
||||||
|
#include "StereoBuffer.h"
|
||||||
#include "Voice.h"
|
#include "Voice.h"
|
||||||
#include <sndfile.hh>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <optional>
|
|
||||||
#include <string_view>
|
|
||||||
#include <absl/container/flat_hash_map.h>
|
|
||||||
#include <map>
|
|
||||||
#include "readerwriterqueue.h"
|
#include "readerwriterqueue.h"
|
||||||
|
#include <absl/container/flat_hash_map.h>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
|
#include <sndfile.hh>
|
||||||
|
#include <string_view>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz {
|
||||||
{
|
class FilePool {
|
||||||
class FilePool
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
FilePool()
|
FilePool()
|
||||||
: fileLoadingThread(std::thread(&FilePool::loadingThread, this))
|
: fileLoadingThread(std::thread(&FilePool::loadingThread, this))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~FilePool()
|
~FilePool()
|
||||||
|
|
@ -30,8 +27,7 @@ public:
|
||||||
void setRootDirectory(const std::filesystem::path& directory) { rootDirectory = directory; }
|
void setRootDirectory(const std::filesystem::path& directory) { rootDirectory = directory; }
|
||||||
size_t getNumPreloadedSamples() { return preloadedData.size(); }
|
size_t getNumPreloadedSamples() { return preloadedData.size(); }
|
||||||
|
|
||||||
struct FileInformation
|
struct FileInformation {
|
||||||
{
|
|
||||||
uint32_t end { Default::sampleEndRange.getEnd() };
|
uint32_t end { Default::sampleEndRange.getEnd() };
|
||||||
uint32_t loopBegin { Default::loopRange.getStart() };
|
uint32_t loopBegin { Default::loopRange.getStart() };
|
||||||
uint32_t loopEnd { Default::loopRange.getEnd() };
|
uint32_t loopEnd { Default::loopRange.getEnd() };
|
||||||
|
|
@ -40,7 +36,8 @@ public:
|
||||||
};
|
};
|
||||||
std::optional<FileInformation> getFileInformation(std::string_view filename);
|
std::optional<FileInformation> getFileInformation(std::string_view filename);
|
||||||
void enqueueLoading(Voice* voice, std::string_view sample, int numFrames);
|
void enqueueLoading(Voice* voice, std::string_view sample, int numFrames);
|
||||||
static void deleteAndTrackBuffers(StereoBuffer<float>* buffer) {
|
static void deleteAndTrackBuffers(StereoBuffer<float>* buffer)
|
||||||
|
{
|
||||||
fileBuffers--;
|
fileBuffers--;
|
||||||
delete buffer;
|
delete buffer;
|
||||||
};
|
};
|
||||||
|
|
@ -48,10 +45,10 @@ public:
|
||||||
{
|
{
|
||||||
return fileBuffers.load();
|
return fileBuffers.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::filesystem::path rootDirectory;
|
std::filesystem::path rootDirectory;
|
||||||
struct FileLoadingInformation
|
struct FileLoadingInformation {
|
||||||
{
|
|
||||||
Voice* voice;
|
Voice* voice;
|
||||||
std::string_view sample;
|
std::string_view sample;
|
||||||
int numFrames;
|
int numFrames;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz {
|
||||||
{
|
|
||||||
|
|
||||||
namespace config
|
namespace config {
|
||||||
{
|
|
||||||
constexpr float defaultSampleRate { 48000 };
|
constexpr float defaultSampleRate { 48000 };
|
||||||
constexpr int defaultSamplesPerBlock { 1024 };
|
constexpr int defaultSamplesPerBlock { 1024 };
|
||||||
constexpr int preloadSize { 8192 };
|
constexpr int preloadSize { 8192 };
|
||||||
|
|
@ -21,8 +19,7 @@ namespace config
|
||||||
|
|
||||||
} // namespace sfz
|
} // namespace sfz
|
||||||
|
|
||||||
namespace SIMDConfig
|
namespace SIMDConfig {
|
||||||
{
|
|
||||||
constexpr unsigned int defaultAlignment { 16 };
|
constexpr unsigned int defaultAlignment { 16 };
|
||||||
constexpr bool writeInterleaved { true };
|
constexpr bool writeInterleaved { true };
|
||||||
constexpr bool readInterleaved { true };
|
constexpr bool readInterleaved { true };
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,11 @@
|
||||||
inline void trimInPlace(std::string_view& s)
|
inline void trimInPlace(std::string_view& s)
|
||||||
{
|
{
|
||||||
const auto leftPosition = s.find_first_not_of(" \r\t\n\f\v");
|
const auto leftPosition = s.find_first_not_of(" \r\t\n\f\v");
|
||||||
if (leftPosition != s.npos)
|
if (leftPosition != s.npos) {
|
||||||
{
|
|
||||||
s.remove_prefix(leftPosition);
|
s.remove_prefix(leftPosition);
|
||||||
const auto rightPosition = s.find_last_not_of(" \r\t\n\f\v");
|
const auto rightPosition = s.find_last_not_of(" \r\t\n\f\v");
|
||||||
s.remove_suffix(s.size() - rightPosition - 1);
|
s.remove_suffix(s.size() - rightPosition - 1);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
s.remove_suffix(s.size());
|
s.remove_suffix(s.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -21,14 +18,11 @@ inline void trimInPlace(std::string_view &s)
|
||||||
inline std::string_view trim(std::string_view s)
|
inline std::string_view trim(std::string_view s)
|
||||||
{
|
{
|
||||||
const auto leftPosition = s.find_first_not_of(" \r\t\n\f\v");
|
const auto leftPosition = s.find_first_not_of(" \r\t\n\f\v");
|
||||||
if (leftPosition != s.npos)
|
if (leftPosition != s.npos) {
|
||||||
{
|
|
||||||
s.remove_prefix(leftPosition);
|
s.remove_prefix(leftPosition);
|
||||||
const auto rightPosition = s.find_last_not_of(" \r\t\n\f\v");
|
const auto rightPosition = s.find_last_not_of(" \r\t\n\f\v");
|
||||||
s.remove_suffix(s.size() - rightPosition - 1);
|
s.remove_suffix(s.size() - rightPosition - 1);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
s.remove_suffix(s.size());
|
s.remove_suffix(s.size());
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
|
@ -112,8 +106,7 @@ inline constexpr Type mag2db(Type in)
|
||||||
return static_cast<Type>(20.0) * std::log10(in);
|
return static_cast<Type>(20.0) * std::log10(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Random
|
namespace Random {
|
||||||
{
|
|
||||||
static inline std::random_device randomDevice;
|
static inline std::random_device randomDevice;
|
||||||
static inline std::mt19937 randomGenerator { randomDevice() };
|
static inline std::mt19937 randomGenerator { randomDevice() };
|
||||||
} // namespace Random
|
} // namespace Random
|
||||||
|
|
@ -132,8 +125,7 @@ constexpr Type piTwo{pi<Type> / 2};
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
template <class Owner>
|
template <class Owner>
|
||||||
class LeakDetector
|
class LeakDetector {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
LeakDetector()
|
LeakDetector()
|
||||||
{
|
{
|
||||||
|
|
@ -146,8 +138,7 @@ public:
|
||||||
~LeakDetector()
|
~LeakDetector()
|
||||||
{
|
{
|
||||||
objectCounter.count--;
|
objectCounter.count--;
|
||||||
if (objectCounter.count.load() < 0)
|
if (objectCounter.count.load() < 0) {
|
||||||
{
|
|
||||||
DBG("Deleted a dangling pointer for class " << Owner::getClassName());
|
DBG("Deleted a dangling pointer for class " << Owner::getClassName());
|
||||||
// Deleted a dangling pointer!
|
// Deleted a dangling pointer!
|
||||||
ASSERTFALSE;
|
ASSERTFALSE;
|
||||||
|
|
@ -155,13 +146,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ObjectCounter
|
struct ObjectCounter {
|
||||||
{
|
|
||||||
ObjectCounter() = default;
|
ObjectCounter() = default;
|
||||||
~ObjectCounter()
|
~ObjectCounter()
|
||||||
{
|
{
|
||||||
if (auto residualCount = count.load() > 0)
|
if (auto residualCount = count.load() > 0) {
|
||||||
{
|
|
||||||
DBG("Leaked " << residualCount << " instance(s) of class " << Owner::getClassName());
|
DBG("Leaked " << residualCount << " instance(s) of class " << Owner::getClassName());
|
||||||
// Leaked ojects
|
// Leaked ojects
|
||||||
ASSERTFALSE;
|
ASSERTFALSE;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@
|
||||||
#include "SIMDHelpers.h"
|
#include "SIMDHelpers.h"
|
||||||
#include <absl/algorithm/container.h>
|
#include <absl/algorithm/container.h>
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz {
|
||||||
{
|
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
LinearEnvelope<Type>::LinearEnvelope()
|
LinearEnvelope<Type>::LinearEnvelope()
|
||||||
|
|
@ -60,11 +59,9 @@ void LinearEnvelope<Type>::getBlock(absl::Span<Type> output)
|
||||||
});
|
});
|
||||||
int index { 0 };
|
int index { 0 };
|
||||||
|
|
||||||
for (auto& event: events)
|
for (auto& event : events) {
|
||||||
{
|
|
||||||
const auto length = min(event.first, static_cast<int>(output.size())) - index;
|
const auto length = min(event.first, static_cast<int>(output.size())) - index;
|
||||||
if (length == 0)
|
if (length == 0) {
|
||||||
{
|
|
||||||
currentValue = event.second;
|
currentValue = event.second;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Helpers.h"
|
#include "Helpers.h"
|
||||||
#include <type_traits>
|
|
||||||
#include <functional>
|
|
||||||
#include <absl/types/span.h>
|
#include <absl/types/span.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz {
|
||||||
{
|
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
class LinearEnvelope
|
class LinearEnvelope {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
LinearEnvelope();
|
LinearEnvelope();
|
||||||
LinearEnvelope(int maxCapacity, std::function<Type(Type)> function);
|
LinearEnvelope(int maxCapacity, std::function<Type(Type)> function);
|
||||||
|
|
@ -20,6 +18,7 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
void reset(Type value = 0.0);
|
void reset(Type value = 0.0);
|
||||||
void getBlock(absl::Span<Type> output);
|
void getBlock(absl::Span<Type> output);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::function<Type(Type)> function { [](Type input) { return input; } };
|
std::function<Type(Type)> function { [](Type input) { return input; } };
|
||||||
static_assert(std::is_arithmetic<Type>::value);
|
static_assert(std::is_arithmetic<Type>::value);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include <cmath>
|
|
||||||
#include <absl/types/span.h>
|
#include <absl/types/span.h>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
template <class Type = float>
|
template <class Type = float>
|
||||||
class OnePoleFilter
|
class OnePoleFilter {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
OnePoleFilter() = default;
|
OnePoleFilter() = default;
|
||||||
// Normalized cutoff with respect to the sampling rate
|
// Normalized cutoff with respect to the sampling rate
|
||||||
|
|
@ -31,8 +30,7 @@ public:
|
||||||
int processLowpass(absl::Span<const Type> input, absl::Span<Type> lowpass)
|
int processLowpass(absl::Span<const Type> input, absl::Span<Type> lowpass)
|
||||||
{
|
{
|
||||||
for (auto [in, out] = std::pair(input.begin(), lowpass.begin());
|
for (auto [in, out] = std::pair(input.begin(), lowpass.begin());
|
||||||
in < input.end() && out < lowpass.end(); in++, out++)
|
in < input.end() && out < lowpass.end(); in++, out++) {
|
||||||
{
|
|
||||||
oneLowpass(in, out);
|
oneLowpass(in, out);
|
||||||
}
|
}
|
||||||
return std::min(input.size(), lowpass.size());
|
return std::min(input.size(), lowpass.size());
|
||||||
|
|
@ -41,8 +39,7 @@ public:
|
||||||
int processHighpass(absl::Span<const Type> input, absl::Span<Type> highpass)
|
int processHighpass(absl::Span<const Type> input, absl::Span<Type> highpass)
|
||||||
{
|
{
|
||||||
for (auto [in, out] = std::pair(input.begin(), highpass.begin());
|
for (auto [in, out] = std::pair(input.begin(), highpass.begin());
|
||||||
in < input.end() && out < highpass.end(); in++, out++)
|
in < input.end() && out < highpass.end(); in++, out++) {
|
||||||
{
|
|
||||||
oneHighpass(in, out);
|
oneHighpass(in, out);
|
||||||
}
|
}
|
||||||
return std::min(input.size(), highpass.size());
|
return std::min(input.size(), highpass.size());
|
||||||
|
|
@ -51,8 +48,7 @@ public:
|
||||||
int processLowpassVariableGain(absl::Span<const Type> input, absl::Span<Type> lowpass, absl::Span<const Type> gain)
|
int processLowpassVariableGain(absl::Span<const Type> input, absl::Span<Type> lowpass, absl::Span<const Type> gain)
|
||||||
{
|
{
|
||||||
for (auto [in, out, g] = std::tuple(input.begin(), lowpass.begin(), gain.begin());
|
for (auto [in, out, g] = std::tuple(input.begin(), lowpass.begin(), gain.begin());
|
||||||
in < input.end() && out < lowpass.end() && g < gain.end(); in++, out++, g++)
|
in < input.end() && out < lowpass.end() && g < gain.end(); in++, out++, g++) {
|
||||||
{
|
|
||||||
setGain(*g);
|
setGain(*g);
|
||||||
oneLowpass(in, out);
|
oneLowpass(in, out);
|
||||||
}
|
}
|
||||||
|
|
@ -63,8 +59,7 @@ public:
|
||||||
int processHighpassVariableGain(absl::Span<const Type> input, absl::Span<Type> highpass, absl::Span<const Type> gain)
|
int processHighpassVariableGain(absl::Span<const Type> input, absl::Span<Type> highpass, absl::Span<const Type> gain)
|
||||||
{
|
{
|
||||||
for (auto [in, out, g] = std::tuple(input.begin(), highpass.begin(), gain.begin());
|
for (auto [in, out, g] = std::tuple(input.begin(), highpass.begin(), gain.begin());
|
||||||
in < input.end() && out < highpass.end() && g < gain.end(); in++, out++, g++)
|
in < input.end() && out < highpass.end() && g < gain.end(); in++, out++, g++) {
|
||||||
{
|
|
||||||
setGain(*g);
|
setGain(*g);
|
||||||
oneHighpass(in, out);
|
oneHighpass(in, out);
|
||||||
}
|
}
|
||||||
|
|
@ -73,6 +68,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() { state = 0.0; }
|
void reset() { state = 0.0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type state { 0.0 };
|
Type state { 0.0 };
|
||||||
Type gain { 0.25 };
|
Type gain { 0.25 };
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
#include "Opcode.h"
|
#include "Opcode.h"
|
||||||
|
|
||||||
sfz::Opcode::Opcode(std::string_view inputOpcode, std::string_view inputValue)
|
sfz::Opcode::Opcode(std::string_view inputOpcode, std::string_view inputValue)
|
||||||
:opcode(inputOpcode), value(inputValue)
|
: opcode(inputOpcode)
|
||||||
{
|
, value(inputValue)
|
||||||
if (const auto lastCharIndex = inputOpcode.find_last_not_of("1234567890"); lastCharIndex != inputOpcode.npos)
|
|
||||||
{
|
{
|
||||||
|
if (const auto lastCharIndex = inputOpcode.find_last_not_of("1234567890"); lastCharIndex != inputOpcode.npos) {
|
||||||
int returnedValue;
|
int returnedValue;
|
||||||
std::string_view parameterView = inputOpcode;
|
std::string_view parameterView = inputOpcode;
|
||||||
parameterView.remove_prefix(lastCharIndex + 1);
|
parameterView.remove_prefix(lastCharIndex + 1);
|
||||||
if (absl::SimpleAtoi(parameterView, &returnedValue))
|
if (absl::SimpleAtoi(parameterView, &returnedValue)) {
|
||||||
{
|
|
||||||
parameter = returnedValue;
|
parameter = returnedValue;
|
||||||
opcode.remove_suffix(opcode.size() - lastCharIndex - 1);
|
opcode.remove_suffix(opcode.size() - lastCharIndex - 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Helpers.h"
|
|
||||||
#include "SfzHelpers.h"
|
|
||||||
#include "Defaults.h"
|
#include "Defaults.h"
|
||||||
|
#include "Helpers.h"
|
||||||
#include "Range.h"
|
#include "Range.h"
|
||||||
#include <string_view>
|
#include "SfzHelpers.h"
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
// charconv support is still sketchy with clang/gcc so we use abseil's numbers
|
// charconv support is still sketchy with clang/gcc so we use abseil's numbers
|
||||||
#include "absl/strings/numbers.h"
|
#include "absl/strings/numbers.h"
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz {
|
||||||
{
|
struct Opcode {
|
||||||
struct Opcode
|
|
||||||
{
|
|
||||||
Opcode() = delete;
|
Opcode() = delete;
|
||||||
Opcode(std::string_view inputOpcode, std::string_view inputValue);
|
Opcode(std::string_view inputOpcode, std::string_view inputValue);
|
||||||
std::string_view opcode {};
|
std::string_view opcode {};
|
||||||
|
|
@ -25,8 +23,7 @@ struct Opcode
|
||||||
template <class ValueType>
|
template <class ValueType>
|
||||||
inline std::optional<ValueType> readOpcode(std::string_view value, const Range<ValueType>& validRange)
|
inline std::optional<ValueType> readOpcode(std::string_view value, const Range<ValueType>& validRange)
|
||||||
{
|
{
|
||||||
if constexpr(std::is_integral<ValueType>::value)
|
if constexpr (std::is_integral<ValueType>::value) {
|
||||||
{
|
|
||||||
int64_t returnedValue;
|
int64_t returnedValue;
|
||||||
if (!absl::SimpleAtoi(value, &returnedValue))
|
if (!absl::SimpleAtoi(value, &returnedValue))
|
||||||
return {};
|
return {};
|
||||||
|
|
@ -37,9 +34,7 @@ inline std::optional<ValueType> readOpcode(std::string_view value, const Range<V
|
||||||
returnedValue = std::numeric_limits<ValueType>::min();
|
returnedValue = std::numeric_limits<ValueType>::min();
|
||||||
|
|
||||||
return validRange.clamp(static_cast<ValueType>(returnedValue));
|
return validRange.clamp(static_cast<ValueType>(returnedValue));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
float returnedValue;
|
float returnedValue;
|
||||||
if (!absl::SimpleAtof(value, &returnedValue))
|
if (!absl::SimpleAtof(value, &returnedValue))
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#include "Parser.h"
|
#include "Parser.h"
|
||||||
#include "Helpers.h"
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
|
#include "Helpers.h"
|
||||||
#include "absl/strings/str_join.h"
|
#include "absl/strings/str_join.h"
|
||||||
#include <fstream>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
using svregex_iterator = std::regex_iterator<std::string_view::const_iterator>;
|
using svregex_iterator = std::regex_iterator<std::string_view::const_iterator>;
|
||||||
using svmatch_results = std::match_results<std::string_view::const_iterator>;
|
using svmatch_results = std::match_results<std::string_view::const_iterator>;
|
||||||
|
|
@ -32,8 +32,7 @@ bool sfz::Parser::loadSfzFile(const std::filesystem::path &file)
|
||||||
|
|
||||||
std::vector<Opcode> currentMembers;
|
std::vector<Opcode> currentMembers;
|
||||||
|
|
||||||
for (; headerIterator != regexEnd; ++headerIterator)
|
for (; headerIterator != regexEnd; ++headerIterator) {
|
||||||
{
|
|
||||||
svmatch_results headerMatch = *headerIterator;
|
svmatch_results headerMatch = *headerIterator;
|
||||||
|
|
||||||
// Can't use uniform initialization here because it generates narrowing conversions
|
// Can't use uniform initialization here because it generates narrowing conversions
|
||||||
|
|
@ -42,8 +41,7 @@ bool sfz::Parser::loadSfzFile(const std::filesystem::path &file)
|
||||||
auto paramIterator = svregex_iterator(members.cbegin(), members.cend(), sfz::Regexes::members);
|
auto paramIterator = svregex_iterator(members.cbegin(), members.cend(), sfz::Regexes::members);
|
||||||
|
|
||||||
// Store or handle members
|
// Store or handle members
|
||||||
for (; paramIterator != regexEnd; ++paramIterator)
|
for (; paramIterator != regexEnd; ++paramIterator) {
|
||||||
{
|
|
||||||
const svmatch_results paramMatch = *paramIterator;
|
const svmatch_results paramMatch = *paramIterator;
|
||||||
const std::string_view opcode(&*paramMatch[1].first, paramMatch[1].length());
|
const std::string_view opcode(&*paramMatch[1].first, paramMatch[1].length());
|
||||||
const std::string_view value(&*paramMatch[2].first, paramMatch[2].length());
|
const std::string_view value(&*paramMatch[2].first, paramMatch[2].length());
|
||||||
|
|
@ -67,8 +65,7 @@ void sfz::Parser::readSfzFile(const std::filesystem::path &fileName, std::vector
|
||||||
svmatch_results defineMatch;
|
svmatch_results defineMatch;
|
||||||
|
|
||||||
std::string tmpString;
|
std::string tmpString;
|
||||||
while (std::getline(fileStream, tmpString))
|
while (std::getline(fileStream, tmpString)) {
|
||||||
{
|
|
||||||
std::string_view tmpView { tmpString };
|
std::string_view tmpView { tmpString };
|
||||||
|
|
||||||
removeCommentOnLine(tmpView);
|
removeCommentOnLine(tmpView);
|
||||||
|
|
@ -78,21 +75,16 @@ void sfz::Parser::readSfzFile(const std::filesystem::path &fileName, std::vector
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// New #include
|
// New #include
|
||||||
if (std::regex_search(tmpView.begin(), tmpView.end(), includeMatch, sfz::Regexes::includes))
|
if (std::regex_search(tmpView.begin(), tmpView.end(), includeMatch, sfz::Regexes::includes)) {
|
||||||
{
|
|
||||||
auto includePath = includeMatch.str(1);
|
auto includePath = includeMatch.str(1);
|
||||||
std::replace(includePath.begin(), includePath.end(), '\\', '/');
|
std::replace(includePath.begin(), includePath.end(), '\\', '/');
|
||||||
const auto newFile = rootDirectory / includePath;
|
const auto newFile = rootDirectory / includePath;
|
||||||
auto alreadyIncluded = std::find(includedFiles.begin(), includedFiles.end(), newFile);
|
auto alreadyIncluded = std::find(includedFiles.begin(), includedFiles.end(), newFile);
|
||||||
if (std::filesystem::exists(newFile))
|
if (std::filesystem::exists(newFile)) {
|
||||||
{
|
if (alreadyIncluded == includedFiles.end()) {
|
||||||
if (alreadyIncluded == includedFiles.end())
|
|
||||||
{
|
|
||||||
includedFiles.push_back(newFile);
|
includedFiles.push_back(newFile);
|
||||||
readSfzFile(newFile, lines);
|
readSfzFile(newFile, lines);
|
||||||
}
|
} else if (!recursiveIncludeGuard) {
|
||||||
else if (!recursiveIncludeGuard)
|
|
||||||
{
|
|
||||||
readSfzFile(newFile, lines);
|
readSfzFile(newFile, lines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -100,8 +92,7 @@ void sfz::Parser::readSfzFile(const std::filesystem::path &fileName, std::vector
|
||||||
}
|
}
|
||||||
|
|
||||||
// New #define
|
// New #define
|
||||||
if (std::regex_search(tmpView.begin(), tmpView.end(), defineMatch, sfz::Regexes::defines))
|
if (std::regex_search(tmpView.begin(), tmpView.end(), defineMatch, sfz::Regexes::defines)) {
|
||||||
{
|
|
||||||
defines[defineMatch.str(1)] = defineMatch.str(2);
|
defines[defineMatch.str(1)] = defineMatch.str(2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -112,23 +103,19 @@ void sfz::Parser::readSfzFile(const std::filesystem::path &fileName, std::vector
|
||||||
std::string::size_type lastPos = 0;
|
std::string::size_type lastPos = 0;
|
||||||
std::string::size_type findPos = tmpView.find(sfz::config::defineCharacter, lastPos);
|
std::string::size_type findPos = tmpView.find(sfz::config::defineCharacter, lastPos);
|
||||||
|
|
||||||
while (findPos < tmpView.npos)
|
while (findPos < tmpView.npos) {
|
||||||
{
|
|
||||||
newString.append(tmpView, lastPos, findPos - lastPos);
|
newString.append(tmpView, lastPos, findPos - lastPos);
|
||||||
|
|
||||||
for (auto &definePair : defines)
|
for (auto& definePair : defines) {
|
||||||
{
|
|
||||||
std::string_view candidate = tmpView.substr(findPos, definePair.first.length());
|
std::string_view candidate = tmpView.substr(findPos, definePair.first.length());
|
||||||
if (candidate == definePair.first)
|
if (candidate == definePair.first) {
|
||||||
{
|
|
||||||
newString += definePair.second;
|
newString += definePair.second;
|
||||||
lastPos = findPos + definePair.first.length();
|
lastPos = findPos + definePair.first.length();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastPos <= findPos)
|
if (lastPos <= findPos) {
|
||||||
{
|
|
||||||
newString += sfz::config::defineCharacter;
|
newString += sfz::config::defineCharacter;
|
||||||
lastPos = findPos + 1;
|
lastPos = findPos + 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Opcode.h"
|
#include "Opcode.h"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <regex>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz {
|
||||||
{
|
namespace Regexes {
|
||||||
namespace Regexes
|
|
||||||
{
|
|
||||||
inline static std::regex includes { R"V(#include\s*"(.*?)".*$)V", std::regex::optimize };
|
inline static std::regex includes { R"V(#include\s*"(.*?)".*$)V", std::regex::optimize };
|
||||||
inline static std::regex defines { R"(#define\s*(\$[a-zA-Z0-9]+)\s+([a-zA-Z0-9]+)(?=\s|$))", std::regex::optimize };
|
inline static std::regex defines { R"(#define\s*(\$[a-zA-Z0-9]+)\s+([a-zA-Z0-9]+)(?=\s|$))", std::regex::optimize };
|
||||||
inline static std::regex headers { R"(<(.*?)>(.*?)(?=<|$))", std::regex::optimize };
|
inline static std::regex headers { R"(<(.*?)>(.*?)(?=<|$))", std::regex::optimize };
|
||||||
|
|
@ -18,17 +16,18 @@ namespace Regexes
|
||||||
inline static std::regex opcodeParameters { R"(([a-zA-Z0-9_]+?)([0-9]+)$)", std::regex::optimize };
|
inline static std::regex opcodeParameters { R"(([a-zA-Z0-9_]+?)([0-9]+)$)", std::regex::optimize };
|
||||||
}
|
}
|
||||||
|
|
||||||
class Parser
|
class Parser {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual bool loadSfzFile(const std::filesystem::path& file);
|
virtual bool loadSfzFile(const std::filesystem::path& file);
|
||||||
const std::map<std::string, std::string>& getDefines() const noexcept { return defines; }
|
const std::map<std::string, std::string>& getDefines() const noexcept { return defines; }
|
||||||
const std::vector<std::filesystem::path>& getIncludedFiles() const noexcept { return includedFiles; }
|
const std::vector<std::filesystem::path>& getIncludedFiles() const noexcept { return includedFiles; }
|
||||||
void disableRecursiveIncludeGuard() { recursiveIncludeGuard = false; }
|
void disableRecursiveIncludeGuard() { recursiveIncludeGuard = false; }
|
||||||
void enableRecursiveIncludeGuard() { recursiveIncludeGuard = true; }
|
void enableRecursiveIncludeGuard() { recursiveIncludeGuard = true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void callback(std::string_view header, const std::vector<Opcode>& members) = 0;
|
virtual void callback(std::string_view header, const std::vector<Opcode>& members) = 0;
|
||||||
std::filesystem::path rootDirectory { std::filesystem::current_path() };
|
std::filesystem::path rootDirectory { std::filesystem::current_path() };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool recursiveIncludeGuard { false };
|
bool recursiveIncludeGuard { false };
|
||||||
std::map<std::string, std::string> defines;
|
std::map<std::string, std::string> defines;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <type_traits>
|
|
||||||
#include <initializer_list>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
class Range
|
class Range {
|
||||||
{
|
|
||||||
static_assert(std::is_arithmetic<Type>::value, "The Type should be arithmetic");
|
static_assert(std::is_arithmetic<Type>::value, "The Type should be arithmetic");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr Range() = default;
|
constexpr Range() = default;
|
||||||
// constexpr Range(std::initializer_list<Type> list)
|
// constexpr Range(std::initializer_list<Type> list)
|
||||||
|
|
@ -25,7 +25,10 @@ public:
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
constexpr Range(Type start, Type end) noexcept
|
constexpr Range(Type start, Type end) noexcept
|
||||||
: _start(start), _end(std::max(start, end)) {}
|
: _start(start)
|
||||||
|
, _end(std::max(start, end))
|
||||||
|
{
|
||||||
|
}
|
||||||
~Range() = default;
|
~Range() = default;
|
||||||
Type getStart() const noexcept { return _start; }
|
Type getStart() const noexcept { return _start; }
|
||||||
Type getEnd() const noexcept { return _end; }
|
Type getEnd() const noexcept { return _end; }
|
||||||
|
|
@ -59,6 +62,7 @@ public:
|
||||||
if (end < _end)
|
if (end < _end)
|
||||||
_end = end;
|
_end = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type _start { static_cast<Type>(0.0) };
|
Type _start { static_cast<Type>(0.0) };
|
||||||
Type _end { static_cast<Type>(0.0) };
|
Type _end { static_cast<Type>(0.0) };
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
bool sfz::Region::parseOpcode(const Opcode& opcode)
|
bool sfz::Region::parseOpcode(const Opcode& opcode)
|
||||||
{
|
{
|
||||||
switch (hash(opcode.opcode))
|
switch (hash(opcode.opcode)) {
|
||||||
{
|
|
||||||
// Sound source: sample playback
|
// Sound source: sample playback
|
||||||
case hash("sample"):
|
case hash("sample"):
|
||||||
sample = absl::StrReplaceAll(trim(opcode.value), { { "\\", "/" } });
|
sample = absl::StrReplaceAll(trim(opcode.value), { { "\\", "/" } });
|
||||||
|
|
@ -34,8 +33,7 @@ bool sfz::Region::parseOpcode(const Opcode &opcode)
|
||||||
break;
|
break;
|
||||||
case hash("loopmode"):
|
case hash("loopmode"):
|
||||||
case hash("loop_mode"):
|
case hash("loop_mode"):
|
||||||
switch (hash(opcode.value))
|
switch (hash(opcode.value)) {
|
||||||
{
|
|
||||||
case hash("no_loop"):
|
case hash("no_loop"):
|
||||||
loopMode = SfzLoopMode::no_loop;
|
loopMode = SfzLoopMode::no_loop;
|
||||||
break;
|
break;
|
||||||
|
|
@ -70,8 +68,7 @@ bool sfz::Region::parseOpcode(const Opcode &opcode)
|
||||||
setValueFromOpcode(opcode, offBy, Default::groupRange);
|
setValueFromOpcode(opcode, offBy, Default::groupRange);
|
||||||
break;
|
break;
|
||||||
case hash("off_mode"):
|
case hash("off_mode"):
|
||||||
switch (hash(opcode.value))
|
switch (hash(opcode.value)) {
|
||||||
{
|
|
||||||
case hash("fast"):
|
case hash("fast"):
|
||||||
offMode = SfzOffMode::fast;
|
offMode = SfzOffMode::fast;
|
||||||
break;
|
break;
|
||||||
|
|
@ -115,8 +112,7 @@ bool sfz::Region::parseOpcode(const Opcode &opcode)
|
||||||
setRangeEndFromOpcode(opcode, bendRange, Default::bendRange);
|
setRangeEndFromOpcode(opcode, bendRange, Default::bendRange);
|
||||||
break;
|
break;
|
||||||
case hash("locc"):
|
case hash("locc"):
|
||||||
if (opcode.parameter)
|
if (opcode.parameter) {
|
||||||
{
|
|
||||||
setRangeStartFromOpcode(opcode, ccConditions[*opcode.parameter], Default::ccRange);
|
setRangeStartFromOpcode(opcode, ccConditions[*opcode.parameter], Default::ccRange);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -146,8 +142,7 @@ bool sfz::Region::parseOpcode(const Opcode &opcode)
|
||||||
previousKeySwitched = false;
|
previousKeySwitched = false;
|
||||||
break;
|
break;
|
||||||
case hash("sw_vel"):
|
case hash("sw_vel"):
|
||||||
switch (hash(opcode.value))
|
switch (hash(opcode.value)) {
|
||||||
{
|
|
||||||
case hash("current"):
|
case hash("current"):
|
||||||
velocityOverride = SfzVelocityOverride::current;
|
velocityOverride = SfzVelocityOverride::current;
|
||||||
break;
|
break;
|
||||||
|
|
@ -186,8 +181,7 @@ bool sfz::Region::parseOpcode(const Opcode &opcode)
|
||||||
break;
|
break;
|
||||||
// Region logic: triggers
|
// Region logic: triggers
|
||||||
case hash("trigger"):
|
case hash("trigger"):
|
||||||
switch (hash(opcode.value))
|
switch (hash(opcode.value)) {
|
||||||
{
|
|
||||||
case hash("attack"):
|
case hash("attack"):
|
||||||
trigger = SfzTrigger::attack;
|
trigger = SfzTrigger::attack;
|
||||||
break;
|
break;
|
||||||
|
|
@ -263,8 +257,7 @@ bool sfz::Region::parseOpcode(const Opcode &opcode)
|
||||||
gainDistribution.param(std::uniform_real_distribution<float>::param_type(-ampRandom, ampRandom));
|
gainDistribution.param(std::uniform_real_distribution<float>::param_type(-ampRandom, ampRandom));
|
||||||
break;
|
break;
|
||||||
case hash("amp_velcurve_"):
|
case hash("amp_velcurve_"):
|
||||||
if (opcode.parameter && Default::ccRange.containsWithEnd(*opcode.parameter))
|
if (opcode.parameter && Default::ccRange.containsWithEnd(*opcode.parameter)) {
|
||||||
{
|
|
||||||
if (auto value = readOpcode(opcode.value, Default::ampVelcurveRange); value)
|
if (auto value = readOpcode(opcode.value, Default::ampVelcurveRange); value)
|
||||||
velocityPoints.emplace_back(*opcode.parameter, *value);
|
velocityPoints.emplace_back(*opcode.parameter, *value);
|
||||||
}
|
}
|
||||||
|
|
@ -294,8 +287,7 @@ bool sfz::Region::parseOpcode(const Opcode &opcode)
|
||||||
setRangeEndFromOpcode(opcode, crossfadeVelOutRange, Default::velocityRange);
|
setRangeEndFromOpcode(opcode, crossfadeVelOutRange, Default::velocityRange);
|
||||||
break;
|
break;
|
||||||
case hash("xf_keycurve"):
|
case hash("xf_keycurve"):
|
||||||
switch (hash(opcode.value))
|
switch (hash(opcode.value)) {
|
||||||
{
|
|
||||||
case hash("power"):
|
case hash("power"):
|
||||||
crossfadeKeyCurve = SfzCrossfadeCurve::power;
|
crossfadeKeyCurve = SfzCrossfadeCurve::power;
|
||||||
break;
|
break;
|
||||||
|
|
@ -307,8 +299,7 @@ bool sfz::Region::parseOpcode(const Opcode &opcode)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case hash("xf_velcurve"):
|
case hash("xf_velcurve"):
|
||||||
switch (hash(opcode.value))
|
switch (hash(opcode.value)) {
|
||||||
{
|
|
||||||
case hash("power"):
|
case hash("power"):
|
||||||
crossfadeVelCurve = SfzCrossfadeCurve::power;
|
crossfadeVelCurve = SfzCrossfadeCurve::power;
|
||||||
break;
|
break;
|
||||||
|
|
@ -423,10 +414,8 @@ bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity,
|
||||||
if (!chanOk)
|
if (!chanOk)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (keyswitchRange.containsWithEnd(noteNumber))
|
if (keyswitchRange.containsWithEnd(noteNumber)) {
|
||||||
{
|
if (keyswitch) {
|
||||||
if (keyswitch)
|
|
||||||
{
|
|
||||||
if (*keyswitch == noteNumber)
|
if (*keyswitch == noteNumber)
|
||||||
keySwitched = true;
|
keySwitched = true;
|
||||||
else
|
else
|
||||||
|
|
@ -441,8 +430,7 @@ bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity,
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool keyOk = keyRange.containsWithEnd(noteNumber);
|
const bool keyOk = keyRange.containsWithEnd(noteNumber);
|
||||||
if (keyOk)
|
if (keyOk) {
|
||||||
{
|
|
||||||
// Update the number of notes playing for the region
|
// Update the number of notes playing for the region
|
||||||
activeNotesInRange++;
|
activeNotesInRange++;
|
||||||
|
|
||||||
|
|
@ -457,8 +445,7 @@ bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity,
|
||||||
if (trigger == SfzTrigger::release_key || velocityOverride == SfzVelocityOverride::previous)
|
if (trigger == SfzTrigger::release_key || velocityOverride == SfzVelocityOverride::previous)
|
||||||
lastNoteVelocities[noteNumber] = velocity;
|
lastNoteVelocities[noteNumber] = velocity;
|
||||||
|
|
||||||
if (previousNote)
|
if (previousNote) {
|
||||||
{
|
|
||||||
if (*previousNote == noteNumber)
|
if (*previousNote == noteNumber)
|
||||||
previousKeySwitched = true;
|
previousKeySwitched = true;
|
||||||
else
|
else
|
||||||
|
|
@ -487,8 +474,7 @@ bool sfz::Region::registerNoteOff(int channel, int noteNumber, uint8_t velocity[
|
||||||
if (!chanOk)
|
if (!chanOk)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (keyswitchRange.containsWithEnd(noteNumber))
|
if (keyswitchRange.containsWithEnd(noteNumber)) {
|
||||||
{
|
|
||||||
if (keyswitchDown && *keyswitchDown == noteNumber)
|
if (keyswitchDown && *keyswitchDown == noteNumber)
|
||||||
keySwitched = false;
|
keySwitched = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Helpers.h"
|
|
||||||
#include <bits/stdint-uintn.h>
|
|
||||||
#include <optional>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include "Opcode.h"
|
|
||||||
#include "EGDescription.h"
|
|
||||||
#include "StereoBuffer.h"
|
|
||||||
#include "Defaults.h"
|
|
||||||
#include "CCMap.h"
|
#include "CCMap.h"
|
||||||
|
#include "Defaults.h"
|
||||||
|
#include "EGDescription.h"
|
||||||
|
#include "Helpers.h"
|
||||||
|
#include "Opcode.h"
|
||||||
|
#include "StereoBuffer.h"
|
||||||
|
#include <bits/stdint-uintn.h>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <optional>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz {
|
||||||
{
|
struct Region {
|
||||||
struct Region
|
|
||||||
{
|
|
||||||
Region()
|
Region()
|
||||||
{
|
{
|
||||||
ccSwitched.set();
|
ccSwitched.set();
|
||||||
|
|
@ -137,6 +135,7 @@ struct Region
|
||||||
double sampleRate { config::defaultSampleRate };
|
double sampleRate { config::defaultSampleRate };
|
||||||
int numChannels { 1 };
|
int numChannels { 1 };
|
||||||
std::shared_ptr<StereoBuffer<float>> preloadedData { nullptr };
|
std::shared_ptr<StereoBuffer<float>> preloadedData { nullptr };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool keySwitched { true };
|
bool keySwitched { true };
|
||||||
bool previousKeySwitched { true };
|
bool previousKeySwitched { true };
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "SIMDHelpers.h"
|
|
||||||
#include "Helpers.h"
|
#include "Helpers.h"
|
||||||
|
#include "SIMDHelpers.h"
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void readInterleaved<float, true>(absl::Span<const float> input, absl::Span<float> outputLeft, absl::Span<float> outputRight) noexcept
|
void readInterleaved<float, true>(absl::Span<const float> input, absl::Span<float> outputLeft, absl::Span<float> outputRight) noexcept
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include <absl/types/span.h>
|
|
||||||
#include <absl/algorithm/container.h>
|
|
||||||
#include "Helpers.h"
|
#include "Helpers.h"
|
||||||
|
#include <absl/algorithm/container.h>
|
||||||
|
#include <absl/types/span.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
#include "Synth.h"
|
#include "Synth.h"
|
||||||
#include "Helpers.h"
|
#include "Helpers.h"
|
||||||
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
void sfz::Synth::callback(std::string_view header, const std::vector<Opcode>& members)
|
void sfz::Synth::callback(std::string_view header, const std::vector<Opcode>& members)
|
||||||
{
|
{
|
||||||
switch (hash(header))
|
switch (hash(header)) {
|
||||||
{
|
|
||||||
case hash("global"):
|
case hash("global"):
|
||||||
// We shouldn't have multiple global headers in file
|
// We shouldn't have multiple global headers in file
|
||||||
ASSERT(!hasGlobal);
|
ASSERT(!hasGlobal);
|
||||||
|
|
@ -35,7 +34,7 @@ void sfz::Synth::callback(std::string_view header, const std::vector<Opcode>& me
|
||||||
numCurves++;
|
numCurves++;
|
||||||
break;
|
break;
|
||||||
case hash("effect"):
|
case hash("effect"):
|
||||||
// TODO: implement curves
|
// TODO: implement effects
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cerr << "Unknown header: " << header << '\n';
|
std::cerr << "Unknown header: " << header << '\n';
|
||||||
|
|
@ -79,8 +78,7 @@ void sfz::Synth::clear()
|
||||||
|
|
||||||
void sfz::Synth::handleGlobalOpcodes(const std::vector<Opcode>& members)
|
void sfz::Synth::handleGlobalOpcodes(const std::vector<Opcode>& members)
|
||||||
{
|
{
|
||||||
for (auto& member: members)
|
for (auto& member : members) {
|
||||||
{
|
|
||||||
if (member.opcode == "sw_default")
|
if (member.opcode == "sw_default")
|
||||||
setValueFromOpcode(member, defaultSwitch, Default::keyRange);
|
setValueFromOpcode(member, defaultSwitch, Default::keyRange);
|
||||||
}
|
}
|
||||||
|
|
@ -88,10 +86,8 @@ void sfz::Synth::handleGlobalOpcodes(const std::vector<Opcode>& members)
|
||||||
|
|
||||||
void sfz::Synth::handleControlOpcodes(const std::vector<Opcode>& members)
|
void sfz::Synth::handleControlOpcodes(const std::vector<Opcode>& members)
|
||||||
{
|
{
|
||||||
for (auto& member: members)
|
for (auto& member : members) {
|
||||||
{
|
switch (hash(member.opcode)) {
|
||||||
switch (hash(member.opcode))
|
|
||||||
{
|
|
||||||
case hash("set_cc"):
|
case hash("set_cc"):
|
||||||
if (member.parameter && Default::ccRange.containsWithEnd(*member.parameter))
|
if (member.parameter && Default::ccRange.containsWithEnd(*member.parameter))
|
||||||
setValueFromOpcode(member, ccState[*member.parameter], Default::ccRange);
|
setValueFromOpcode(member, ccState[*member.parameter], Default::ccRange);
|
||||||
|
|
@ -125,19 +121,16 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename)
|
||||||
|
|
||||||
auto lastRegion = regions.end() - 1;
|
auto lastRegion = regions.end() - 1;
|
||||||
auto currentRegion = regions.begin();
|
auto currentRegion = regions.begin();
|
||||||
while (currentRegion <= lastRegion)
|
while (currentRegion <= lastRegion) {
|
||||||
{
|
|
||||||
auto region = currentRegion->get();
|
auto region = currentRegion->get();
|
||||||
|
|
||||||
if (region->isGenerator())
|
if (region->isGenerator()) {
|
||||||
{
|
|
||||||
currentRegion++;
|
currentRegion++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fileInformation = filePool.getFileInformation(region->sample);
|
auto fileInformation = filePool.getFileInformation(region->sample);
|
||||||
if (!fileInformation)
|
if (!fileInformation) {
|
||||||
{
|
|
||||||
DBG("Removing the region with sample " << region->sample);
|
DBG("Removing the region with sample " << region->sample);
|
||||||
std::iter_swap(currentRegion, lastRegion);
|
std::iter_swap(currentRegion, lastRegion);
|
||||||
lastRegion--;
|
lastRegion--;
|
||||||
|
|
@ -159,8 +152,7 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename)
|
||||||
for (int ccIndex = 1; ccIndex < 128; ccIndex++)
|
for (int ccIndex = 1; ccIndex < 128; ccIndex++)
|
||||||
region->registerCC(region->channelRange.getStart(), ccIndex, ccState[ccIndex]);
|
region->registerCC(region->channelRange.getStart(), ccIndex, ccState[ccIndex]);
|
||||||
|
|
||||||
if (defaultSwitch)
|
if (defaultSwitch) {
|
||||||
{
|
|
||||||
region->registerNoteOn(region->channelRange.getStart(), *defaultSwitch, 127, 1.0);
|
region->registerNoteOn(region->channelRange.getStart(), *defaultSwitch, 127, 1.0);
|
||||||
region->registerNoteOff(region->channelRange.getStart(), *defaultSwitch, 0, 1.0);
|
region->registerNoteOff(region->channelRange.getStart(), *defaultSwitch, 0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@
|
||||||
#include "SfzHelpers.h"
|
#include "SfzHelpers.h"
|
||||||
#include "StereoSpan.h"
|
#include "StereoSpan.h"
|
||||||
#include "absl/types/span.h"
|
#include "absl/types/span.h"
|
||||||
|
#include <chrono>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <chrono>
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
|
|
@ -177,8 +177,7 @@ private:
|
||||||
std::thread garbageCollectionThread { [&]() {
|
std::thread garbageCollectionThread { [&]() {
|
||||||
while (!threadsShouldQuit) {
|
while (!threadsShouldQuit) {
|
||||||
auto activeVoices { 0 };
|
auto activeVoices { 0 };
|
||||||
for (auto& voice : voices)
|
for (auto& voice : voices) {
|
||||||
{
|
|
||||||
voice->garbageCollect();
|
voice->garbageCollect();
|
||||||
if (!voice->isFree())
|
if (!voice->isFree())
|
||||||
activeVoices++;
|
activeVoices++;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "ADSREnvelope.h"
|
#include "ADSREnvelope.h"
|
||||||
|
#include "Defaults.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Region.h"
|
#include "Region.h"
|
||||||
#include "SIMDHelpers.h"
|
#include "SIMDHelpers.h"
|
||||||
|
|
@ -7,7 +8,6 @@
|
||||||
#include "StereoBuffer.h"
|
#include "StereoBuffer.h"
|
||||||
#include "StereoSpan.h"
|
#include "StereoSpan.h"
|
||||||
#include "absl/types/span.h"
|
#include "absl/types/span.h"
|
||||||
#include "Defaults.h"
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|
@ -92,7 +92,6 @@ public:
|
||||||
if (ccState[64] < 63)
|
if (ccState[64] < 63)
|
||||||
egEnvelope.startRelease(delay);
|
egEnvelope.startRelease(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerCC(int delay [[maybe_unused]], int channel [[maybe_unused]], int ccNumber [[maybe_unused]], uint8_t ccValue [[maybe_unused]])
|
void registerCC(int delay [[maybe_unused]], int channel [[maybe_unused]], int ccNumber [[maybe_unused]], uint8_t ccValue [[maybe_unused]])
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
#include "../sources/ADSREnvelope.h"
|
#include "../sources/ADSREnvelope.h"
|
||||||
#include <array>
|
#include "catch2/catch.hpp"
|
||||||
#include <algorithm>
|
|
||||||
#include <iostream>
|
|
||||||
#include <absl/types/span.h>
|
|
||||||
#include <absl/algorithm/container.h>
|
#include <absl/algorithm/container.h>
|
||||||
|
#include <absl/types/span.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
|
|
@ -14,8 +14,7 @@ inline bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (size_t i = 0; i < rhs.size(); ++i)
|
for (size_t i = 0; i < rhs.size(); ++i)
|
||||||
if (rhs[i] != Approx(lhs[i]).epsilon(eps))
|
if (rhs[i] != Approx(lhs[i]).epsilon(eps)) {
|
||||||
{
|
|
||||||
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
#include "../sources/Synth.h"
|
#include "../sources/Synth.h"
|
||||||
|
#include "catch2/catch.hpp"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
|
|
@ -109,14 +109,12 @@ TEST_CASE("[Files] Define test")
|
||||||
REQUIRE(synth.getRegionView(2)->keyRange == Range<uint8_t>(42, 42));
|
REQUIRE(synth.getRegionView(2)->keyRange == Range<uint8_t>(42, 42));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("[Files] Group from AVL")
|
TEST_CASE("[Files] Group from AVL")
|
||||||
{
|
{
|
||||||
sfz::Synth synth;
|
sfz::Synth synth;
|
||||||
synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/groups_avl.sfz");
|
synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/groups_avl.sfz");
|
||||||
REQUIRE(synth.getNumRegions() == 5);
|
REQUIRE(synth.getNumRegions() == 5);
|
||||||
for (int i = 0; i < synth.getNumRegions(); ++i)
|
for (int i = 0; i < synth.getNumRegions(); ++i) {
|
||||||
{
|
|
||||||
REQUIRE(synth.getRegionView(i)->volume == 6.0f);
|
REQUIRE(synth.getRegionView(i)->volume == 6.0f);
|
||||||
REQUIRE(synth.getRegionView(i)->keyRange == Range<uint8_t>(36, 36));
|
REQUIRE(synth.getRegionView(i)->keyRange == Range<uint8_t>(36, 36));
|
||||||
}
|
}
|
||||||
|
|
@ -132,8 +130,7 @@ TEST_CASE("[Files] Full hierarchy")
|
||||||
sfz::Synth synth;
|
sfz::Synth synth;
|
||||||
synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/basic_hierarchy.sfz");
|
synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/basic_hierarchy.sfz");
|
||||||
REQUIRE(synth.getNumRegions() == 8);
|
REQUIRE(synth.getNumRegions() == 8);
|
||||||
for (int i = 0; i < synth.getNumRegions(); ++i)
|
for (int i = 0; i < synth.getNumRegions(); ++i) {
|
||||||
{
|
|
||||||
REQUIRE(synth.getRegionView(i)->width == 40.0f);
|
REQUIRE(synth.getRegionView(i)->width == 40.0f);
|
||||||
}
|
}
|
||||||
REQUIRE(synth.getRegionView(0)->pan == 30.0f);
|
REQUIRE(synth.getRegionView(0)->pan == 30.0f);
|
||||||
|
|
@ -214,8 +211,7 @@ TEST_CASE("[Files] Pizz basic")
|
||||||
sfz::Synth synth;
|
sfz::Synth synth;
|
||||||
synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/SpecificBugs/MeatBassPizz/Programs/pizz.sfz");
|
synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/SpecificBugs/MeatBassPizz/Programs/pizz.sfz");
|
||||||
REQUIRE(synth.getNumRegions() == 4);
|
REQUIRE(synth.getNumRegions() == 4);
|
||||||
for (int i = 0; i < synth.getNumRegions(); ++i)
|
for (int i = 0; i < synth.getNumRegions(); ++i) {
|
||||||
{
|
|
||||||
REQUIRE(synth.getRegionView(i)->keyRange == Range<uint8_t>(12, 22));
|
REQUIRE(synth.getRegionView(i)->keyRange == Range<uint8_t>(12, 22));
|
||||||
REQUIRE(synth.getRegionView(i)->velocityRange == Range<uint8_t>(97, 127));
|
REQUIRE(synth.getRegionView(i)->velocityRange == Range<uint8_t>(97, 127));
|
||||||
REQUIRE(synth.getRegionView(i)->pitchKeycenter == 21);
|
REQUIRE(synth.getRegionView(i)->pitchKeycenter == 21);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
#include "../sources/Helpers.h"
|
#include "../sources/Helpers.h"
|
||||||
|
#include "catch2/catch.hpp"
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
using namespace std::literals::string_view_literals;
|
using namespace std::literals::string_view_literals;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
#include "../sources/LinearEnvelope.h"
|
#include "../sources/LinearEnvelope.h"
|
||||||
#include <array>
|
#include "catch2/catch.hpp"
|
||||||
#include <algorithm>
|
|
||||||
#include <iostream>
|
|
||||||
#include <absl/types/span.h>
|
|
||||||
#include <absl/algorithm/container.h>
|
#include <absl/algorithm/container.h>
|
||||||
|
#include <absl/types/span.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
|
|
@ -14,8 +14,7 @@ inline bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (size_t i = 0; i < rhs.size(); ++i)
|
for (size_t i = 0; i < rhs.size(); ++i)
|
||||||
if (rhs[i] != Approx(lhs[i]).epsilon(eps))
|
if (rhs[i] != Approx(lhs[i]).epsilon(eps)) {
|
||||||
{
|
|
||||||
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
#include "../sources/OnePoleFilter.h"
|
#include "../sources/OnePoleFilter.h"
|
||||||
#include "catch2/catch.hpp"
|
#include "catch2/catch.hpp"
|
||||||
#include "cnpy.h"
|
#include "cnpy.h"
|
||||||
#include <string>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <absl/types/span.h>
|
#include <absl/types/span.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <string>
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
|
|
@ -14,8 +14,7 @@ inline bool approxEqual(const std::vector<Type>& lhs, const std::vector<Type>& r
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (size_t i = 0; i < rhs.size(); ++i)
|
for (size_t i = 0; i < rhs.size(); ++i)
|
||||||
if (lhs[i] != Approx(rhs[i]).epsilon(1e-3))
|
if (lhs[i] != Approx(rhs[i]).epsilon(1e-3)) {
|
||||||
{
|
|
||||||
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -98,28 +97,23 @@ TEST_CASE("[OnePoleFilter] Lowpass Float")
|
||||||
testLowpass<float>(
|
testLowpass<float>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy",
|
||||||
0.1f
|
0.1f);
|
||||||
);
|
|
||||||
testLowpass<float>(
|
testLowpass<float>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy",
|
||||||
0.3f
|
0.3f);
|
||||||
);
|
|
||||||
testLowpass<float>(
|
testLowpass<float>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy",
|
||||||
0.5f
|
0.5f);
|
||||||
);
|
|
||||||
testLowpass<float>(
|
testLowpass<float>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy",
|
||||||
0.7f
|
0.7f);
|
||||||
);
|
|
||||||
testLowpass<float>(
|
testLowpass<float>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy",
|
||||||
0.9f
|
0.9f);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[OnePoleFilter] Lowpass Double")
|
TEST_CASE("[OnePoleFilter] Lowpass Double")
|
||||||
|
|
@ -127,28 +121,23 @@ TEST_CASE("[OnePoleFilter] Lowpass Double")
|
||||||
testLowpass<double>(
|
testLowpass<double>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.1.npy",
|
||||||
0.1f
|
0.1f);
|
||||||
);
|
|
||||||
testLowpass<double>(
|
testLowpass<double>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.3.npy",
|
||||||
0.3f
|
0.3f);
|
||||||
);
|
|
||||||
testLowpass<double>(
|
testLowpass<double>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.5.npy",
|
||||||
0.5f
|
0.5f);
|
||||||
);
|
|
||||||
testLowpass<double>(
|
testLowpass<double>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.7.npy",
|
||||||
0.7f
|
0.7f);
|
||||||
);
|
|
||||||
testLowpass<double>(
|
testLowpass<double>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_low_gain_0.9.npy",
|
||||||
0.9f
|
0.9f);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[OnePoleFilter] Highpass Float")
|
TEST_CASE("[OnePoleFilter] Highpass Float")
|
||||||
|
|
@ -156,28 +145,23 @@ TEST_CASE("[OnePoleFilter] Highpass Float")
|
||||||
testHighpass<float>(
|
testHighpass<float>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy",
|
||||||
0.1f
|
0.1f);
|
||||||
);
|
|
||||||
testHighpass<float>(
|
testHighpass<float>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy",
|
||||||
0.3f
|
0.3f);
|
||||||
);
|
|
||||||
testHighpass<float>(
|
testHighpass<float>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy",
|
||||||
0.5f
|
0.5f);
|
||||||
);
|
|
||||||
testHighpass<float>(
|
testHighpass<float>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy",
|
||||||
0.7f
|
0.7f);
|
||||||
);
|
|
||||||
testHighpass<float>(
|
testHighpass<float>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy",
|
||||||
0.9f
|
0.9f);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[OnePoleFilter] Highpass Double")
|
TEST_CASE("[OnePoleFilter] Highpass Double")
|
||||||
|
|
@ -185,26 +169,21 @@ TEST_CASE("[OnePoleFilter] Highpass Double")
|
||||||
testHighpass<double>(
|
testHighpass<double>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.1.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.1.npy",
|
||||||
0.1f
|
0.1f);
|
||||||
);
|
|
||||||
testHighpass<double>(
|
testHighpass<double>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.3.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.3.npy",
|
||||||
0.3f
|
0.3f);
|
||||||
);
|
|
||||||
testHighpass<double>(
|
testHighpass<double>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.5.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.5.npy",
|
||||||
0.5f
|
0.5f);
|
||||||
);
|
|
||||||
testHighpass<double>(
|
testHighpass<double>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.7.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.7.npy",
|
||||||
0.7f
|
0.7f);
|
||||||
);
|
|
||||||
testHighpass<double>(
|
testHighpass<double>(
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_input_gain_0.9.npy",
|
||||||
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy",
|
std::filesystem::current_path() / "tests/TestFiles/OnePoleFilter/OPF_high_gain_0.9.npy",
|
||||||
0.9f
|
0.9f);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
#include "../sources/Region.h"
|
#include "../sources/Region.h"
|
||||||
|
#include "catch2/catch.hpp"
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
TEST_CASE("[Opcode] Construction")
|
TEST_CASE("[Opcode] Construction")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
#include "../sources/Parser.h"
|
#include "../sources/Parser.h"
|
||||||
|
#include "catch2/catch.hpp"
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
void includeTest(const std::string& line, const std::string& fileName)
|
void includeTest(const std::string& line, const std::string& fileName)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
#include "../sources/Region.h"
|
#include "../sources/Region.h"
|
||||||
|
#include "catch2/catch.hpp"
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
TEST_CASE("Region activation", "Region tests")
|
TEST_CASE("Region activation", "Region tests")
|
||||||
|
|
@ -219,7 +219,6 @@ TEST_CASE("Region activation", "Region tests")
|
||||||
REQUIRE(!region.isSwitchedOn());
|
REQUIRE(!region.isSwitchedOn());
|
||||||
region.registerNoteOff(1, 40, 0, 0.5f);
|
region.registerNoteOff(1, 40, 0, 0.5f);
|
||||||
REQUIRE(!region.isSwitchedOn());
|
REQUIRE(!region.isSwitchedOn());
|
||||||
|
|
||||||
}
|
}
|
||||||
SECTION("Sequences: length 2, position 2")
|
SECTION("Sequences: length 2, position 2")
|
||||||
{
|
{
|
||||||
|
|
@ -239,7 +238,6 @@ TEST_CASE("Region activation", "Region tests")
|
||||||
REQUIRE(region.isSwitchedOn());
|
REQUIRE(region.isSwitchedOn());
|
||||||
region.registerNoteOff(1, 40, 0, 0.5f);
|
region.registerNoteOff(1, 40, 0, 0.5f);
|
||||||
REQUIRE(region.isSwitchedOn());
|
REQUIRE(region.isSwitchedOn());
|
||||||
|
|
||||||
}
|
}
|
||||||
SECTION("Sequences: length 3, position 2")
|
SECTION("Sequences: length 3, position 2")
|
||||||
{
|
{
|
||||||
|
|
@ -265,4 +263,3 @@ TEST_CASE("Region activation", "Region tests")
|
||||||
REQUIRE(region.isSwitchedOn());
|
REQUIRE(region.isSwitchedOn());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
#include "../sources/Region.h"
|
#include "../sources/Region.h"
|
||||||
|
#include "catch2/catch.hpp"
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
TEST_CASE("[Region] Parsing opcodes")
|
TEST_CASE("[Region] Parsing opcodes")
|
||||||
|
|
@ -428,8 +428,7 @@ TEST_CASE("[Region] Parsing opcodes")
|
||||||
|
|
||||||
SECTION("on_locc, on_hicc")
|
SECTION("on_locc, on_hicc")
|
||||||
{
|
{
|
||||||
for (int ccIdx = 1; ccIdx < 128; ++ccIdx)
|
for (int ccIdx = 1; ccIdx < 128; ++ccIdx) {
|
||||||
{
|
|
||||||
REQUIRE(!region.ccTriggers.contains(ccIdx));
|
REQUIRE(!region.ccTriggers.contains(ccIdx));
|
||||||
}
|
}
|
||||||
region.parseOpcode({ "on_locc45", "15" });
|
region.parseOpcode({ "on_locc45", "15" });
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
#include "../sources/Region.h"
|
#include "../sources/Region.h"
|
||||||
|
#include "catch2/catch.hpp"
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
TEST_CASE("Basic triggers", "Region triggers")
|
TEST_CASE("Basic triggers", "Region triggers")
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
#include "../sources/SIMDHelpers.h"
|
#include "../sources/SIMDHelpers.h"
|
||||||
#include <array>
|
#include "catch2/catch.hpp"
|
||||||
#include <algorithm>
|
|
||||||
#include <iostream>
|
|
||||||
#include <absl/types/span.h>
|
|
||||||
#include <absl/algorithm/container.h>
|
#include <absl/algorithm/container.h>
|
||||||
|
#include <absl/types/span.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
constexpr int smallBufferSize { 3 };
|
constexpr int smallBufferSize { 3 };
|
||||||
|
|
@ -19,8 +19,7 @@ inline bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (size_t i = 0; i < rhs.size(); ++i)
|
for (size_t i = 0; i < rhs.size(); ++i)
|
||||||
if (rhs[i] != Approx(lhs[i]).epsilon(eps))
|
if (rhs[i] != Approx(lhs[i]).epsilon(eps)) {
|
||||||
{
|
|
||||||
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
std::cerr << lhs[i] << " != " << rhs[i] << " at index " << i << '\n';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +95,6 @@ TEST_CASE("[Helpers] fill() - Big buffer -- doubles")
|
||||||
REQUIRE(buffer == expected);
|
REQUIRE(buffer == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("[Helpers] Interleaved read")
|
TEST_CASE("[Helpers] Interleaved read")
|
||||||
{
|
{
|
||||||
std::array<float, 16> input { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f };
|
std::array<float, 16> input { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f };
|
||||||
|
|
@ -215,7 +213,16 @@ TEST_CASE("[Helpers] Interleaved read SIMD vs Scalar")
|
||||||
|
|
||||||
TEST_CASE("[Helpers] Interleaved write")
|
TEST_CASE("[Helpers] Interleaved write")
|
||||||
{
|
{
|
||||||
std::array<float, 8> leftInput { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, };
|
std::array<float, 8> leftInput {
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
2.0f,
|
||||||
|
3.0f,
|
||||||
|
4.0f,
|
||||||
|
5.0f,
|
||||||
|
6.0f,
|
||||||
|
7.0f,
|
||||||
|
};
|
||||||
std::array<float, 8> rightInput { 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f };
|
std::array<float, 8> rightInput { 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f };
|
||||||
std::array<float, 16> output;
|
std::array<float, 16> output;
|
||||||
std::array<float, 16> expected { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f };
|
std::array<float, 16> expected { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f };
|
||||||
|
|
@ -245,7 +252,16 @@ TEST_CASE("[Helpers] Small interleaved write unaligned end")
|
||||||
|
|
||||||
TEST_CASE("[Helpers] Interleaved write -- SIMD")
|
TEST_CASE("[Helpers] Interleaved write -- SIMD")
|
||||||
{
|
{
|
||||||
std::array<float, 8> leftInput { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, };
|
std::array<float, 8> leftInput {
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
2.0f,
|
||||||
|
3.0f,
|
||||||
|
4.0f,
|
||||||
|
5.0f,
|
||||||
|
6.0f,
|
||||||
|
7.0f,
|
||||||
|
};
|
||||||
std::array<float, 8> rightInput { 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f };
|
std::array<float, 8> rightInput { 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f };
|
||||||
std::array<float, 16> output;
|
std::array<float, 16> output;
|
||||||
std::array<float, 16> expected { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f };
|
std::array<float, 16> expected { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f };
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
#include "../sources/StereoBuffer.h"
|
#include "../sources/StereoBuffer.h"
|
||||||
|
#include "catch2/catch.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
|
|
@ -33,14 +33,12 @@ TEST_CASE("[StereoBuffer] Access")
|
||||||
{
|
{
|
||||||
const int size { 5 };
|
const int size { 5 };
|
||||||
StereoBuffer<double> doubleBuffer(size);
|
StereoBuffer<double> doubleBuffer(size);
|
||||||
for (auto frameIdx = 0; frameIdx < doubleBuffer.getNumFrames(); ++frameIdx)
|
for (auto frameIdx = 0; frameIdx < doubleBuffer.getNumFrames(); ++frameIdx) {
|
||||||
{
|
|
||||||
doubleBuffer.getSample(Channel::left, frameIdx) = static_cast<double>(doubleBuffer.getNumFrames()) + frameIdx;
|
doubleBuffer.getSample(Channel::left, frameIdx) = static_cast<double>(doubleBuffer.getNumFrames()) + frameIdx;
|
||||||
doubleBuffer.getSample(Channel::right, frameIdx) = static_cast<double>(doubleBuffer.getNumFrames()) - frameIdx;
|
doubleBuffer.getSample(Channel::right, frameIdx) = static_cast<double>(doubleBuffer.getNumFrames()) - frameIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto frameIdx = 0; frameIdx < doubleBuffer.getNumFrames(); ++frameIdx)
|
for (auto frameIdx = 0; frameIdx < doubleBuffer.getNumFrames(); ++frameIdx) {
|
||||||
{
|
|
||||||
REQUIRE(doubleBuffer.getSample(Channel::left, frameIdx) == static_cast<double>(doubleBuffer.getNumFrames()) + frameIdx);
|
REQUIRE(doubleBuffer.getSample(Channel::left, frameIdx) == static_cast<double>(doubleBuffer.getNumFrames()) + frameIdx);
|
||||||
REQUIRE(doubleBuffer(Channel::left, frameIdx) == static_cast<double>(doubleBuffer.getNumFrames()) + frameIdx);
|
REQUIRE(doubleBuffer(Channel::left, frameIdx) == static_cast<double>(doubleBuffer.getNumFrames()) + frameIdx);
|
||||||
REQUIRE(doubleBuffer.getSample(Channel::right, frameIdx) == static_cast<double>(doubleBuffer.getNumFrames()) - frameIdx);
|
REQUIRE(doubleBuffer.getSample(Channel::right, frameIdx) == static_cast<double>(doubleBuffer.getNumFrames()) - frameIdx);
|
||||||
|
|
@ -147,7 +145,6 @@ TEST_CASE("[AudioBuffer] fills")
|
||||||
REQUIRE(real == expected);
|
REQUIRE(real == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("[AudioBuffer] Fill a big Audiobuffer")
|
TEST_CASE("[AudioBuffer] Fill a big Audiobuffer")
|
||||||
{
|
{
|
||||||
constexpr int size { 2039247 };
|
constexpr int size { 2039247 };
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue