Included buffer and prelim work for the FilePool
This commit is contained in:
parent
d1343ef6f5
commit
7922c98c7f
13 changed files with 459 additions and 22 deletions
|
|
@ -25,6 +25,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|||
set(COMMON_SOURCES
|
||||
sources/Opcode.cpp
|
||||
sources/Synth.cpp
|
||||
sources/FilePool.cpp
|
||||
sources/Region.cpp
|
||||
sources/Parser.cpp
|
||||
)
|
||||
|
|
@ -39,6 +40,8 @@ set(TEST_SOURCES
|
|||
tests/Region.cpp
|
||||
tests/Range.cpp
|
||||
tests/Opcode.cpp
|
||||
tests/Buffer.cpp
|
||||
tests/AudioBuffer.cpp
|
||||
tests/Files.cpp
|
||||
tests/Main.cpp
|
||||
)
|
||||
|
|
|
|||
116
sources/AudioBuffer.h
Normal file
116
sources/AudioBuffer.h
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
#pragma once
|
||||
#include "Buffer.h"
|
||||
#include "Helpers.h"
|
||||
#include "Globals.h"
|
||||
|
||||
template<class Type, unsigned int NumChannels = sfz::Config::numChannels, unsigned int Alignment = sfz::Config::defaultAlignment>
|
||||
|
||||
class AudioBuffer
|
||||
{
|
||||
public:
|
||||
AudioBuffer() = default;
|
||||
|
||||
AudioBuffer(int numFrames)
|
||||
{
|
||||
resize(numFrames);
|
||||
}
|
||||
|
||||
bool resize(int numFrames)
|
||||
{
|
||||
// should have a positive number of frames...
|
||||
ASSERT(numFrames >= 0);
|
||||
if (buffer.resize(static_cast<size_t>(NumChannels * numFrames)))
|
||||
{
|
||||
this->numFrames = numFrames;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Type& getSample(int channelIndex, int sampleIndex) noexcept
|
||||
{
|
||||
ASSERT(channelIndex >= 0);
|
||||
ASSERT(sampleIndex >= 0);
|
||||
return *(buffer.data() + numFrames * channelIndex + sampleIndex);
|
||||
}
|
||||
|
||||
Type* getChannel(int channelIndex) noexcept
|
||||
{
|
||||
ASSERT(channelIndex >= 0);
|
||||
if (channelIndex < NumChannels)
|
||||
return buffer.data() + numFrames * channelIndex;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Type& operator()(int channelIndex, int sampleIndex) noexcept
|
||||
{
|
||||
return getSample(channelIndex, sampleIndex);
|
||||
}
|
||||
|
||||
int getNumFrames() const noexcept { return numFrames; }
|
||||
int getNumChannels() const noexcept { return NumChannels; }
|
||||
bool empty() const noexcept { return numFrames == 0; }
|
||||
|
||||
private:
|
||||
int numFrames { 0 };
|
||||
Buffer<Type, Alignment> buffer {};
|
||||
};
|
||||
|
||||
template<class Type, unsigned int NumChannels = sfz::Config::numChannels, unsigned int Alignment = sfz::Config::defaultAlignment>
|
||||
class SplitAudioBuffer
|
||||
{
|
||||
public:
|
||||
SplitAudioBuffer() = default;
|
||||
SplitAudioBuffer(int numFrames)
|
||||
{
|
||||
resize(numFrames);
|
||||
}
|
||||
|
||||
bool resize(int numFrames)
|
||||
{
|
||||
// should have a positive number of frames...
|
||||
ASSERT(numFrames >= 0);
|
||||
bool resizedOK = true;
|
||||
|
||||
for (auto& buffer: buffers)
|
||||
resizedOK &= buffer.resize(static_cast<size_t>(numFrames));
|
||||
|
||||
if (resizedOK)
|
||||
this->numFrames = numFrames;
|
||||
else
|
||||
this->numFrames = std::min(numFrames, this->numFrames);
|
||||
|
||||
return resizedOK;
|
||||
}
|
||||
|
||||
Type& getSample(int channelIndex, int sampleIndex) noexcept
|
||||
{
|
||||
ASSERT(channelIndex >= 0);
|
||||
ASSERT(sampleIndex >= 0);
|
||||
return *(buffers[channelIndex].data() + sampleIndex);
|
||||
}
|
||||
|
||||
Type& operator()(int channelIndex, int sampleIndex) noexcept
|
||||
{
|
||||
return getSample(channelIndex, sampleIndex);
|
||||
}
|
||||
|
||||
Type* getChannel(int channelIndex) noexcept
|
||||
{
|
||||
ASSERT(channelIndex >= 0);
|
||||
if (channelIndex < NumChannels)
|
||||
return &buffers[channelIndex].data();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int getNumFrames() const noexcept { return numFrames; }
|
||||
int getNumChannels() const noexcept { return NumChannels; }
|
||||
bool empty() const noexcept { return numFrames == 0; }
|
||||
|
||||
private:
|
||||
int numFrames { 0 };
|
||||
std::array<Buffer<Type, Alignment>, NumChannels> buffers;
|
||||
};
|
||||
|
|
@ -1,20 +1,64 @@
|
|||
#pragma once
|
||||
#include "Globals.h"
|
||||
#include <type_traits>
|
||||
template<class Type>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
template<class Type, unsigned int Alignment = sfz::Config::defaultAlignment>
|
||||
class Buffer
|
||||
{
|
||||
static_assert(std::is_arithmetic<Type>::value, "Type should be arithmetic");
|
||||
static_assert(Alignment == 0 || Alignment == 4 || Alignment == 8 || Alignment == 16, "Bad alignment value");
|
||||
public:
|
||||
Buffer()
|
||||
Buffer() { }
|
||||
Buffer(size_t size)
|
||||
{
|
||||
resize(size);
|
||||
}
|
||||
bool resize(size_t newSize)
|
||||
{
|
||||
if (newSize == 0)
|
||||
{
|
||||
clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
auto tempSize = newSize + Alignment;
|
||||
auto* newData = largerData != nullptr ? std::realloc(largerData, tempSize * sizeof(Type)) : std::malloc(tempSize * sizeof(Type));
|
||||
if (newData == nullptr)
|
||||
return false;
|
||||
|
||||
largerSize = tempSize;
|
||||
alignedSize = newSize;
|
||||
largerData = static_cast<Type*>(newData);
|
||||
alignedData = static_cast<Type*>(std::align(Alignment, alignedSize, newData, tempSize));
|
||||
return true;
|
||||
}
|
||||
|
||||
Type* data() { return alignedData; }
|
||||
void clear()
|
||||
{
|
||||
std::free(largerData);
|
||||
largerSize = 0;
|
||||
alignedSize = 0;
|
||||
alignedData = nullptr;
|
||||
}
|
||||
~Buffer()
|
||||
{
|
||||
|
||||
std::free(largerData);
|
||||
}
|
||||
|
||||
Type& operator[](int idx) { return *(alignedData + idx); }
|
||||
size_t size() const noexcept { return alignedSize; }
|
||||
bool empty() const noexcept { return alignedSize == 0; }
|
||||
|
||||
Type* begin() noexcept { return data(); }
|
||||
Type* end() noexcept { return data() + alignedSize; }
|
||||
const Type* cbegin() const noexcept { return data(); }
|
||||
const Type* cend() const noexcept { return data() + alignedSize; }
|
||||
private:
|
||||
size_t realSize;
|
||||
size_t alignment;
|
||||
Type* data;
|
||||
size_t largerSize { 0 };
|
||||
size_t alignedSize { 0 };
|
||||
Type* largerData { nullptr };
|
||||
Type* alignedData { nullptr };
|
||||
};
|
||||
1
sources/FilePool.cpp
Normal file
1
sources/FilePool.cpp
Normal file
|
|
@ -0,0 +1 @@
|
|||
#include "FilePool.h"
|
||||
17
sources/FilePool.h
Normal file
17
sources/FilePool.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
#include "AudioBuffer.h"
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <string_view>
|
||||
|
||||
namespace sfz
|
||||
{
|
||||
class FilePool
|
||||
{
|
||||
public:
|
||||
FilePool() = default;
|
||||
private:
|
||||
std::filesystem::path rootDirectory;
|
||||
std::map<std::string_view, std::shared_ptr<AudioBuffer<float>>> preloadedData;
|
||||
};
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ namespace Config
|
|||
inline constexpr double fastReleaseDuration { 0.01 };
|
||||
inline constexpr char defineCharacter { '$' };
|
||||
inline constexpr int oversamplingFactor { 2 };
|
||||
inline constexpr unsigned int defaultAlignment { 16 };
|
||||
} // namespace config
|
||||
|
||||
} // namespace sfz
|
||||
|
|
@ -33,5 +33,10 @@ int main(int argc, char** argv)
|
|||
std::cout << "Defines:" << '\n';
|
||||
for (auto& define: synth.getDefines())
|
||||
std::cout << '\t' << define.first << '=' << define.second << '\n';
|
||||
std::cout << "==========" << '\n';
|
||||
std::cout << "Unknown opcodes:";
|
||||
for (auto& opcode: synth.getUnknownOpcodes())
|
||||
std::cout << opcode << ',';
|
||||
std::cout << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#include "Helpers.h"
|
||||
#include "absl/strings/str_replace.h"
|
||||
|
||||
void sfz::Region::parseOpcode(const Opcode& opcode)
|
||||
bool sfz::Region::parseOpcode(const Opcode& opcode)
|
||||
{
|
||||
switch (hash(opcode.opcode))
|
||||
{
|
||||
|
|
@ -237,7 +237,41 @@ void sfz::Region::parseOpcode(const Opcode& opcode)
|
|||
case hash("ampeg_vel2depth"):
|
||||
break;
|
||||
default:
|
||||
std::string opcodeStr { opcode.opcode.begin(), opcode.opcode.end() };
|
||||
unknownOpcodes.push_back(opcodeStr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sfz::Region::prepare()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool sfz::Region::isSwitchedOn() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool sfz::Region::registerNoteOff(int channel, int noteNumber, uint8_t velocity, float randValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool sfz::Region::registerCC(int channel, int ccNumber, uint8_t ccValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
void sfz::Region::registerPitchWheel(int channel, int pitch)
|
||||
{
|
||||
|
||||
}
|
||||
void sfz::Region::registerAftertouch(int channel, uint8_t aftertouch)
|
||||
{
|
||||
|
||||
}
|
||||
void sfz::Region::registerTempo(float secondsPerQuarter)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -10,7 +10,19 @@ namespace sfz
|
|||
{
|
||||
struct Region
|
||||
{
|
||||
void parseOpcode(const Opcode& opcode);
|
||||
bool isRelease() const noexcept { return trigger == SfzTrigger::release || trigger == SfzTrigger::release_key; }
|
||||
bool isGenerator() const noexcept { return sample.size() > 0 ? sample[0] == '*' : false; }
|
||||
bool shouldLoop() const noexcept { return (loopMode == SfzLoopMode::loop_continuous || loopMode == SfzLoopMode::loop_sustain); }
|
||||
bool isSwitchedOn() const noexcept;
|
||||
bool registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue);
|
||||
bool registerNoteOff(int channel, int noteNumber, uint8_t velocity, float randValue);
|
||||
bool registerCC(int channel, int ccNumber, uint8_t ccValue);
|
||||
void registerPitchWheel(int channel, int pitch);
|
||||
void registerAftertouch(int channel, uint8_t aftertouch);
|
||||
void registerTempo(float secondsPerQuarter);
|
||||
bool prepare();
|
||||
bool isStereo() const noexcept;
|
||||
bool parseOpcode(const Opcode& opcode);
|
||||
// Sound source: sample playback
|
||||
std::string sample {}; // Sample
|
||||
float delay { Default::delay }; // delay
|
||||
|
|
@ -93,7 +105,5 @@ struct Region
|
|||
|
||||
double sampleRate { Config::defaultSampleRate };
|
||||
int numChannels { 1 };
|
||||
|
||||
std::vector<std::string> unknownOpcodes;
|
||||
};
|
||||
} // namespace sfz
|
||||
|
|
@ -43,14 +43,17 @@ void sfz::Synth::callback(std::string_view header, std::vector<Opcode> members)
|
|||
void sfz::Synth::buildRegion(const std::vector<Opcode>& regionOpcodes)
|
||||
{
|
||||
auto& lastRegion = regions.emplace_back();
|
||||
for (auto& opcode: globalOpcodes)
|
||||
lastRegion.parseOpcode(opcode);
|
||||
for (auto& opcode: masterOpcodes)
|
||||
lastRegion.parseOpcode(opcode);
|
||||
for (auto& opcode: groupOpcodes)
|
||||
lastRegion.parseOpcode(opcode);
|
||||
for (auto& opcode: regionOpcodes)
|
||||
lastRegion.parseOpcode(opcode);
|
||||
|
||||
auto parseOpcodes = [&](const auto& opcodes) {
|
||||
for (auto& opcode: opcodes)
|
||||
if (!lastRegion.parseOpcode(opcode))
|
||||
unknownOpcodes.insert(opcode.opcode);
|
||||
};
|
||||
|
||||
parseOpcodes(globalOpcodes);
|
||||
parseOpcodes(masterOpcodes);
|
||||
parseOpcodes(groupOpcodes);
|
||||
parseOpcodes(regionOpcodes);
|
||||
}
|
||||
|
||||
void sfz::Synth::clear()
|
||||
|
|
@ -107,4 +110,4 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename)
|
|||
{
|
||||
clear();
|
||||
return sfz::Parser::loadSfzFile(filename);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "Region.h"
|
||||
#include "SfzHelpers.h"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
|
|
@ -18,6 +19,7 @@ public:
|
|||
int getNumMasters() const noexcept { return numMasters; }
|
||||
int getNumCurves() const noexcept { return numCurves; }
|
||||
const Region* getRegionView(int idx) const noexcept { return idx < regions.size() ? ®ions[idx] : nullptr; }
|
||||
auto getUnknownOpcodes() { return unknownOpcodes; }
|
||||
protected:
|
||||
void callback(std::string_view header, std::vector<Opcode> members) final;
|
||||
private:
|
||||
|
|
@ -36,7 +38,7 @@ private:
|
|||
CCValueArray ccState;
|
||||
std::vector<CCNamePair> ccNames;
|
||||
std::optional<uint8_t> defaultSwitch;
|
||||
|
||||
std::set<std::string_view> unknownOpcodes;
|
||||
std::vector<Region> regions;
|
||||
void buildRegion(const std::vector<Opcode>& regionOpcodes);
|
||||
};
|
||||
|
|
|
|||
94
tests/AudioBuffer.cpp
Normal file
94
tests/AudioBuffer.cpp
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#include "catch2/catch.hpp"
|
||||
#include "../sources/AudioBuffer.h"
|
||||
#include <algorithm>
|
||||
using namespace Catch::literals;
|
||||
|
||||
TEST_CASE("[AudioBuffer/SplitBuffer] Empty buffers")
|
||||
{
|
||||
AudioBuffer<float> floatBuffer;
|
||||
REQUIRE(floatBuffer.empty());
|
||||
REQUIRE(floatBuffer.getNumFrames() == 0);
|
||||
AudioBuffer<double> doubleBuffer;
|
||||
REQUIRE(doubleBuffer.empty());
|
||||
REQUIRE(doubleBuffer.getNumFrames() == 0);
|
||||
AudioBuffer<int> intBuffer;
|
||||
REQUIRE(intBuffer.empty());
|
||||
REQUIRE(intBuffer.getNumFrames() == 0);
|
||||
|
||||
SplitAudioBuffer<float> floatSplitBuffer;
|
||||
REQUIRE(floatSplitBuffer.empty());
|
||||
REQUIRE(floatSplitBuffer.getNumFrames() == 0);
|
||||
SplitAudioBuffer<double> doubleSplitBuffer;
|
||||
REQUIRE(doubleSplitBuffer.empty());
|
||||
REQUIRE(doubleSplitBuffer.getNumFrames() == 0);
|
||||
SplitAudioBuffer<int> intSplitBuffer;
|
||||
REQUIRE(intSplitBuffer.empty());
|
||||
REQUIRE(intSplitBuffer.getNumFrames() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[AudioBuffer/SplitBuffer] Non-empty")
|
||||
{
|
||||
AudioBuffer<float> floatBuffer(10);
|
||||
REQUIRE(!floatBuffer.empty());
|
||||
REQUIRE(floatBuffer.getNumFrames() == 10);
|
||||
AudioBuffer<double> doubleBuffer(10);
|
||||
REQUIRE(!doubleBuffer.empty());
|
||||
REQUIRE(doubleBuffer.getNumFrames() == 10);
|
||||
AudioBuffer<int> intBuffer(10);
|
||||
REQUIRE(!intBuffer.empty());
|
||||
REQUIRE(intBuffer.getNumFrames() == 10);
|
||||
|
||||
SplitAudioBuffer<float> floatSplitBuffer(10);
|
||||
REQUIRE(!floatSplitBuffer.empty());
|
||||
REQUIRE(floatSplitBuffer.getNumFrames() == 10);
|
||||
SplitAudioBuffer<double> doubleSplitBuffer(10);
|
||||
REQUIRE(!doubleSplitBuffer.empty());
|
||||
REQUIRE(doubleSplitBuffer.getNumFrames() == 10);
|
||||
SplitAudioBuffer<int> intSplitBuffer(10);
|
||||
REQUIRE(!intSplitBuffer.empty());
|
||||
REQUIRE(intSplitBuffer.getNumFrames() == 10);
|
||||
}
|
||||
|
||||
TEST_CASE("[AudioBuffer/SplitBuffer] Access")
|
||||
{
|
||||
const int size { 5 };
|
||||
AudioBuffer<double> doubleBuffer(size);
|
||||
for (auto chanIdx = 0; chanIdx < doubleBuffer.getNumChannels(); ++chanIdx)
|
||||
for (auto frameIdx = 0; frameIdx < doubleBuffer.getNumFrames(); ++frameIdx)
|
||||
doubleBuffer.getSample(chanIdx, frameIdx) = static_cast<double>(doubleBuffer.getNumFrames()) * chanIdx + frameIdx;
|
||||
|
||||
for (auto chanIdx = 0; chanIdx < doubleBuffer.getNumChannels(); ++chanIdx)
|
||||
for (auto frameIdx = 0; frameIdx < doubleBuffer.getNumFrames(); ++frameIdx)
|
||||
REQUIRE(doubleBuffer.getSample(chanIdx, frameIdx) == static_cast<double>(doubleBuffer.getNumFrames()) * chanIdx + frameIdx);
|
||||
|
||||
SplitAudioBuffer<double> splitDoubleBuffer(size);
|
||||
for (auto chanIdx = 0; chanIdx < splitDoubleBuffer.getNumChannels(); ++chanIdx)
|
||||
for (auto frameIdx = 0; frameIdx < splitDoubleBuffer.getNumFrames(); ++frameIdx)
|
||||
splitDoubleBuffer.getSample(chanIdx, frameIdx) = static_cast<double>(splitDoubleBuffer.getNumFrames()) * chanIdx + frameIdx;
|
||||
|
||||
for (auto chanIdx = 0; chanIdx < splitDoubleBuffer.getNumChannels(); ++chanIdx)
|
||||
for (auto frameIdx = 0; frameIdx < splitDoubleBuffer.getNumFrames(); ++frameIdx)
|
||||
REQUIRE(splitDoubleBuffer.getSample(chanIdx, frameIdx) == static_cast<double>(splitDoubleBuffer.getNumFrames()) * chanIdx + frameIdx);
|
||||
}
|
||||
|
||||
TEST_CASE("[AudioBuffer/SplitBuffer] Access 2")
|
||||
{
|
||||
const int size { 5 };
|
||||
AudioBuffer<int> doubleBuffer(size);
|
||||
for (auto chanIdx = 0; chanIdx < doubleBuffer.getNumChannels(); ++chanIdx)
|
||||
for (auto frameIdx = 0; frameIdx < doubleBuffer.getNumFrames(); ++frameIdx)
|
||||
doubleBuffer(chanIdx, frameIdx) = static_cast<int>(doubleBuffer.getNumFrames()) * chanIdx + frameIdx;
|
||||
|
||||
for (auto chanIdx = 0; chanIdx < doubleBuffer.getNumChannels(); ++chanIdx)
|
||||
for (auto frameIdx = 0; frameIdx < doubleBuffer.getNumFrames(); ++frameIdx)
|
||||
REQUIRE(doubleBuffer(chanIdx, frameIdx) == static_cast<int>(doubleBuffer.getNumFrames()) * chanIdx + frameIdx);
|
||||
|
||||
SplitAudioBuffer<int> splitDoubleBuffer(size);
|
||||
for (auto chanIdx = 0; chanIdx < splitDoubleBuffer.getNumChannels(); ++chanIdx)
|
||||
for (auto frameIdx = 0; frameIdx < splitDoubleBuffer.getNumFrames(); ++frameIdx)
|
||||
splitDoubleBuffer(chanIdx, frameIdx) = static_cast<int>(splitDoubleBuffer.getNumFrames()) * chanIdx + frameIdx;
|
||||
|
||||
for (auto chanIdx = 0; chanIdx < splitDoubleBuffer.getNumChannels(); ++chanIdx)
|
||||
for (auto frameIdx = 0; frameIdx < splitDoubleBuffer.getNumFrames(); ++frameIdx)
|
||||
REQUIRE(splitDoubleBuffer(chanIdx, frameIdx) == static_cast<int>(splitDoubleBuffer.getNumFrames()) * chanIdx + frameIdx);
|
||||
}
|
||||
107
tests/Buffer.cpp
Normal file
107
tests/Buffer.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#include "catch2/catch.hpp"
|
||||
#include "../sources/Buffer.h"
|
||||
#include <algorithm>
|
||||
using namespace Catch::literals;
|
||||
|
||||
TEST_CASE("[Buffer] Empty (float)")
|
||||
{
|
||||
Buffer<float> emptyBuffer;
|
||||
REQUIRE(emptyBuffer.empty());
|
||||
REQUIRE(emptyBuffer.size() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[Buffer] Empty (int)")
|
||||
{
|
||||
Buffer<int> emptyBuffer;
|
||||
REQUIRE(emptyBuffer.empty());
|
||||
REQUIRE(emptyBuffer.size() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[Buffer] Empty (double)")
|
||||
{
|
||||
Buffer<double> emptyBuffer;
|
||||
REQUIRE(emptyBuffer.empty());
|
||||
REQUIRE(emptyBuffer.size() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[Buffer] Empty (uint8_t)")
|
||||
{
|
||||
Buffer<uint8_t> emptyBuffer;
|
||||
REQUIRE(emptyBuffer.empty());
|
||||
REQUIRE(emptyBuffer.size() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[Buffer] 10 floats ")
|
||||
{
|
||||
Buffer<float> buffer(10);
|
||||
REQUIRE(!buffer.empty());
|
||||
REQUIRE(buffer.size() == 10);
|
||||
REQUIRE(((size_t)buffer.data() & (sfz::Config::defaultAlignment - 1)) == 0);
|
||||
for (auto& element: buffer)
|
||||
element = 0.0f;
|
||||
for (auto& element: buffer)
|
||||
REQUIRE(element == 0.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("[Buffer] Resize 10 floats ")
|
||||
{
|
||||
const int baseSize { 10 };
|
||||
const int smallSize { baseSize / 2 };
|
||||
const int bigSize { baseSize * 2 };
|
||||
Buffer<float> buffer(baseSize);
|
||||
REQUIRE(!buffer.empty());
|
||||
REQUIRE(buffer.size() == baseSize);
|
||||
REQUIRE(((size_t)buffer.data() & (sfz::Config::defaultAlignment - 1)) == 0);
|
||||
std::fill(buffer.begin(), buffer.end(), 1.0f);
|
||||
REQUIRE( buffer.resize(smallSize) );
|
||||
REQUIRE( buffer.size() == smallSize );
|
||||
REQUIRE(((size_t)buffer.data() & (sfz::Config::defaultAlignment - 1)) == 0);
|
||||
REQUIRE( std::all_of(buffer.begin(), buffer.end(), [](auto value) { return value == 1.0f; }) );
|
||||
REQUIRE( buffer.resize(bigSize) );
|
||||
REQUIRE( buffer.size() == bigSize );
|
||||
REQUIRE(((size_t)buffer.data() & (sfz::Config::defaultAlignment - 1)) == 0);
|
||||
for (auto i = 0; i < smallSize; ++i)
|
||||
REQUIRE(buffer[i] == 1.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("[Buffer] Resize 4096 floats ")
|
||||
{
|
||||
const int baseSize { 10 };
|
||||
const int smallSize { baseSize / 2 };
|
||||
const int bigSize { baseSize * 2 };
|
||||
Buffer<float> buffer(baseSize);
|
||||
REQUIRE(!buffer.empty());
|
||||
REQUIRE(buffer.size() == baseSize);
|
||||
REQUIRE(((size_t)buffer.data() & (sfz::Config::defaultAlignment - 1)) == 0);
|
||||
std::fill(buffer.begin(), buffer.end(), 1.0f);
|
||||
REQUIRE( buffer.resize(smallSize) );
|
||||
REQUIRE( buffer.size() == smallSize );
|
||||
REQUIRE(((size_t)buffer.data() & (sfz::Config::defaultAlignment - 1)) == 0);
|
||||
REQUIRE( std::all_of(buffer.begin(), buffer.end(), [](auto value) { return value == 1.0f; }) );
|
||||
REQUIRE( buffer.resize(bigSize) );
|
||||
REQUIRE( buffer.size() == bigSize );
|
||||
REQUIRE(((size_t)buffer.data() & (sfz::Config::defaultAlignment - 1)) == 0);
|
||||
for (auto i = 0; i < smallSize; ++i)
|
||||
REQUIRE(buffer[i] == 1.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("[Buffer] Resize 65536 floats ")
|
||||
{
|
||||
const int baseSize { 10 };
|
||||
const int smallSize { baseSize / 2 };
|
||||
const int bigSize { baseSize * 2 };
|
||||
Buffer<float> buffer(baseSize);
|
||||
REQUIRE(!buffer.empty());
|
||||
REQUIRE(buffer.size() == baseSize);
|
||||
REQUIRE(((size_t)buffer.data() & (sfz::Config::defaultAlignment - 1)) == 0);
|
||||
std::fill(buffer.begin(), buffer.end(), 1.0f);
|
||||
REQUIRE( buffer.resize(smallSize) );
|
||||
REQUIRE( buffer.size() == smallSize );
|
||||
REQUIRE(((size_t)buffer.data() & (sfz::Config::defaultAlignment - 1)) == 0);
|
||||
REQUIRE( std::all_of(buffer.begin(), buffer.end(), [](auto value) { return value == 1.0f; }) );
|
||||
REQUIRE( buffer.resize(bigSize) );
|
||||
REQUIRE( buffer.size() == bigSize );
|
||||
REQUIRE(((size_t)buffer.data() & (sfz::Config::defaultAlignment - 1)) == 0);
|
||||
for (auto i = 0; i < smallSize; ++i)
|
||||
REQUIRE(buffer[i] == 1.0f);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue