Parse <sample> with base64 data
Also added the necessary plumbing to load from RAM It's missing AIFF since the API is file-based for now.
This commit is contained in:
parent
2aab560f39
commit
803052b552
23 changed files with 1910 additions and 248 deletions
105
external/st_audiofile/src/st_audiofile.c
vendored
105
external/st_audiofile/src/st_audiofile.c
vendored
|
|
@ -177,6 +177,111 @@ static st_audio_file* st_generic_open_file(const void* filename, int widepath)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
st_audio_file* st_open_memory(const void* memory, size_t length)
|
||||
{
|
||||
st_audio_file* af = (st_audio_file*)malloc(sizeof(st_audio_file));
|
||||
if (!af)
|
||||
return NULL;
|
||||
|
||||
// Try WAV
|
||||
{
|
||||
af->wav = (drwav*)malloc(sizeof(drwav));
|
||||
if (!af->wav) {
|
||||
free(af);
|
||||
return NULL;
|
||||
}
|
||||
drwav_bool32 ok =
|
||||
drwav_init_memory(af->wav, memory, length, NULL);
|
||||
if (!ok)
|
||||
free(af->wav);
|
||||
else {
|
||||
af->type = st_audio_file_wav;
|
||||
return af;
|
||||
}
|
||||
}
|
||||
|
||||
// Try FLAC
|
||||
{
|
||||
af->flac =
|
||||
drflac_open_memory(memory, length, NULL);
|
||||
if (af->flac) {
|
||||
af->type = st_audio_file_flac;
|
||||
return af;
|
||||
}
|
||||
}
|
||||
|
||||
// Try OGG
|
||||
{
|
||||
int err = 0;
|
||||
char* alloc_buffer = NULL;
|
||||
int alloc_size = 0;
|
||||
const int alloc_max_size = 16 * 1024 * 1024;
|
||||
|
||||
af->alloc.ogg.alloc_buffer = NULL;
|
||||
af->alloc.ogg.alloc_buffer_length_in_bytes = 0;
|
||||
|
||||
int try_again;
|
||||
do {
|
||||
af->ogg =
|
||||
stb_vorbis_open_memory(memory, length, &err, &af->alloc.ogg);
|
||||
try_again = 0;
|
||||
if (!af->ogg && err == VORBIS_outofmem) {
|
||||
int next_size = alloc_size ? (int)(alloc_size * 3L / 2) : (128 * 1024);
|
||||
if (next_size <= alloc_max_size) {
|
||||
free(alloc_buffer);
|
||||
alloc_size = next_size;
|
||||
alloc_buffer = (char*)malloc(alloc_size);
|
||||
af->alloc.ogg.alloc_buffer = alloc_buffer;
|
||||
af->alloc.ogg.alloc_buffer_length_in_bytes = alloc_size;
|
||||
try_again = alloc_buffer != NULL;
|
||||
}
|
||||
}
|
||||
} while (try_again);
|
||||
|
||||
if (!af->ogg)
|
||||
free(alloc_buffer);
|
||||
else {
|
||||
af->cache.ogg.frames = stb_vorbis_stream_length_in_samples(af->ogg);
|
||||
if (af->cache.ogg.frames == 0) {
|
||||
stb_vorbis_close(af->ogg);
|
||||
free(alloc_buffer);
|
||||
free(af);
|
||||
return NULL;
|
||||
}
|
||||
stb_vorbis_info info = stb_vorbis_get_info(af->ogg);
|
||||
af->cache.ogg.channels = info.channels;
|
||||
af->cache.ogg.sample_rate = info.sample_rate;
|
||||
af->type = st_audio_file_ogg;
|
||||
return af;
|
||||
}
|
||||
}
|
||||
|
||||
// Try MP3
|
||||
{
|
||||
af->mp3 = (drmp3*)malloc(sizeof(drmp3));
|
||||
if (!af->mp3) {
|
||||
free(af);
|
||||
return NULL;
|
||||
}
|
||||
drmp3_bool32 ok = drmp3_init_memory(af->mp3, memory, length, NULL);
|
||||
if (!ok)
|
||||
free(af->mp3);
|
||||
else {
|
||||
af->cache.mp3.frames = drmp3_get_pcm_frame_count(af->mp3);
|
||||
if (af->cache.mp3.frames == 0) {
|
||||
free(af->mp3);
|
||||
free(af);
|
||||
return NULL;
|
||||
}
|
||||
af->type = st_audio_file_mp3;
|
||||
return af;
|
||||
}
|
||||
}
|
||||
|
||||
free(af);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
st_audio_file* st_open_file(const char* filename)
|
||||
{
|
||||
return st_generic_open_file(filename, 0);
|
||||
|
|
|
|||
2
external/st_audiofile/src/st_audiofile.h
vendored
2
external/st_audiofile/src/st_audiofile.h
vendored
|
|
@ -14,6 +14,7 @@
|
|||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#if defined(_WIN32)
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
|
@ -33,6 +34,7 @@ typedef enum st_audio_file_type {
|
|||
st_audio_file_other,
|
||||
} st_audio_file_type;
|
||||
|
||||
st_audio_file* st_open_memory(const void* memory, size_t length);
|
||||
st_audio_file* st_open_file(const char* filename);
|
||||
#if defined(_WIN32)
|
||||
st_audio_file* st_open_file_w(const wchar_t* filename);
|
||||
|
|
|
|||
8
external/st_audiofile/src/st_audiofile.hpp
vendored
8
external/st_audiofile/src/st_audiofile.hpp
vendored
|
|
@ -25,6 +25,7 @@ public:
|
|||
#if defined(_WIN32)
|
||||
bool open_file_w(const wchar_t* filename);
|
||||
#endif
|
||||
bool open_memory(const void* memory, size_t length);
|
||||
|
||||
int get_type() const noexcept;
|
||||
const char* get_type_string() const noexcept;
|
||||
|
|
@ -96,6 +97,13 @@ bool ST_AudioFile::open_file(const char* filename)
|
|||
reset(new_af);
|
||||
return new_af != nullptr;
|
||||
}
|
||||
|
||||
bool ST_AudioFile::open_memory(const void* memory, size_t length)
|
||||
{
|
||||
st_audio_file* new_af = st_open_memory(memory, length);
|
||||
reset(new_af);
|
||||
return new_af != nullptr;
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
inline bool ST_AudioFile::open_file_w(const wchar_t* filename)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "AudioReader.h"
|
||||
#include "FileMetadata.h"
|
||||
#include <absl/memory/memory.h>
|
||||
#include <st_audiofile.hpp>
|
||||
#if defined(SFIZZ_USE_SNDFILE)
|
||||
#include <sndfile.h>
|
||||
|
|
@ -16,17 +17,19 @@ namespace sfz {
|
|||
|
||||
class BasicSndfileReader : public AudioReader {
|
||||
public:
|
||||
explicit BasicSndfileReader(ST_AudioFile handle) : handle_(std::move(handle)) {}
|
||||
explicit BasicSndfileReader(ST_AudioFile handle, std::unique_ptr<MetadataReader> mdReader)
|
||||
: handle_(std::move(handle)), mdReader_(std::move(mdReader)) {}
|
||||
virtual ~BasicSndfileReader() {}
|
||||
|
||||
int format() const override;
|
||||
int64_t frames() const override;
|
||||
unsigned channels() const override;
|
||||
unsigned sampleRate() const override;
|
||||
bool getInstrument(InstrumentInfo* instrument) override;
|
||||
|
||||
bool getInstrumentInfo(InstrumentInfo& instrument) override;
|
||||
bool getWavetableInfo(WavetableInfo& instrument) override;
|
||||
protected:
|
||||
ST_AudioFile handle_;
|
||||
std::unique_ptr<MetadataReader> mdReader_;
|
||||
};
|
||||
|
||||
int BasicSndfileReader::format() const
|
||||
|
|
@ -49,7 +52,21 @@ unsigned BasicSndfileReader::sampleRate() const
|
|||
return handle_.get_sample_rate();
|
||||
}
|
||||
|
||||
bool BasicSndfileReader::getInstrument(InstrumentInfo* instrument)
|
||||
bool BasicSndfileReader::getWavetableInfo(WavetableInfo& wt)
|
||||
{
|
||||
if (!mdReader_)
|
||||
return false;
|
||||
|
||||
if (!mdReader_->isOpened())
|
||||
mdReader_->open();
|
||||
|
||||
if (mdReader_->isOpened())
|
||||
return mdReader_->extractWavetableInfo(wt);
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
bool BasicSndfileReader::getInstrumentInfo(InstrumentInfo& instrument)
|
||||
{
|
||||
#if defined(SFIZZ_USE_SNDFILE)
|
||||
SNDFILE* sndfile = reinterpret_cast<SNDFILE*>(handle_.get_sndfile_handle());
|
||||
|
|
@ -57,7 +74,14 @@ bool BasicSndfileReader::getInstrument(InstrumentInfo* instrument)
|
|||
if (sf_command(sndfile, SFC_GET_INSTRUMENT, sfins, sizeof(SF_INSTRUMENT)) == SF_TRUE)
|
||||
return true;
|
||||
#else
|
||||
(void)instrument;
|
||||
if (!mdReader_)
|
||||
return false;
|
||||
|
||||
if (!mdReader_->isOpened())
|
||||
mdReader_->open();
|
||||
|
||||
if (mdReader_->isOpened())
|
||||
return mdReader_->extractInstrument(instrument);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
|
@ -69,13 +93,13 @@ bool BasicSndfileReader::getInstrument(InstrumentInfo* instrument)
|
|||
*/
|
||||
class ForwardReader : public BasicSndfileReader {
|
||||
public:
|
||||
explicit ForwardReader(ST_AudioFile handle);
|
||||
explicit ForwardReader(ST_AudioFile handle, std::unique_ptr<MetadataReader> mdReader);
|
||||
AudioReaderType type() const override;
|
||||
size_t readNextBlock(float* buffer, size_t frames) override;
|
||||
};
|
||||
|
||||
ForwardReader::ForwardReader(ST_AudioFile handle)
|
||||
: BasicSndfileReader(std::move(handle))
|
||||
ForwardReader::ForwardReader(ST_AudioFile handle, std::unique_ptr<MetadataReader> mdReader)
|
||||
: BasicSndfileReader(std::move(handle), std::move(mdReader))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +162,7 @@ static void reverse_frames(float* data, size_t frames, unsigned channels)
|
|||
*/
|
||||
class ReverseReader : public BasicSndfileReader {
|
||||
public:
|
||||
explicit ReverseReader(ST_AudioFile handle);
|
||||
explicit ReverseReader(ST_AudioFile handle, std::unique_ptr<MetadataReader> mdReader);
|
||||
AudioReaderType type() const override;
|
||||
size_t readNextBlock(float* buffer, size_t frames) override;
|
||||
|
||||
|
|
@ -146,8 +170,8 @@ private:
|
|||
uint64_t position_ {};
|
||||
};
|
||||
|
||||
ReverseReader::ReverseReader(ST_AudioFile handle)
|
||||
: BasicSndfileReader(std::move(handle))
|
||||
ReverseReader::ReverseReader(ST_AudioFile handle, std::unique_ptr<MetadataReader> mdReader)
|
||||
: BasicSndfileReader(std::move(handle), std::move(mdReader))
|
||||
{
|
||||
position_ = handle_.get_frame_count();
|
||||
}
|
||||
|
|
@ -183,7 +207,7 @@ size_t ReverseReader::readNextBlock(float* buffer, size_t frames)
|
|||
*/
|
||||
class NoSeekReverseReader : public BasicSndfileReader {
|
||||
public:
|
||||
explicit NoSeekReverseReader(ST_AudioFile handle);
|
||||
explicit NoSeekReverseReader(ST_AudioFile handle, std::unique_ptr<MetadataReader> mdReader);
|
||||
AudioReaderType type() const override;
|
||||
size_t readNextBlock(float* buffer, size_t frames) override;
|
||||
|
||||
|
|
@ -195,8 +219,8 @@ private:
|
|||
uint64_t fileFramesLeft_ { 0 };
|
||||
};
|
||||
|
||||
NoSeekReverseReader::NoSeekReverseReader(ST_AudioFile handle)
|
||||
: BasicSndfileReader(std::move(handle))
|
||||
NoSeekReverseReader::NoSeekReverseReader(ST_AudioFile handle, std::unique_ptr<MetadataReader> mdReader)
|
||||
: BasicSndfileReader(std::move(handle), std::move(mdReader))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -281,6 +305,7 @@ const std::error_category& undetailed_category()
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static fs::path emptyPath_ {};
|
||||
|
||||
class DummyAudioReader : public AudioReader {
|
||||
public:
|
||||
|
|
@ -291,8 +316,7 @@ public:
|
|||
unsigned channels() const override { return 1; }
|
||||
unsigned sampleRate() const override { return 44100; }
|
||||
size_t readNextBlock(float*, size_t) override { return 0; }
|
||||
bool getInstrument(InstrumentInfo* ) override { return false; }
|
||||
|
||||
bool getInstrumentInfo(InstrumentInfo& ) override { return false; }
|
||||
private:
|
||||
AudioReaderType type_ {};
|
||||
};
|
||||
|
|
@ -334,7 +358,7 @@ static bool formatHasFastSeeking(int format)
|
|||
}
|
||||
#endif
|
||||
|
||||
static AudioReaderPtr createAudioReaderWithHandle(ST_AudioFile handle, bool reverse, std::error_code* ec)
|
||||
static AudioReaderPtr createAudioReaderWithHandle(ST_AudioFile handle, std::unique_ptr<MetadataReader> mdReader, bool reverse, std::error_code* ec)
|
||||
{
|
||||
AudioReaderPtr reader;
|
||||
|
||||
|
|
@ -347,7 +371,7 @@ static AudioReaderPtr createAudioReaderWithHandle(ST_AudioFile handle, bool reve
|
|||
reader.reset(new DummyAudioReader(reverse ? AudioReaderType::Reverse : AudioReaderType::Forward));
|
||||
}
|
||||
else if (!reverse)
|
||||
reader.reset(new ForwardReader(std::move(handle)));
|
||||
reader.reset(new ForwardReader(std::move(handle), std::move(mdReader)));
|
||||
else {
|
||||
#if defined(SFIZZ_USE_SNDFILE)
|
||||
bool hasFastSeeking = formatHasFastSeeking(handle.get_sndfile_format());
|
||||
|
|
@ -355,9 +379,9 @@ static AudioReaderPtr createAudioReaderWithHandle(ST_AudioFile handle, bool reve
|
|||
bool hasFastSeeking = true;
|
||||
#endif
|
||||
if (hasFastSeeking)
|
||||
reader.reset(new ReverseReader(std::move(handle)));
|
||||
reader.reset(new ReverseReader(std::move(handle), std::move(mdReader)));
|
||||
else
|
||||
reader.reset(new NoSeekReverseReader(std::move(handle)));
|
||||
reader.reset(new NoSeekReverseReader(std::move(handle), std::move(mdReader)));
|
||||
}
|
||||
|
||||
return reader;
|
||||
|
|
@ -371,47 +395,16 @@ AudioReaderPtr createAudioReader(const fs::path& path, bool reverse, std::error_
|
|||
#else
|
||||
handle.open_file(path.c_str());
|
||||
#endif
|
||||
return createAudioReaderWithHandle(std::move(handle), reverse, ec);
|
||||
return createAudioReaderWithHandle(std::move(handle),
|
||||
absl::make_unique<FileMetadataReader>(path), reverse, ec);
|
||||
}
|
||||
|
||||
static AudioReaderPtr createExplicitAudioReaderWithHandle(ST_AudioFile handle, AudioReaderType type, std::error_code* ec)
|
||||
{
|
||||
AudioReaderPtr reader;
|
||||
|
||||
if (ec)
|
||||
ec->clear();
|
||||
|
||||
if (!handle) {
|
||||
if (ec)
|
||||
*ec = std::error_code(1, undetailed_category());
|
||||
reader.reset(new DummyAudioReader(type));
|
||||
}
|
||||
else {
|
||||
switch (type) {
|
||||
case AudioReaderType::Forward:
|
||||
reader.reset(new ForwardReader(std::move(handle)));
|
||||
break;
|
||||
case AudioReaderType::Reverse:
|
||||
reader.reset(new ReverseReader(std::move(handle)));
|
||||
break;
|
||||
case AudioReaderType::NoSeekReverse:
|
||||
reader.reset(new NoSeekReverseReader(std::move(handle)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
AudioReaderPtr createExplicitAudioReader(const fs::path& path, AudioReaderType type, std::error_code* ec)
|
||||
AudioReaderPtr createAudioReaderFromMemory(const void* memory, size_t length, bool reverse, std::error_code* ec)
|
||||
{
|
||||
ST_AudioFile handle;
|
||||
#if defined(_WIN32)
|
||||
handle.open_file_w(path.wstring().c_str());
|
||||
#else
|
||||
handle.open_file(path.c_str());
|
||||
#endif
|
||||
return createExplicitAudioReaderWithHandle(std::move(handle), type, ec);
|
||||
handle.open_memory(memory, length);
|
||||
return createAudioReaderWithHandle(std::move(handle),
|
||||
absl::make_unique<MemoryMetadataReader>(memory, length), reverse, ec);
|
||||
}
|
||||
|
||||
} // namespace sfz
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
namespace sfz {
|
||||
struct InstrumentInfo;
|
||||
struct WavetableInfo;
|
||||
|
||||
/**
|
||||
* @brief Designation of a particular kind of audio reader
|
||||
|
|
@ -39,7 +40,8 @@ public:
|
|||
virtual unsigned channels() const = 0;
|
||||
virtual unsigned sampleRate() const = 0;
|
||||
virtual size_t readNextBlock(float* buffer, size_t frames) = 0;
|
||||
virtual bool getInstrument(InstrumentInfo* instrument) = 0;
|
||||
virtual bool getInstrumentInfo(InstrumentInfo&) { return false; };
|
||||
virtual bool getWavetableInfo(WavetableInfo&) { return false; };
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<AudioReader> AudioReaderPtr;
|
||||
|
|
@ -50,8 +52,8 @@ typedef std::unique_ptr<AudioReader> AudioReaderPtr;
|
|||
AudioReaderPtr createAudioReader(const fs::path& path, bool reverse, std::error_code* ec = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Create a file reader of explicit type. (for testing purposes)
|
||||
* @brief Create a memory reader of detected type.
|
||||
*/
|
||||
AudioReaderPtr createExplicitAudioReader(const fs::path& path, AudioReaderType type, std::error_code* ec = nullptr);
|
||||
AudioReaderPtr createAudioReaderFromMemory(const void* memory, size_t length, bool reverse, std::error_code* ec = nullptr);
|
||||
|
||||
} // namespace sfz
|
||||
|
|
|
|||
|
|
@ -52,50 +52,12 @@ static uint16_t u16be(const uint8_t *bytes)
|
|||
return (bytes[0] << 8) | bytes[1];
|
||||
}
|
||||
|
||||
static bool fread_u32le(FILE* stream, uint32_t& value)
|
||||
{
|
||||
uint8_t bytes[4];
|
||||
if (fread(bytes, 4, 1, stream) != 1)
|
||||
return false;
|
||||
value = u32le(bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool fread_u32be(FILE* stream, uint32_t& value)
|
||||
{
|
||||
uint8_t bytes[4];
|
||||
if (fread(bytes, 4, 1, stream) != 1)
|
||||
return false;
|
||||
value = u32be(bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static bool fread_u16le(FILE* stream, uint16_t& value)
|
||||
{
|
||||
uint8_t bytes[2];
|
||||
if (fread(bytes, 2, 1, stream) != 1)
|
||||
return false;
|
||||
value = u16le(bytes);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool fread_u16be(FILE* stream, uint16_t& value)
|
||||
{
|
||||
uint8_t bytes[2];
|
||||
if (fread(bytes, 2, 1, stream) != 1)
|
||||
return false;
|
||||
value = u16be(bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct FileMetadataReader::Impl {
|
||||
FILE_u stream_;
|
||||
struct MetadataReader::Impl {
|
||||
MetadataReader* parent;
|
||||
std::vector<RiffChunkInfo> riffChunks_;
|
||||
|
||||
bool opened_ { false };
|
||||
enum class ChunkType { None, Riff, Aiff };
|
||||
ChunkType chunkType_ = ChunkType::None;
|
||||
|
||||
|
|
@ -110,35 +72,72 @@ struct FileMetadataReader::Impl {
|
|||
const RiffChunkInfo* riffChunk(size_t index) const;
|
||||
const RiffChunkInfo* riffChunkById(RiffChunkId id) const;
|
||||
size_t readRiffData(size_t index, void* buffer, size_t count);
|
||||
bool read_u32le(uint32_t& value);
|
||||
bool read_u32be(uint32_t& value);
|
||||
bool read_u16le(uint16_t& value);
|
||||
bool read_u16be(uint16_t& value);
|
||||
};
|
||||
|
||||
FileMetadataReader::FileMetadataReader()
|
||||
bool MetadataReader::Impl::read_u32le(uint32_t& value)
|
||||
{
|
||||
uint8_t bytes[4];
|
||||
if (parent->doRead(bytes, 4, 1) != 1)
|
||||
return false;
|
||||
value = u32le(bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetadataReader::Impl::read_u32be(uint32_t& value)
|
||||
{
|
||||
uint8_t bytes[4];
|
||||
if (parent->doRead(bytes, 4, 1) != 1)
|
||||
return false;
|
||||
value = u32be(bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool MetadataReader::Impl::read_u16le(uint16_t& value)
|
||||
{
|
||||
uint8_t bytes[2];
|
||||
if (parent->do_read(bytes, 2, 1) != 1)
|
||||
return false;
|
||||
value = u16le(bytes);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool MetadataReader::Impl::read_u16be(uint16_t& value)
|
||||
{
|
||||
uint8_t bytes[2];
|
||||
if (parent->doRead(bytes, 2, 1) != 1)
|
||||
return false;
|
||||
value = u16be(bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
MetadataReader::MetadataReader()
|
||||
: impl_(new Impl)
|
||||
{
|
||||
impl_->parent = this;
|
||||
impl_->riffChunks_.reserve(16);
|
||||
}
|
||||
|
||||
FileMetadataReader::~FileMetadataReader()
|
||||
MetadataReader::~MetadataReader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool FileMetadataReader::open(const fs::path& path)
|
||||
bool MetadataReader::open()
|
||||
{
|
||||
close();
|
||||
|
||||
#if !defined(_WIN32)
|
||||
FILE* stream = fopen(path.c_str(), "rb");
|
||||
#else
|
||||
FILE* stream = _wfopen(path.wstring().c_str(), L"rb");
|
||||
#endif
|
||||
|
||||
if (!stream)
|
||||
if (!doOpen())
|
||||
return false;
|
||||
|
||||
impl_->stream_.reset(stream);
|
||||
|
||||
Impl& impl = *impl_;
|
||||
impl.opened_ = true;
|
||||
char magic[4];
|
||||
size_t count = fread(magic, 1, sizeof(magic), stream);
|
||||
size_t count = doRead(magic, 1, sizeof(magic));
|
||||
|
||||
if (count >= 4 && !memcmp(magic, "fLaC", 4)) {
|
||||
if (!impl_->openFlac()) {
|
||||
|
|
@ -165,96 +164,99 @@ bool FileMetadataReader::open(const fs::path& path)
|
|||
return true;
|
||||
}
|
||||
|
||||
void FileMetadataReader::close()
|
||||
bool MetadataReader::isOpened()
|
||||
{
|
||||
impl_->stream_.reset();
|
||||
impl_->riffChunks_.clear();
|
||||
return impl_->opened_;
|
||||
}
|
||||
|
||||
bool FileMetadataReader::Impl::openFlac()
|
||||
void MetadataReader::close()
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
impl.riffChunks_.clear();
|
||||
doClose();
|
||||
impl.opened_ = false;
|
||||
}
|
||||
|
||||
bool MetadataReader::Impl::openFlac()
|
||||
{
|
||||
FILE* stream = stream_.get();
|
||||
std::vector<RiffChunkInfo>& riffChunks = riffChunks_;
|
||||
|
||||
if (fseek(stream, 4, SEEK_SET) != 0)
|
||||
if (parent->doSeek(4, SEEK_SET) != 0)
|
||||
return false;
|
||||
|
||||
uint32_t header = 0;
|
||||
while (((header >> 31) & 1) != 1) {
|
||||
if (!fread_u32be(stream, header))
|
||||
if (!read_u32be(header))
|
||||
return false;
|
||||
|
||||
const uint32_t blockType = (header >> 24) & 0x7f;
|
||||
const uint32_t blockSize = header & ((1 << 24) - 1);
|
||||
|
||||
const off_t offStartBlock = ftell(stream);
|
||||
const off_t offStartBlock = parent->doTell();
|
||||
const off_t offNextBlock = offStartBlock + blockSize;
|
||||
|
||||
if (blockType == 2) { // APPLICATION block
|
||||
char blockId[4];
|
||||
char riffId[4];
|
||||
uint32_t riffChunkSize;
|
||||
if (fread(blockId, 4, 1, stream) == 1 && memcmp(blockId, "riff", 4) == 0 &&
|
||||
fread(riffId, 4, 1, stream) == 1 &&
|
||||
fread_u32le(stream, riffChunkSize) && riffChunkSize <= blockSize - 12)
|
||||
if (parent->doRead(blockId, 4, 1) == 1 && memcmp(blockId, "riff", 4) == 0 &&
|
||||
parent->doRead(riffId, 4, 1) == 1 &&
|
||||
read_u32le(riffChunkSize) && riffChunkSize <= blockSize - 12)
|
||||
{
|
||||
RiffChunkInfo info;
|
||||
info.index = riffChunks.size();
|
||||
info.fileOffset = ftell(stream);
|
||||
info.fileOffset = parent->doTell();
|
||||
memcpy(info.id.data(), riffId, 4);
|
||||
info.length = riffChunkSize;
|
||||
riffChunks.push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
if (fseek(stream, offNextBlock, SEEK_SET) != 0)
|
||||
if (parent->doSeek(offNextBlock, SEEK_SET) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileMetadataReader::Impl::openRiff()
|
||||
bool MetadataReader::Impl::openRiff()
|
||||
{
|
||||
FILE* stream = stream_.get();
|
||||
std::vector<RiffChunkInfo>& riffChunks = riffChunks_;
|
||||
|
||||
if (fseek(stream, 12, SEEK_SET) != 0)
|
||||
if (parent->doSeek(12, SEEK_SET) != 0)
|
||||
return false;
|
||||
|
||||
char riffId[4];
|
||||
uint32_t riffChunkSize;
|
||||
while (fread(riffId, 4, 1, stream) == 1 && fread_u32le(stream, riffChunkSize)) {
|
||||
while (parent->doRead(riffId, 4, 1) == 1 && read_u32le(riffChunkSize)) {
|
||||
RiffChunkInfo info;
|
||||
info.index = riffChunks.size();
|
||||
info.fileOffset = ftell(stream);
|
||||
info.fileOffset = parent->doTell();
|
||||
memcpy(info.id.data(), riffId, 4);
|
||||
info.length = riffChunkSize;
|
||||
riffChunks.push_back(info);
|
||||
|
||||
if (fseek(stream, riffChunkSize + (riffChunkSize & 1), SEEK_CUR) != 0)
|
||||
if (parent->doSeek(riffChunkSize + (riffChunkSize & 1), SEEK_CUR) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileMetadataReader::Impl::openAiff()
|
||||
bool MetadataReader::Impl::openAiff()
|
||||
{
|
||||
FILE* stream = stream_.get();
|
||||
|
||||
rewind(stream);
|
||||
parent->doRewind();
|
||||
|
||||
char formId[4];
|
||||
uint32_t formSize;
|
||||
if (fread(formId, 4, 1, stream) != 1 || memcmp(formId, "FORM", 4) ||
|
||||
!fread_u32be(stream, formSize))
|
||||
if (parent->doRead(formId, 4, 1) != 1 || memcmp(formId, "FORM", 4) ||
|
||||
!read_u32be(formSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char aiffId[4];
|
||||
if (fread(aiffId, 4, 1, stream) != 1 ||
|
||||
if (parent->doRead(aiffId, 4, 1) != 1 ||
|
||||
(memcmp(aiffId, "AIFF", 4) && memcmp(aiffId, "AIFC", 4)))
|
||||
{
|
||||
return false;
|
||||
|
|
@ -264,42 +266,42 @@ bool FileMetadataReader::Impl::openAiff()
|
|||
|
||||
char riffId[4];
|
||||
uint32_t riffChunkSize;
|
||||
while (fread(riffId, 4, 1, stream) == 1 && fread_u32be(stream, riffChunkSize)) {
|
||||
while (parent->doRead(riffId, 4, 1) == 1 && read_u32be(riffChunkSize)) {
|
||||
RiffChunkInfo info;
|
||||
info.index = riffChunks.size();
|
||||
info.fileOffset = ftell(stream);
|
||||
info.fileOffset = parent->doTell();
|
||||
memcpy(info.id.data(), riffId, 4);
|
||||
info.length = riffChunkSize;
|
||||
riffChunks.push_back(info);
|
||||
|
||||
if (fseek(stream, riffChunkSize + (riffChunkSize & 1), SEEK_CUR) != 0)
|
||||
if (parent->doSeek(riffChunkSize + (riffChunkSize & 1), SEEK_CUR) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t FileMetadataReader::riffChunkCount() const
|
||||
size_t MetadataReader::riffChunkCount() const
|
||||
{
|
||||
return impl_->riffChunks_.size();
|
||||
}
|
||||
|
||||
const RiffChunkInfo* FileMetadataReader::riffChunk(size_t index) const
|
||||
const RiffChunkInfo* MetadataReader::riffChunk(size_t index) const
|
||||
{
|
||||
return impl_->riffChunk(index);
|
||||
}
|
||||
|
||||
const RiffChunkInfo* FileMetadataReader::Impl::riffChunk(size_t index) const
|
||||
const RiffChunkInfo* MetadataReader::Impl::riffChunk(size_t index) const
|
||||
{
|
||||
return (index < riffChunks_.size()) ? &riffChunks_[index] : nullptr;
|
||||
}
|
||||
|
||||
const RiffChunkInfo* FileMetadataReader::riffChunkById(RiffChunkId id) const
|
||||
const RiffChunkInfo* MetadataReader::riffChunkById(RiffChunkId id) const
|
||||
{
|
||||
return impl_->riffChunkById(id);
|
||||
}
|
||||
|
||||
const RiffChunkInfo* FileMetadataReader::Impl::riffChunkById(RiffChunkId id) const
|
||||
const RiffChunkInfo* MetadataReader::Impl::riffChunkById(RiffChunkId id) const
|
||||
{
|
||||
for (const RiffChunkInfo& riff : riffChunks_) {
|
||||
if (riff.id == id)
|
||||
|
|
@ -308,12 +310,12 @@ const RiffChunkInfo* FileMetadataReader::Impl::riffChunkById(RiffChunkId id) con
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
size_t FileMetadataReader::readRiffData(size_t index, void* buffer, size_t count)
|
||||
size_t MetadataReader::readRiffData(size_t index, void* buffer, size_t count)
|
||||
{
|
||||
return impl_->readRiffData(index, buffer, count);
|
||||
}
|
||||
|
||||
size_t FileMetadataReader::Impl::readRiffData(size_t index, void* buffer, size_t count)
|
||||
size_t MetadataReader::Impl::readRiffData(size_t index, void* buffer, size_t count)
|
||||
{
|
||||
const RiffChunkInfo* riff = riffChunk(index);
|
||||
if (!riff)
|
||||
|
|
@ -321,14 +323,13 @@ size_t FileMetadataReader::Impl::readRiffData(size_t index, void* buffer, size_t
|
|||
|
||||
count = (count < riff->length) ? count : riff->length;
|
||||
|
||||
FILE* stream = stream_.get();
|
||||
if (fseek(stream, riff->fileOffset, SEEK_SET) != 0)
|
||||
if (parent->doSeek(riff->fileOffset, SEEK_SET) != 0)
|
||||
return 0;
|
||||
|
||||
return fread(buffer, 1, count, stream);
|
||||
return parent->doRead(buffer, 1, count);
|
||||
}
|
||||
|
||||
bool FileMetadataReader::extractInstrument(InstrumentInfo& ins)
|
||||
bool MetadataReader::extractInstrument(InstrumentInfo& ins)
|
||||
{
|
||||
if (extractRiffInstrument(ins))
|
||||
return true;
|
||||
|
|
@ -339,7 +340,7 @@ bool FileMetadataReader::extractInstrument(InstrumentInfo& ins)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool FileMetadataReader::extractRiffInstrument(InstrumentInfo& ins)
|
||||
bool MetadataReader::extractRiffInstrument(InstrumentInfo& ins)
|
||||
{
|
||||
if (impl_->chunkType_ != Impl::ChunkType::Riff)
|
||||
return false;
|
||||
|
|
@ -399,9 +400,10 @@ bool FileMetadataReader::extractRiffInstrument(InstrumentInfo& ins)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FileMetadataReader::extractAiffInstrument(InstrumentInfo& ins)
|
||||
bool MetadataReader::extractAiffInstrument(InstrumentInfo& ins)
|
||||
{
|
||||
if (impl_->chunkType_ != Impl::ChunkType::Aiff)
|
||||
Impl& impl = *impl_;
|
||||
if (impl.chunkType_ != Impl::ChunkType::Aiff)
|
||||
return false;
|
||||
|
||||
const RiffChunkInfo* instChunk = riffChunkById(RiffChunkId{'I', 'N', 'S', 'T'});
|
||||
|
|
@ -418,12 +420,11 @@ bool FileMetadataReader::extractAiffInstrument(InstrumentInfo& ins)
|
|||
//
|
||||
std::map<uint16_t, uint32_t> markers;
|
||||
if (markChunk) {
|
||||
FILE* stream = impl_->stream_.get();
|
||||
if (fseek(stream, markChunk->fileOffset, SEEK_SET) != 0)
|
||||
if (doSeek(markChunk->fileOffset, SEEK_SET) != 0)
|
||||
return false;
|
||||
|
||||
uint16_t numMarkers;
|
||||
if (!fread_u16be(stream, numMarkers))
|
||||
if (!impl.read_u16be(numMarkers))
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < numMarkers; ++i) {
|
||||
|
|
@ -432,12 +433,12 @@ bool FileMetadataReader::extractAiffInstrument(InstrumentInfo& ins)
|
|||
uint8_t size;
|
||||
char name[256];
|
||||
|
||||
if (!fread_u16be(stream, id) || !fread_u32be(stream, position) || fread(&size, 1, 1, stream) != 1 || fread(name, size, 1, stream) != 1)
|
||||
if (!impl.read_u16be(id) || !impl.read_u32be(position) || doRead(&size, 1, 1) != 1 || doRead(name, size, 1) != 1)
|
||||
return false;
|
||||
name[size] = '\0';
|
||||
|
||||
if (i + 1 < numMarkers && ((~size) & 1)) {
|
||||
if (fseek(stream, 1, SEEK_CUR) != 0)
|
||||
if (doSeek(1, SEEK_CUR) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -502,7 +503,7 @@ bool FileMetadataReader::extractAiffInstrument(InstrumentInfo& ins)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FileMetadataReader::extractWavetableInfo(WavetableInfo& wt)
|
||||
bool MetadataReader::extractWavetableInfo(WavetableInfo& wt)
|
||||
{
|
||||
if (impl_->extractClmWavetable(wt))
|
||||
return true;
|
||||
|
|
@ -520,7 +521,7 @@ bool FileMetadataReader::extractWavetableInfo(WavetableInfo& wt)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool FileMetadataReader::Impl::extractClmWavetable(WavetableInfo &wt)
|
||||
bool MetadataReader::Impl::extractClmWavetable(WavetableInfo &wt)
|
||||
{
|
||||
const RiffChunkInfo* clm = riffChunkById(RiffChunkId{'c', 'l', 'm', ' '});
|
||||
if (!clm)
|
||||
|
|
@ -551,7 +552,7 @@ bool FileMetadataReader::Impl::extractClmWavetable(WavetableInfo &wt)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FileMetadataReader::Impl::extractSurgeWavetable(WavetableInfo &wt)
|
||||
bool MetadataReader::Impl::extractSurgeWavetable(WavetableInfo &wt)
|
||||
{
|
||||
const RiffChunkInfo* srge;
|
||||
|
||||
|
|
@ -574,7 +575,7 @@ bool FileMetadataReader::Impl::extractSurgeWavetable(WavetableInfo &wt)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FileMetadataReader::Impl::extractUheWavetable(WavetableInfo &wt)
|
||||
bool MetadataReader::Impl::extractUheWavetable(WavetableInfo &wt)
|
||||
{
|
||||
const RiffChunkInfo* uhwt = riffChunkById(RiffChunkId{'u', 'h', 'W', 'T'});
|
||||
if (!uhwt)
|
||||
|
|
@ -596,4 +597,160 @@ bool FileMetadataReader::Impl::extractUheWavetable(WavetableInfo &wt)
|
|||
return true;
|
||||
}
|
||||
|
||||
struct FileMetadataReader::Impl {
|
||||
fs::path path;
|
||||
FILE_u stream_;
|
||||
};
|
||||
|
||||
FileMetadataReader::FileMetadataReader(const fs::path& path)
|
||||
: impl_(new Impl)
|
||||
{
|
||||
impl_->path = path;
|
||||
}
|
||||
|
||||
FileMetadataReader::~FileMetadataReader()
|
||||
{
|
||||
}
|
||||
|
||||
void FileMetadataReader::doClose()
|
||||
{
|
||||
impl_->stream_.reset();
|
||||
}
|
||||
|
||||
bool FileMetadataReader::doOpen()
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
#if !defined(_WIN32)
|
||||
FILE* stream = fopen(impl.path.c_str(), "rb");
|
||||
#else
|
||||
FILE* stream = _wfopen(impl.path.wstring().c_str(), L"rb");
|
||||
#endif
|
||||
|
||||
if (!stream)
|
||||
return false;
|
||||
|
||||
impl_->stream_.reset(stream);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t FileMetadataReader::doRead(void* ptr, size_t size, size_t n)
|
||||
{
|
||||
return fread(ptr, size, n, impl_->stream_.get());
|
||||
}
|
||||
|
||||
int FileMetadataReader::doSeek(long off, int whence)
|
||||
{
|
||||
return fseek(impl_->stream_.get(), off, whence);
|
||||
}
|
||||
|
||||
void FileMetadataReader::doRewind()
|
||||
{
|
||||
rewind(impl_->stream_.get());
|
||||
}
|
||||
|
||||
long FileMetadataReader::doTell()
|
||||
{
|
||||
return ftell(impl_->stream_.get());
|
||||
}
|
||||
|
||||
struct MemoryMetadataReader::Impl {
|
||||
const char* memory;
|
||||
size_t length;
|
||||
size_t position { 0 };
|
||||
};
|
||||
|
||||
MemoryMetadataReader::MemoryMetadataReader(const void* memory, size_t length)
|
||||
: impl_(new Impl)
|
||||
{
|
||||
impl_->memory = reinterpret_cast<const char*>(memory);
|
||||
impl_->length = length;
|
||||
}
|
||||
|
||||
MemoryMetadataReader::~MemoryMetadataReader()
|
||||
{
|
||||
}
|
||||
|
||||
void MemoryMetadataReader::doClose()
|
||||
{
|
||||
}
|
||||
|
||||
bool MemoryMetadataReader::doOpen()
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
if (impl.length == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t MemoryMetadataReader::doRead(void* ptr, size_t size, size_t n)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
size_t actualCount =
|
||||
(std::min(impl.position + n * size, impl.length) - impl.position) / size;
|
||||
size_t totalBytes = actualCount * size;
|
||||
memcpy(ptr, impl.memory + impl.position, totalBytes);
|
||||
impl.position += totalBytes;
|
||||
return actualCount;
|
||||
}
|
||||
|
||||
int MemoryMetadataReader::doSeek(long off, int whence)
|
||||
{
|
||||
Impl& impl = *impl_;
|
||||
|
||||
switch(whence) {
|
||||
case SEEK_SET:
|
||||
{
|
||||
if (off < 0)
|
||||
return -1;
|
||||
|
||||
const size_t offset = static_cast<size_t>(off);
|
||||
if (offset > impl.length)
|
||||
return -1;
|
||||
impl.position = offset;
|
||||
}
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
{
|
||||
if (off < 0) {
|
||||
const size_t minusOffset = static_cast<size_t>(-off);
|
||||
if (minusOffset > impl.position)
|
||||
return -1;
|
||||
|
||||
impl.position -= minusOffset;
|
||||
} else {
|
||||
const size_t offset = static_cast<size_t>(off);
|
||||
const size_t newPosition = impl.position + offset;
|
||||
if (newPosition > impl.length)
|
||||
return -1;
|
||||
|
||||
impl.position = newPosition;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SEEK_END:
|
||||
{
|
||||
if (off > 0)
|
||||
return -1;
|
||||
|
||||
const size_t minusOffset = static_cast<size_t>(-off);
|
||||
if (minusOffset > impl.length)
|
||||
return -1;
|
||||
impl.position = impl.length - minusOffset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MemoryMetadataReader::doRewind()
|
||||
{
|
||||
impl_->position = 0;
|
||||
}
|
||||
|
||||
long MemoryMetadataReader::doTell()
|
||||
{
|
||||
return static_cast<long>(impl_->position);
|
||||
}
|
||||
|
||||
} // namespace sfz
|
||||
|
|
|
|||
|
|
@ -81,19 +81,10 @@ struct WavetableInfo {
|
|||
bool oneShot;
|
||||
};
|
||||
|
||||
class FileMetadataReader {
|
||||
class MetadataReader {
|
||||
public:
|
||||
FileMetadataReader();
|
||||
~FileMetadataReader();
|
||||
|
||||
/**
|
||||
* @brief Open an audio file of supported format and read internal structures
|
||||
*/
|
||||
bool open(const fs::path& path);
|
||||
/**
|
||||
* @brief Close an audio file
|
||||
*/
|
||||
void close();
|
||||
MetadataReader();
|
||||
virtual ~MetadataReader();
|
||||
|
||||
/**
|
||||
* @brief Get the number of RIFF chunks in the file
|
||||
|
|
@ -132,9 +123,68 @@ public:
|
|||
*/
|
||||
bool extractWavetableInfo(WavetableInfo& wt);
|
||||
|
||||
/**
|
||||
* @brief Opens the metadata reader and perform initialization.
|
||||
* If the reader is opened already it closes it and reopens.
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool open();
|
||||
|
||||
/**
|
||||
* @brief Check if the reader is already opened
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool isOpened();
|
||||
|
||||
/**
|
||||
* @brief Close the metadata reader
|
||||
*
|
||||
*/
|
||||
void close();
|
||||
protected:
|
||||
virtual bool doOpen() { return true; };
|
||||
virtual void doClose() {}
|
||||
virtual size_t doRead(void* ptr, size_t size, size_t n) = 0;
|
||||
virtual int doSeek(long off, int whence) = 0;
|
||||
virtual void doRewind() = 0;
|
||||
virtual long doTell() = 0;
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
class FileMetadataReader: public MetadataReader {
|
||||
public:
|
||||
FileMetadataReader(const fs::path& path);
|
||||
~FileMetadataReader();
|
||||
private:
|
||||
bool doOpen() override;
|
||||
void doClose() override;
|
||||
size_t doRead(void* ptr, size_t size, size_t n) override;
|
||||
int doSeek(long off, int whence) override;
|
||||
void doRewind() override;
|
||||
long doTell() override;
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
class MemoryMetadataReader: public MetadataReader {
|
||||
public:
|
||||
MemoryMetadataReader(const void* memory, size_t length);
|
||||
~MemoryMetadataReader();
|
||||
private:
|
||||
bool doOpen() override;
|
||||
void doClose() override;
|
||||
size_t doRead(void* ptr, size_t size, size_t n) override;
|
||||
int doSeek(long off, int whence) override;
|
||||
void doRewind() override;
|
||||
long doTell() override;
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
} // namespace sfz
|
||||
|
|
|
|||
|
|
@ -232,6 +232,9 @@ bool sfz::FilePool::checkSample(std::string& filename) const noexcept
|
|||
|
||||
bool sfz::FilePool::checkSampleId(FileId& fileId) const noexcept
|
||||
{
|
||||
if (loadedFiles.contains(fileId))
|
||||
return true;
|
||||
|
||||
std::string filename = fileId.filename();
|
||||
bool result = checkSample(filename);
|
||||
if (result)
|
||||
|
|
@ -239,64 +242,78 @@ bool sfz::FilePool::checkSampleId(FileId& fileId) const noexcept
|
|||
return result;
|
||||
}
|
||||
|
||||
absl::optional<sfz::FileInformation> getReaderInformation(sfz::AudioReader* reader) noexcept
|
||||
{
|
||||
const unsigned channels = reader->channels();
|
||||
if (channels != 1 && channels != 2)
|
||||
return {};
|
||||
|
||||
sfz::FileInformation returnedValue;
|
||||
returnedValue.end = static_cast<uint32_t>(reader->frames()) - 1;
|
||||
returnedValue.sampleRate = static_cast<double>(reader->sampleRate());
|
||||
returnedValue.numChannels = static_cast<int>(channels);
|
||||
|
||||
// Check for instrument info
|
||||
sfz::InstrumentInfo instrumentInfo {};
|
||||
if (reader->getInstrumentInfo(instrumentInfo)) {
|
||||
returnedValue.rootKey = clamp<uint8_t>(instrumentInfo.basenote, 0, 127);
|
||||
if (reader->type() == sfz::AudioReaderType::Forward) {
|
||||
if (instrumentInfo.loop_count > 0) {
|
||||
returnedValue.hasLoop = true;
|
||||
returnedValue.loopStart = instrumentInfo.loops[0].start;
|
||||
returnedValue.loopEnd =
|
||||
min(returnedValue.end, static_cast<int64_t>(instrumentInfo.loops[0].end - 1));
|
||||
}
|
||||
} else {
|
||||
// TODO loops ignored when reversed
|
||||
// prehaps it can make use of SF_LOOP_BACKWARD?
|
||||
}
|
||||
}
|
||||
|
||||
// Check for wavetable info
|
||||
sfz::WavetableInfo wt {};
|
||||
if (reader->getWavetableInfo(wt))
|
||||
returnedValue.wavetable = wt;
|
||||
|
||||
return returnedValue;
|
||||
}
|
||||
|
||||
absl::optional<sfz::FileInformation> sfz::FilePool::checkExistingFileInformation(const FileId& fileId) noexcept
|
||||
{
|
||||
const auto loadedFile = loadedFiles.find(fileId);
|
||||
if (loadedFile != loadedFiles.end())
|
||||
return loadedFile->second.information;
|
||||
|
||||
const auto preloadedFile = preloadedFiles.find(fileId);
|
||||
if (preloadedFile != preloadedFiles.end())
|
||||
return preloadedFile->second.information;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
absl::optional<sfz::FileInformation> sfz::FilePool::getFileInformation(const FileId& fileId) noexcept
|
||||
{
|
||||
auto existingInformation = checkExistingFileInformation(fileId);
|
||||
if (existingInformation)
|
||||
return existingInformation;
|
||||
|
||||
const fs::path file { rootDirectory / fileId.filename() };
|
||||
|
||||
if (!fs::exists(file))
|
||||
return {};
|
||||
|
||||
AudioReaderPtr reader = createAudioReader(file, fileId.isReverse());
|
||||
const unsigned channels = reader->channels();
|
||||
|
||||
if (channels != 1 && channels != 2) {
|
||||
DBG("[sfizz] Missing logic for " << reader->channels() << " channels, discarding sample " << fileId);
|
||||
return {};
|
||||
}
|
||||
|
||||
FileInformation returnedValue;
|
||||
returnedValue.end = static_cast<uint32_t>(reader->frames()) - 1;
|
||||
returnedValue.sampleRate = static_cast<double>(reader->sampleRate());
|
||||
returnedValue.numChannels = static_cast<int>(reader->channels());
|
||||
|
||||
InstrumentInfo instrumentInfo {};
|
||||
bool haveInstrumentInfo = reader->getInstrument(&instrumentInfo);
|
||||
|
||||
FileMetadataReader mdReader;
|
||||
bool mdReaderOpened = mdReader.open(file);
|
||||
|
||||
if (!haveInstrumentInfo) {
|
||||
// if no instrument, then try extracting from embedded RIFF chunks (flac)
|
||||
if (mdReaderOpened)
|
||||
haveInstrumentInfo = mdReader.extractInstrument(instrumentInfo);
|
||||
}
|
||||
|
||||
if (mdReaderOpened) {
|
||||
WavetableInfo wt;
|
||||
if (mdReader.extractWavetableInfo(wt))
|
||||
returnedValue.wavetable = wt;
|
||||
}
|
||||
|
||||
if (!fileId.isReverse()) {
|
||||
if (haveInstrumentInfo && instrumentInfo.loop_count > 0) {
|
||||
returnedValue.hasLoop = true;
|
||||
returnedValue.loopStart = instrumentInfo.loops[0].start;
|
||||
returnedValue.loopEnd =
|
||||
min(returnedValue.end, static_cast<int64_t>(instrumentInfo.loops[0].end - 1));
|
||||
}
|
||||
} else {
|
||||
// TODO loops ignored when reversed
|
||||
// prehaps it can make use of SF_LOOP_BACKWARD?
|
||||
}
|
||||
|
||||
if (haveInstrumentInfo)
|
||||
returnedValue.rootKey = clamp<uint8_t>(instrumentInfo.basenote, 0, 127);
|
||||
|
||||
return returnedValue;
|
||||
return getReaderInformation(reader.get());
|
||||
}
|
||||
|
||||
bool sfz::FilePool::preloadFile(const FileId& fileId, uint32_t maxOffset) noexcept
|
||||
{
|
||||
const auto loadedFile = loadedFiles.find(fileId);
|
||||
if (loadedFile != loadedFiles.end()) {
|
||||
loadedFile->second.preloadCallCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto fileInformation = getFileInformation(fileId);
|
||||
if (!fileInformation)
|
||||
return false;
|
||||
|
|
@ -368,28 +385,50 @@ sfz::FileDataHolder sfz::FilePool::loadFile(const FileId& fileId) noexcept
|
|||
if (!fileInformation)
|
||||
return {};
|
||||
|
||||
const fs::path file { rootDirectory / fileId.filename() };
|
||||
AudioReaderPtr reader = createAudioReader(file, fileId.isReverse());
|
||||
|
||||
const auto frames = static_cast<uint32_t>(reader->frames());
|
||||
const auto existingFile = loadedFiles.find(fileId);
|
||||
if (existingFile != loadedFiles.end()) {
|
||||
existingFile->second.preloadCallCount++;
|
||||
return { &existingFile->second };
|
||||
} else {
|
||||
fileInformation->sampleRate = static_cast<double>(reader->sampleRate());
|
||||
auto insertedPair = loadedFiles.insert_or_assign(fileId, {
|
||||
readFromFile(*reader, frames),
|
||||
*fileInformation
|
||||
});
|
||||
insertedPair.first->second.status = FileData::Status::Preloaded;
|
||||
insertedPair.first->second.preloadCallCount++;
|
||||
return { &insertedPair.first->second };
|
||||
}
|
||||
|
||||
const fs::path file { rootDirectory / fileId.filename() };
|
||||
AudioReaderPtr reader = createAudioReader(file, fileId.isReverse());
|
||||
|
||||
const auto frames = static_cast<uint32_t>(reader->frames());
|
||||
auto insertedPair = loadedFiles.insert_or_assign(fileId, {
|
||||
readFromFile(*reader, frames),
|
||||
*fileInformation
|
||||
});
|
||||
insertedPair.first->second.status = FileData::Status::Preloaded;
|
||||
insertedPair.first->second.preloadCallCount++;
|
||||
return { &insertedPair.first->second };
|
||||
}
|
||||
|
||||
sfz::FileDataHolder sfz::FilePool::loadFromRam(const FileId& fileId, const std::vector<char>& data) noexcept
|
||||
{
|
||||
const auto loaded = loadedFiles.find(fileId);
|
||||
if (loaded != loadedFiles.end())
|
||||
return { &loaded->second };
|
||||
|
||||
auto reader = createAudioReaderFromMemory(data.data(), data.size(), fileId.isReverse());
|
||||
auto fileInformation = getReaderInformation(reader.get());
|
||||
const auto frames = static_cast<uint32_t>(reader->frames());
|
||||
auto insertedPair = loadedFiles.insert_or_assign(fileId, {
|
||||
readFromFile(*reader, frames),
|
||||
*fileInformation
|
||||
});
|
||||
insertedPair.first->second.status = FileData::Status::Preloaded;
|
||||
insertedPair.first->second.preloadCallCount++;
|
||||
DBG("Added a file " << fileId.filename());
|
||||
return { &insertedPair.first->second };
|
||||
}
|
||||
|
||||
sfz::FileDataHolder sfz::FilePool::getFilePromise(const std::shared_ptr<FileId>& fileId) noexcept
|
||||
{
|
||||
const auto loaded = loadedFiles.find(*fileId);
|
||||
if (loaded != loadedFiles.end())
|
||||
return { &loaded->second };
|
||||
|
||||
const auto preloaded = preloadedFiles.find(*fileId);
|
||||
if (preloaded == preloadedFiles.end()) {
|
||||
DBG("[sfizz] File not found in the preloaded files: " << fileId->filename());
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ public:
|
|||
*
|
||||
* @return size_t
|
||||
*/
|
||||
size_t getNumPreloadedSamples() const noexcept { return preloadedFiles.size(); }
|
||||
size_t getNumPreloadedSamples() const noexcept { return preloadedFiles.size() + loadedFiles.size(); }
|
||||
|
||||
/**
|
||||
* @brief Get metadata information about a file.
|
||||
|
|
@ -236,6 +236,16 @@ public:
|
|||
*/
|
||||
FileDataHolder loadFile(const FileId& fileId) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Load a file from RAM and return its information. The file pool will store\
|
||||
* this data for future requests so use this function responsibly.
|
||||
*
|
||||
* @param fileId
|
||||
* @param data
|
||||
* @return A handle on the file data
|
||||
*/
|
||||
FileDataHolder loadFromRam(const FileId& fileId, const std::vector<char>& data) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Check that the sample exists. If not, try to find it in a case insensitive way.
|
||||
*
|
||||
|
|
@ -325,6 +335,8 @@ public:
|
|||
*/
|
||||
void triggerGarbageCollection() noexcept;
|
||||
private:
|
||||
|
||||
absl::optional<sfz::FileInformation> checkExistingFileInformation(const FileId& fileId) noexcept;
|
||||
fs::path rootDirectory;
|
||||
|
||||
bool loadInRam { config::loadInRam };
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "Metronome.h"
|
||||
#include "SynthConfig.h"
|
||||
#include "ScopedFTZ.h"
|
||||
#include "utility/Base64.h"
|
||||
#include "utility/StringViewHelpers.h"
|
||||
#include "utility/Timing.h"
|
||||
#include "utility/XmlHelpers.h"
|
||||
|
|
@ -130,6 +131,9 @@ void Synth::Impl::onParseFullBlock(const std::string& header, const std::vector<
|
|||
case hash("effect"):
|
||||
handleEffectOpcodes(members);
|
||||
break;
|
||||
case hash("sample"):
|
||||
handleSampleOpcodes(members);
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Unknown header: " << header << '\n';
|
||||
}
|
||||
|
|
@ -549,6 +553,47 @@ void Synth::Impl::handleEffectOpcodes(const std::vector<Opcode>& rawMembers)
|
|||
getOrCreateBus(busIndex).addEffect(std::move(fx));
|
||||
}
|
||||
|
||||
void Synth::Impl::handleSampleOpcodes(const std::vector<Opcode>& rawMembers)
|
||||
{
|
||||
absl::string_view name { "" };
|
||||
bool hasData { false };
|
||||
absl::string_view sampleData;
|
||||
|
||||
for (const Opcode& opcode : rawMembers) {
|
||||
switch (opcode.lettersOnlyHash) {
|
||||
case hash("name"):
|
||||
name = opcode.value;
|
||||
break;
|
||||
case hash("base&data"):
|
||||
if (opcode.parameters.front() == 64)
|
||||
sampleData = opcode.value;
|
||||
break;
|
||||
case hash("data"):
|
||||
hasData = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (name.empty())
|
||||
return;
|
||||
|
||||
if (hasData && sampleData.empty()) {
|
||||
DBG("The sample data provided for sample " << name
|
||||
<< " doesn't use base64 encoding, which is the only one sfizz knows how to decode.\n "
|
||||
<< "If it does, please use base64data= instead of data=."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sampleData.empty())
|
||||
return;
|
||||
|
||||
auto data = decodeBase64(sampleData);
|
||||
FilePool& filePool = resources_.getFilePool();
|
||||
FileId id { std::string(name) };
|
||||
filePool.loadFromRam(id, data);
|
||||
}
|
||||
|
||||
void Synth::Impl::resetDefaultCCValues() noexcept
|
||||
{
|
||||
fill(absl::MakeSpan(defaultCCValues_), 0.0f);
|
||||
|
|
|
|||
|
|
@ -88,6 +88,12 @@ struct Synth::Impl final: public Parser::Listener {
|
|||
* @param members the opcodes of the <effect> block
|
||||
*/
|
||||
void handleEffectOpcodes(const std::vector<Opcode>& members);
|
||||
/**
|
||||
* @brief Helper function to dispatch <effect> opcodes
|
||||
*
|
||||
* @param members the opcodes of the <effect> block
|
||||
*/
|
||||
void handleSampleOpcodes(const std::vector<Opcode>& members);
|
||||
/**
|
||||
* @brief Helper function to merge all the currently active opcodes
|
||||
* as set by the successive callbacks and create a new region to store
|
||||
|
|
|
|||
|
|
@ -288,8 +288,26 @@ void Parser::processOpcode()
|
|||
}
|
||||
|
||||
reader.getChar();
|
||||
|
||||
SourceLocation valueStart = reader.location();
|
||||
|
||||
// If we're parsing a base64 data field, ignore comments and process until the next header/directive
|
||||
if (nameExpanded == "base64data") {
|
||||
std::string valueRaw;
|
||||
reader.extractWhile(&valueRaw, [&reader](char c) {
|
||||
if (c == '<' || c == '#')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
SourceLocation valueEnd = reader.location();
|
||||
_currentOpcodes.emplace_back(nameExpanded, valueRaw);
|
||||
|
||||
if (_listener)
|
||||
_listener->onParseOpcode({ opcodeStart, opcodeEnd }, { valueStart, valueEnd }, nameExpanded, valueRaw);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string valueRaw;
|
||||
extractToEol(reader, &valueRaw);
|
||||
|
||||
|
|
|
|||
86
src/sfizz/utility/Base64.h
Normal file
86
src/sfizz/utility/Base64.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
// Inspired by the public domain implementation at https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Debug.h"
|
||||
#include <vector>
|
||||
#include <absl/strings/string_view.h>
|
||||
|
||||
namespace sfz
|
||||
{
|
||||
|
||||
inline std::vector<char> decodeBase64(absl::string_view input)
|
||||
{
|
||||
if (input.empty())
|
||||
return {};
|
||||
|
||||
std::size_t padding { 0 };
|
||||
auto length = input.length();
|
||||
|
||||
if (length >= 1 and input[length - 1] == '=')
|
||||
padding++;
|
||||
|
||||
if (length >= 2 and input[length - 2] == '=')
|
||||
padding++;
|
||||
|
||||
input.remove_suffix(padding);
|
||||
|
||||
std::vector<char> decoded;
|
||||
decoded.reserve(length);
|
||||
|
||||
auto cursor = input.begin();
|
||||
int32_t temp { 0 };
|
||||
size_t position { 0 };
|
||||
while (cursor != input.end()) {
|
||||
char c = *cursor++;
|
||||
if (c == ' ' || c == '\n' || c == '\t' || c == '\r') // Ignore whitespace
|
||||
continue;
|
||||
|
||||
if (c >= 0x41 && c <= 0x5A) // This area will need tweaking if
|
||||
temp |= c - 0x41; // you are using an alternate alphabet
|
||||
else if (c >= 0x61 && c <= 0x7A)
|
||||
temp |= c - 0x47;
|
||||
else if (c >= 0x30 && c <= 0x39)
|
||||
temp |= c + 0x04;
|
||||
else if (c == 0x2B)
|
||||
temp |= 0x3E; //change to 0x2D for URL alphabet
|
||||
else if (c == 0x2F)
|
||||
temp |= 0x3F; //change to 0x5F for URL alphabet
|
||||
else
|
||||
return {};
|
||||
|
||||
if (++position == 4) {
|
||||
decoded.push_back((temp >> 16) & 0x000000FF);
|
||||
decoded.push_back((temp >> 8 ) & 0x000000FF);
|
||||
decoded.push_back((temp ) & 0x000000FF);
|
||||
position = 0;
|
||||
temp = 0;
|
||||
} else {
|
||||
temp <<= 6;
|
||||
}
|
||||
}
|
||||
|
||||
switch(position) {
|
||||
case 3:
|
||||
decoded.push_back((temp >> 16) & 0x000000FF);
|
||||
decoded.push_back((temp >> 8 ) & 0x000000FF);
|
||||
break;
|
||||
case 2:
|
||||
decoded.push_back((temp >> 10) & 0x000000FF);
|
||||
break;
|
||||
case 1:
|
||||
return {};
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
}
|
||||
107
tests/FilesT.cpp
107
tests/FilesT.cpp
|
|
@ -270,10 +270,10 @@ TEST_CASE("[Files] Channels (channels.sfz)")
|
|||
REQUIRE(synth.getRegionView(1)->isStereo());
|
||||
}
|
||||
|
||||
TEST_CASE("[Files] Channels (channels_multi.sfz)")
|
||||
TEST_CASE("[Files] Generators and wavetables")
|
||||
{
|
||||
Synth synth;
|
||||
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/channels_multi.sfz");
|
||||
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/wavetables.sfz");
|
||||
REQUIRE(synth.getNumRegions() == 12);
|
||||
|
||||
int regionNumber = 0;
|
||||
|
|
@ -373,6 +373,69 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)")
|
|||
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto);
|
||||
}
|
||||
|
||||
TEST_CASE("[Files] Embedded wavetables")
|
||||
{
|
||||
Synth synth;
|
||||
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/wavetables_embedded.sfz");
|
||||
REQUIRE(synth.getNumRegions() == 7);
|
||||
|
||||
int regionNumber = 0;
|
||||
const Region* region = nullptr;
|
||||
|
||||
// explicit wavetable
|
||||
region = synth.getRegionView(regionNumber++);
|
||||
REQUIRE(region->sampleId->filename() == "ramp_wave.wav");
|
||||
REQUIRE(!region->isStereo());
|
||||
REQUIRE(!region->isGenerator());
|
||||
REQUIRE(region->isOscillator());
|
||||
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::On);
|
||||
|
||||
// explicit wavetable with multi
|
||||
region = synth.getRegionView(regionNumber++);
|
||||
REQUIRE(region->sampleId->filename() == "ramp_wave.wav");
|
||||
REQUIRE(region->isStereo());
|
||||
REQUIRE(!region->isGenerator());
|
||||
REQUIRE(region->isOscillator());
|
||||
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::On);
|
||||
|
||||
// explicit disabled wavetable
|
||||
region = synth.getRegionView(regionNumber++);
|
||||
REQUIRE(region->sampleId->filename() == "ramp_wave.wav");
|
||||
REQUIRE(!region->isStereo());
|
||||
REQUIRE(!region->isGenerator());
|
||||
REQUIRE(!region->isOscillator());
|
||||
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Off);
|
||||
|
||||
// explicit disabled wavetable with multi
|
||||
region = synth.getRegionView(regionNumber++);
|
||||
REQUIRE(region->sampleId->filename() == "ramp_wave.wav");
|
||||
REQUIRE(!region->isStereo());
|
||||
REQUIRE(!region->isGenerator());
|
||||
REQUIRE(!region->isOscillator());
|
||||
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Off);
|
||||
|
||||
// implicit wavetable (sound file < 3000 frames and wavetable tags)
|
||||
region = synth.getRegionView(regionNumber++);
|
||||
REQUIRE(region->sampleId->filename() == "wavetables/surge.wav");
|
||||
REQUIRE(!region->isGenerator());
|
||||
REQUIRE(region->isOscillator());
|
||||
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto);
|
||||
|
||||
// Parse oscillator=auto and same as above
|
||||
region = synth.getRegionView(regionNumber++);
|
||||
REQUIRE(region->sampleId->filename() == "wavetables/surge.wav");
|
||||
REQUIRE(!region->isGenerator());
|
||||
REQUIRE(region->isOscillator());
|
||||
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto);
|
||||
|
||||
// implicit non wavetable (sound file < 3000 frames but no wavetable tags)
|
||||
region = synth.getRegionView(regionNumber++);
|
||||
REQUIRE(region->sampleId->filename() == "short_non_wavetable.wav");
|
||||
REQUIRE(!region->isGenerator());
|
||||
REQUIRE(!region->isOscillator());
|
||||
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto);
|
||||
}
|
||||
|
||||
TEST_CASE("[Files] wrong (overlapping) replacement for defines")
|
||||
{
|
||||
Synth synth;
|
||||
|
|
@ -715,3 +778,43 @@ TEST_CASE("[Files] Unused samples are cleared on reloading")
|
|||
)");
|
||||
REQUIRE(synth.getNumPreloadedSamples() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("[Files] Embedded sample data")
|
||||
{
|
||||
sfz::Synth synth1;
|
||||
sfz::Synth synth2;
|
||||
synth1.loadSfzFile(fs::current_path() / "tests/TestFiles/kick.sfz");
|
||||
synth2.loadSfzFile(fs::current_path() / "tests/TestFiles/kick_embedded.sfz");
|
||||
REQUIRE(synth1.getNumPreloadedSamples() == 1);
|
||||
REQUIRE(synth2.getNumPreloadedSamples() == 1);
|
||||
|
||||
AudioBuffer<float> buffer1 { 2, 1024 };
|
||||
AudioBuffer<float> buffer2 { 2, 1024 };
|
||||
synth1.noteOn(0, 60, 100);
|
||||
synth2.noteOn(0, 60, 100);
|
||||
|
||||
for (unsigned i = 0; i < 100; ++i) {
|
||||
synth1.renderBlock(buffer1);
|
||||
synth2.renderBlock(buffer2);
|
||||
bool equal = true;
|
||||
for (unsigned j = 0; j < buffer1.getNumFrames(); ++j) {
|
||||
equal &= (buffer1.getSample(0, j) == buffer2.getSample(0, j));
|
||||
equal &= (buffer1.getSample(1, j) == buffer2.getSample(1, j));
|
||||
}
|
||||
REQUIRE(equal);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("[Files] Key center from audio file, with embedded sample data")
|
||||
{
|
||||
sfz::Synth synth;
|
||||
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/sample_keycenter_embedded.sfz");
|
||||
|
||||
REQUIRE(synth.getNumRegions() == 6);
|
||||
REQUIRE(synth.getRegionView(0)->pitchKeycenter == 38);
|
||||
REQUIRE(synth.getRegionView(1)->pitchKeycenter == 62);
|
||||
REQUIRE(synth.getRegionView(2)->pitchKeycenter == 38);
|
||||
REQUIRE(synth.getRegionView(3)->pitchKeycenter == 62);
|
||||
REQUIRE(synth.getRegionView(4)->pitchKeycenter == 10);
|
||||
REQUIRE(synth.getRegionView(5)->pitchKeycenter == 62);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "sfizz/utility/StringViewHelpers.h"
|
||||
#include "sfizz/utility/Base64.h"
|
||||
#include "catch2/catch.hpp"
|
||||
#include "absl/strings/string_view.h"
|
||||
using namespace Catch::literals;
|
||||
|
|
@ -66,3 +67,78 @@ TEST_CASE("[Helpers] trim")
|
|||
REQUIRE(trim(input).empty());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("[Parsing] Base64")
|
||||
{
|
||||
{
|
||||
auto result = sfz::decodeBase64("");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "" );
|
||||
}
|
||||
|
||||
{
|
||||
auto result = sfz::decodeBase64("Zg==");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "f" );
|
||||
}
|
||||
|
||||
{
|
||||
auto result = sfz::decodeBase64("Zg");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "f" );
|
||||
}
|
||||
|
||||
{
|
||||
auto result = sfz::decodeBase64("Zm8=");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "fo" );
|
||||
}
|
||||
|
||||
{
|
||||
auto result = sfz::decodeBase64("Zm8");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "fo" );
|
||||
}
|
||||
|
||||
{
|
||||
auto result = sfz::decodeBase64("Zm9v");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "foo" );
|
||||
}
|
||||
|
||||
{
|
||||
auto result = sfz::decodeBase64("Zm9vYg==");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "foob" );
|
||||
}
|
||||
|
||||
{
|
||||
auto result = sfz::decodeBase64("Zm9vYg");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "foob" );
|
||||
}
|
||||
|
||||
{
|
||||
auto result = sfz::decodeBase64("Zm9vYmE=");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "fooba" );
|
||||
}
|
||||
|
||||
{
|
||||
auto result = sfz::decodeBase64("Zm9vYmE");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "fooba" );
|
||||
}
|
||||
|
||||
{
|
||||
auto result = sfz::decodeBase64("Zm9vYmFy");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "foobar" );
|
||||
}
|
||||
|
||||
{
|
||||
auto result = sfz::decodeBase64("Zm9v\r\n Ym \tFy");
|
||||
absl::string_view view { result.data(), result.size() };
|
||||
REQUIRE( view == "foobar" );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -673,3 +673,75 @@ TEST_CASE("[Parsing] Expanded value of #include")
|
|||
REQUIRE(mock.fullBlockHeaders == expectedHeaders);
|
||||
REQUIRE(mock.fullBlockMembers == expectedMembers);
|
||||
}
|
||||
|
||||
TEST_CASE("[Parsing] Sample data")
|
||||
{
|
||||
sfz::Parser parser;
|
||||
ParsingMocker mock;
|
||||
parser.setListener(&mock);
|
||||
parser.parseString("/opcodeValueWithMultipleConsecutiveSpaces.sfz",R"(
|
||||
#define $test 2
|
||||
<sample> base64data=fdsfeq==w=ew=/////we/* $test */dsafr
|
||||
// fderwq==d=
|
||||
<region> sample=*sine
|
||||
)");
|
||||
|
||||
std::vector<std::vector<sfz::Opcode>> expectedMembers = {
|
||||
{{"base64data", R"(fdsfeq==w=ew=/////we/* $test */dsafr
|
||||
// fderwq==d=)"}},
|
||||
{{"sample", "*sine"}},
|
||||
};
|
||||
std::vector<std::string> expectedHeaders = {
|
||||
"sample", "region"
|
||||
};
|
||||
std::vector<sfz::Opcode> expectedOpcodes;
|
||||
|
||||
for (auto& members: expectedMembers)
|
||||
for (auto& opcode: members)
|
||||
expectedOpcodes.push_back(opcode);
|
||||
|
||||
REQUIRE(mock.beginnings == 1);
|
||||
REQUIRE(mock.endings == 1);
|
||||
REQUIRE(mock.errors.empty());
|
||||
REQUIRE(mock.warnings.empty());
|
||||
REQUIRE(mock.opcodes == expectedOpcodes);
|
||||
REQUIRE(mock.headers == expectedHeaders);
|
||||
REQUIRE(mock.fullBlockHeaders == expectedHeaders);
|
||||
REQUIRE(mock.fullBlockMembers == expectedMembers);
|
||||
}
|
||||
|
||||
TEST_CASE("[Parsing] Sample data 2")
|
||||
{
|
||||
sfz::Parser parser;
|
||||
ParsingMocker mock;
|
||||
parser.setListener(&mock);
|
||||
parser.parseString("/opcodeValueWithMultipleConsecutiveSpaces.sfz",R"(
|
||||
#define $test 2
|
||||
<region> sample=*sine
|
||||
<sample> base64data=fdsfeq==w=ew=/////we/* $test */dsafr
|
||||
// fderwq==d=
|
||||
)");
|
||||
|
||||
std::vector<std::vector<sfz::Opcode>> expectedMembers = {
|
||||
{{"sample", "*sine"}},
|
||||
{{"base64data", R"(fdsfeq==w=ew=/////we/* $test */dsafr
|
||||
// fderwq==d=)"}},
|
||||
};
|
||||
std::vector<std::string> expectedHeaders = {
|
||||
"region", "sample"
|
||||
};
|
||||
std::vector<sfz::Opcode> expectedOpcodes;
|
||||
|
||||
for (auto& members: expectedMembers)
|
||||
for (auto& opcode: members)
|
||||
expectedOpcodes.push_back(opcode);
|
||||
|
||||
REQUIRE(mock.beginnings == 1);
|
||||
REQUIRE(mock.endings == 1);
|
||||
REQUIRE(mock.errors.empty());
|
||||
REQUIRE(mock.warnings.empty());
|
||||
REQUIRE(mock.opcodes == expectedOpcodes);
|
||||
REQUIRE(mock.headers == expectedHeaders);
|
||||
REQUIRE(mock.fullBlockHeaders == expectedHeaders);
|
||||
REQUIRE(mock.fullBlockMembers == expectedMembers);
|
||||
}
|
||||
|
|
|
|||
1
tests/TestFiles/kick.sfz
Normal file
1
tests/TestFiles/kick.sfz
Normal file
|
|
@ -0,0 +1 @@
|
|||
<region> sample=kick.wav
|
||||
3
tests/TestFiles/kick_embedded.sfz
Normal file
3
tests/TestFiles/kick_embedded.sfz
Normal file
File diff suppressed because one or more lines are too long
627
tests/TestFiles/sample_keycenter_embedded.sfz
Normal file
627
tests/TestFiles/sample_keycenter_embedded.sfz
Normal file
|
|
@ -0,0 +1,627 @@
|
|||
<group> pitch_keycenter=sample oscillator=off
|
||||
<region> sample=root_key_38.wav
|
||||
<region> sample=root_key_62.wav
|
||||
<region> sample=root_key_38.flac
|
||||
<region> sample=root_key_62.flac
|
||||
<region> pitch_keycenter=10 sample=root_key_62.flac
|
||||
<region> key=10 sample=root_key_62.flac
|
||||
<sample> name=root_key_38.wav base64data=
|
||||
UklGRtQRAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAATElTVEQAAABJTkZPSVNGVCQAAABM
|
||||
b29wQXVkaXRpb25lZXIgKGxpYnNuZGZpbGUtMS4wLjI4KQBJQ1JEDAAAADIwMjEtMDQtMTUAAGN1
|
||||
ZSAEAAAAAAAAAHNtcGwkAAAAAAAAAAAAAACTWAAAJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGF0
|
||||
YSwRAAAH59pZWZsjIhLeRkT30ozETsbsmbarpBAE3Qa21Fhe56sJcWBlvNwJyBzLLmr67MWwvCvF
|
||||
LFaitgK0R/rUU3IBuu2VVSy9NTJxM4z2KF0jYOL2c6JkCks64L7S/EC79S7Z9g/eZ9I9rXKmOTOL
|
||||
2ZHJwV5ZyZHmY6wDKgLUOBRasSvD0TfwSQZd98euQMVWPyWHScT6IfkBov5dxxpcN2/uP19boxMC
|
||||
S5/5PAZCQc9VNfmkNhwgSGM1nFb39RxNZ7Ndx6gwB6q49fMKYpqTtBHukfsUFID2IPN8yHLH90dT
|
||||
wTPRpeMDx8inQ7+q/IRDocp6skAlmpmzos20H01/vJHiYBftzLA+67u4zaZZZRCtL1UHf6BmvDk2
|
||||
VM74nfFd8AUD6I6+HBSuDZ0hPfGyPoE6ErC2PphDSMtsJbSZOxRq1gTNh+y6+CMBxd+7omjKgk2f
|
||||
qTXtUx1b3pPx3hSySvs/0zlo+EHnDPUJUJC/I8m3malkWqZgy7Yja6YKRn9g3NkmzNXyZEFTEvX7
|
||||
ZqVu+fsLAvlYsMBQ+FCgKwk1jCoR/wPHcat6WqywYtE5vcqwps/3yZLiv1nM1jTC2FMQF730SuAL
|
||||
8qugpELZ/XwAP+g6XUMXj9LTR3ncM6H6C+1Boc7LHQc2ruWYVaRZ3/zWvji900Uysmn6n6Gpnwur
|
||||
yfxU5oAD2QOSwvKa7504EZFemxsqSgFAeF7EUZXl/jn/ufucmwkWBvdY3fyJnG2xcyDKSALKdrTQ
|
||||
UBDQ6MU258Qc1S9uUcVFJzHJVZDwVyn5CljU7wILA7e/6E6k1hvgSlKnRpZM3EQZ3YxPqVz6Y+cx
|
||||
S8AFslYcvPZY3h+dIq2/p/tUR1lPP11Eb+NEAu3oLh7NnltST0QaVJvCAb7+P9yiL6R4HlbmJVq3
|
||||
FO7joyVrO1X8ltu/yxZBGt9G3z5PrM0p0iQopqv7GwXE9PrI0zXJ6+avsei27w8S1lNdKBmz4FgV
|
||||
8GVo1LHDcON3YH1lMUai1dnK3yAjG4YQsQk9Tw9JeMs/Yar+3/XQ9dc4fCUeQ+9QykKl7J/AsTlr
|
||||
n7MHqejxnoJCwRLG6JQ82hGMyNOrF0PRT2AtM+0h8y8W4s/5JA4R7zRytHigXwdVQP1J5vG5HDzQ
|
||||
6xgE8A/WM7oaP17bJWNs65IqSzmzY35Zi0tfQO1CfxIwx6LPT8J1/QFbxDn8yw+poUDBOcxPNSRE
|
||||
xRwG2VqURIdcgsotZTw1RQzrYUO6b9DSNI23icP1GVJeEaALxiG/FNbD7vsisMogwl1VJtpZnLso
|
||||
iMP4JmJUDDBqG5EyLCZTTFYxAvUz8tgsrxUGKUX7oTP2UtKukStoWUnbElEcyW4wqA0y+vRYofy8
|
||||
OrZb8r6sZEgc7axULkjR50UX7je31RCASdAPSNfH+G/S9jj9xQa/KE74VwWyC8OnQoPh5Fnj6SBC
|
||||
cEzqTHYWvkF5pboUnvfPuKPcUy8XZSMx70yGDz4UV/Y1TZ+mKy/GHwPTlFSOB4zEO6D4MNOgH+h6
|
||||
JBnx28OCCp7XtkDb5XzjC+/gQ7ACFTLMDGEB1PxP84aqqaoNUCNeqLfZGH8XFPEFB6S4ChylDQRQ
|
||||
QiMrXBcO9K2iuTCy/Ou6YHb+2TVl6ejbKtIOtR5P7jlLGAbc20pYKa/FlkJpR+5EqvMc0onluBKL
|
||||
VJNZV/xkEVtPBqTAJZWim7xYq+eceiGUR7TsyWNWsywIfEyuUw66HsIgONBJL+5UFM4qusyVoVRj
|
||||
pRi3GnZR0wunsHX8xfQWu8y7w/0W3ovNDwH5ZbauLFRZY3TI8fVvSbq1aBYkpUNU0Pm4+TICOL7Z
|
||||
LC0KJrsW33++NaZQUY3VEAmu3wn3QyvXQ4c7M19/3hs7gKdKzAc4YdabKBQbgPKc2KAmW+DSOPW5
|
||||
8Eh0XTBNuuwwsuXFmhHQvsuwj01ELuT2LN4o80zUVbPs6zoZzlTd+d5LeiaZNh0OIdu3whtNXpt3
|
||||
CYcfursA7JMWh6IdPy0v0M5R6mNUAuZ60UAcTEMPFv2oN7HFL1T71TAuHpZbTRZD3sgrA77LH+RU
|
||||
uaSPIfX3pyqtQ15K0dqeTBEjm6MDtQCnYl5sAeLeOBRW3lNboCPv9bUkjbhcwH7cu60RPSch6D97
|
||||
YYzaZS7Qn31i+L/ZMMc/8KNCpf8lZy1Cr25BxjpEp27cSLPdIS4hMKgc37OwTjMN/nfXZqkrEiau
|
||||
7jC06zSpGKWvs22vLqEO2qxGW0dk5FRS9wZfqzab+OGRTN2oziQ+ZiMxkt8MqNSpsPa9QUkOjDSK
|
||||
UQ+6FkkWHCQMtFiTJzkmvaElL+KZzU4dEKnkvjqqsHP2VjwK+Z7cmUtzt3TcVRZt/eXqkiaAWj7G
|
||||
cs6nKGSx5e5XC+Azb2Gn/Qn1RSHHBcu9jCEt7k80z5+Fwl5Lqvw+ZQjeqD93Stv7uLVo+qlfDAeK
|
||||
uslTrTNk7woWdUuzRPe68Bi6PwYflKeY+ma+wsvEtfQSsZnyu+Q7c0sFH7s6EsNJ+MkeVyVkFM6y
|
||||
lh4MtbzT+wseT4gpnLsuNNQH+9y35ijhZmKx9ClCY7rcJlFevjPzJt+zNwkEDEc5jt18NSjLwGJp
|
||||
9PhFIa+drGhhRen+HiBKZqwAQegXoRqUtwZlLmKUs1Hz8D1f1MSz3TWzoSJBHlBVEbzmACNKVc+1
|
||||
klShUZ8QIzRcmqUjIS8M6jTc5BLR/NW2YMQNsdDU/sLYrMbuuRwtUYop6DacIKwxnBFaCpfcv170
|
||||
xnjLLK4ctba2MCWkT3u3auJlGOcHCyXdxFWeRUKj78q1q7ANGQPJ3QVZz86z/8jcn886EmHdF8Xe
|
||||
Qdc3EB0MIgnIJKAnQCaN4+IQH0RfLOHCnuUD6ybuWOrkxi1Eigb03dX28TU6SpMsJ1DRrNYyjyR/
|
||||
p0nk8Zwj5eladQ+pVEwZrtCBFENj9Ec68jwpbaQ/Ptyt9fg0wiPbvtYjL38f+TOt/lQDIvpy6IgW
|
||||
lcaXpnAkQRH0qSajygXKHzhesLjcVlYMibVsOPZkLEU/Q8w8cVnM1WllLM7wEiYuEVSB4HLG9vAU
|
||||
QT8VI6E5oUMi8yvnGJgyhTVFuP/rVi1a13fcQtNO83mu1NES0h5YPKgaxYbHPaet+dxAyjtX5/e6
|
||||
1Zu0PnJieBdBRj+dW9PJC48cjJ/o2jo78vHVoTKsyzSC2+EFsEm3E18+YjteIg+dhZz+LyX9xUNk
|
||||
BeFKI2WeBzAjLmGwuAsD0mR08mqo/hpl+Ljp0u+8UPXxagIiH9kz6aFpAivhrkZk1yOdJUpM2ooz
|
||||
4+Cqt4rSWsVqtotA9E4tsadfk+uer6/rZ/oCMXdKi0pnutQ0E9Y7I47thqONK1hWHevRC1fHp+6O
|
||||
7wwIx7vbNhkmu/SaYuZC5s4gS4NaHchT0LajNhogMRw7Sf5CFexbtsy6UcQYoyCwW+HdnhBf4BxQ
|
||||
Wz5rNUXZ/9+aV7qpr5/x5eqlAkk2G3ZXGD3ASWDBNUeO/eZY7Bs/YsAHcxGKyBrzysOcT1roGgjL
|
||||
+SgvyPHG0Sb+ezEkGF/vl0E9Hrc75E3bAIXw9j6L1+DT7JlguM43P1mrOqszl/q55ZtiF1TpD9BL
|
||||
DNacsTbfzJ7KCWQXVgPi1B/JHlkRsMJNby5bZDfojrjqPCom0fJAPexEPMQZMC4ZUV5FxFJlgVr6
|
||||
sdEO7z9o7tUmvbid8zjKiTZVXYUFCWYUUPQbbU0VGPAZOM8LN3Twx1t4w03HSjof7sZdGO0E5qm7
|
||||
Aewi2gTUPmGks9koqSHK0g62R1Lsov6sZfGQonZj9qZfVigVSycwv8/lVbGVtKoPCd9GVS1kbNb3
|
||||
28njfPheLlEk6DI0KVw+XPV15MGqzRFa0BC0NSUjKAe9RCKANf+sB9Fh9pvSOB0fDpTtesaUU27c
|
||||
SMSRw9EedQ50IsvmW8z77pSpVqS3SnT0ebUj9jAr9M/stPDsX/OZPQe8yAY0qNUYwz/WK43A8Ma5
|
||||
WLetyAmWtrPXMMJzK45gXg84XiDpWh8nnHLNZa0KuPYpAT9g7kxFh8UnSH4c9eeJ6BYrZ5riwYrw
|
||||
VcE+79jiddVsX9T/kBMzu+LEtg37MLG8PV3v6T2/SsS4/a/dp1RR1ngyiDNCAjcUoOmeUCdjTq5t
|
||||
UaC+QQVarEcUfE456EcN8OcqYuYuMhOACXT5UDZSAMpJ9FsDKxzhPNNCGdYdS59o5qy57RlqNumj
|
||||
qBYkS7dbszv76ayhlOkQ0k3wQF1mIBLsviU1zfRb0LganeP1Mpx0X4O6sONOzCY6JJv90Sq6NrtP
|
||||
Uv1WgMWZArE72rre10q/7cLVJ8T3nRmxHsOxSZ8H3mDlomE+/eDoIPHW/+3hChLqSaYUxeV5SwZN
|
||||
VgZJoO846vY1zBrVPMxw7WET7PHCFtLUFFD7yedZcpupz4rRNufnyiw1fzZrIp3OBbINziayCS1D
|
||||
GvpjshMruuKdOOZ/F3jQvCEfSlEkt86h1bHU6QlXvwsFcP0qwR47XjXKDpqfKATd3nIoJzlM9+Jc
|
||||
tVHuvb8QSU8GOFIxjVPdt2Xipb37Px3GYUhEqC8CobacGOUnGCKir3hPzvZnS9r30Pwo6R892r7p
|
||||
uwPOV7U3p1nyeyzmXPrDY/cUSjTiN0BMocy77Z8SUHnKgAhOoHlJAcrMKIFfFLMwuYZEUhFoHEbH
|
||||
DeijQZ3pbxxoXTT3Zah6I7btxNJ4tGLRYBsUWxXZlD1lYcPCo6GCA3fJglHqM6hYnUplTXGrvShT
|
||||
+DsubFbDRn0Jn9nN/H0AOTecC429i77FRGvYVfa8+RzNzTXr0BvI9V732AAyCsINxIr/RLRLqITm
|
||||
H8ZrNz5FwVpyJ5kl2P2pmgK8uWRMOP8t5bs4XWIMtPon7bmfNC6RvAfXuFwetWYWUSiO3dlAdsE2
|
||||
+I5PXA7AJI4gOO0WGZ7hZqyMsKni087cro60PGMh0WirLwlEMu3+VQ8O+uYhwkxf8Gs9wfxLspG0
|
||||
M9cq2isTXMDsToTRUke71QNRh8KL6CablwvEHWiwjiaXGvLnWjhgvdGz4NAbM0cUKll5GT2eMjDP
|
||||
r/S2I0tv7X737fcuFAXg1y8a9SYcdBoHHkqeAxw1w3cizzIrUKXWX7QZInP6jc5oWSDHQEkqTP1G
|
||||
6U3tFT1dbJ6y+kDkU/wGWdJewEJ3IoTtgviB1imlL/3uWMDOQ7lTJYi4TfYXQAxBIFdEqAk027fs
|
||||
V8kZRGVoP1bJFVw+RG0q79kp2hEdVdKJthrZRyZrFQgW0DE3rI4IK5rfy3zHGLmSKC+hiGBMGdqv
|
||||
KS6QN16hi+FvNipHTBEZLAMlVNWgn5RlyVhd2Le1fcsJZYcx70dvMClEEeoEMaCp9ReCUJc4ix+j
|
||||
Sn/ryjVmEqe8kD1XWn1ZUR4/BTAf7Nz8QDElINxZM/tjNfhFZZViYMPDRqYsG6F0ykL3ILHRSFzh
|
||||
HlD3AZfFN9Vb0WE+Sfh/qFcyXOs4LTDRJKS/o8arui9G5oZFTS3kRGJEfCneob4kvu9cqZxVYU3n
|
||||
wAQ4WMigqpDTWfQ75lULUczrRDoaEGXfyQ3h2M9r1DDrB+K8nd43J8FsMWEWHJ+I9KIeQSqtSmMu
|
||||
dxmqMa1VGOtkYOyZCSVd7obm/8kOIQ/FnUq3H1j1P8X6VSQw2haX0Uo0T+gl+U//GGWm/kBaUB2E
|
||||
woM+T+VjQsIJnNQNx8cD6NSDUoJY3CEWti4TT01Nmn7MQdzyxRK8/qU0Qw30r0AfxZVTm9nOw9Tr
|
||||
eM2AR8MUkqVpxr/wuhVuATAeHLO6PE4KOqUr+M4mzB4V34InrlG/IdhTXKchLqcw0AFpCCtc/+5r
|
||||
SJO5OUF+r6mamu9yu3zHvUaVN00viv4UUaQFbqK5XDBkqC8ZFeXcvfBnAAJlON4hDsUsc6iKqcvO
|
||||
NJ7z/s+wKr7M2azG
|
||||
<sample> name=root_key_62.wav base64data=
|
||||
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
|
||||
NJ7z/s+wKr7M2azG
|
||||
<sample> name=root_key_38.flac base64data=
|
||||
ZkxhQwAAACIQABAAABE3ABE3CsRA8AAACJa/iIn0E/di5nowFYEmMX5GAwAAEgAAAAAAAAAAAAAA
|
||||
AAAAAAAIlgQAACggAAAAcmVmZXJlbmNlIGxpYkZMQUMgMS4zLjIgMjAxNzAxMDEAAAAAAgAAEHJp
|
||||
ZmZSSUZG1BEAAFdBVkUCAAAccmlmZmZtdCAQAAAAAQABAESsAACIWAEAAgAQAAIAAFByaWZmTElT
|
||||
VEQAAABJTkZPSVNGVCQAAABMb29wQXVkaXRpb25lZXIgKGxpYnNuZGZpbGUtMS4wLjI4KQBJQ1JE
|
||||
DAAAADIwMjEtMDQtMTUAAAIAABByaWZmY3VlIAQAAAAAAAAAAgAAMHJpZmZzbXBsJAAAAAAAAAAA
|
||||
AAAAk1gAACYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAxyaWZmZGF0YSwRAACBACAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/+HkIAAiVKwLnB1nam1kiI94SREbS
|
||||
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
|
||||
<sample> name=root_key_62.flac base64data=
|
||||
ZkxhQwAAACIQABAAABE3ABE3CsRA8AAACJa/iIn0E/di5nowFYEmMX5GAwAAEgAAAAAAAAAAAAAA
|
||||
AAAAAAAIlgQAACggAAAAcmVmZXJlbmNlIGxpYkZMQUMgMS4zLjIgMjAxNzAxMDEAAAAAAgAAEHJp
|
||||
ZmZSSUZG1BEAAFdBVkUCAAAccmlmZmZtdCAQAAAAAQABAESsAACIWAEAAgAQAAIAAFByaWZmTElT
|
||||
VEQAAABJTkZPSVNGVCQAAABMb29wQXVkaXRpb25lZXIgKGxpYnNuZGZpbGUtMS4wLjI4KQBJQ1JE
|
||||
DAAAADIwMjEtMDQtMTUAAAIAABByaWZmY3VlIAQAAAAAAAAAAgAAMHJpZmZzbXBsJAAAAAAAAAAA
|
||||
AAAAk1gAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAxyaWZmZGF0YSwRAACBACAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/+HkIAAiVKwLnB1nam1kiI94SREbS
|
||||
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
|
||||
38
tests/TestFiles/table_embedded.sfz
Normal file
38
tests/TestFiles/table_embedded.sfz
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<region> oscillator=on sample=ramp_embedded.wav
|
||||
<sample> name=ramp_embedded.wav encoding=base64 data=UklGRiQIAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAIAAABgEGAgYDBgAGBQYGB
|
||||
gcGBAYJBgoGCwYIBg0GDgYPBgwGEQYSBhMGEAYVBhYGFwYUBhkGGgYbBhgGHQYeBh8GHAYhBiIGI
|
||||
wYgBiUGJgYnBiQGKQYqBisGKAYtBi4GLwYsBjEGMgYzBjAGNQY2BjcGNAY5BjoGOwY4Bj0GPgY/B
|
||||
jwGQQZCBkMGQAZFBkYGRwZEBkkGSgZLBkgGTQZOBk8GTAZRBlIGUwZQBlUGVgZXBlQGWQZaBlsGW
|
||||
AZdBl4GXwZcBmEGYgZjBmAGZQZmBmcGZAZpBmoGawZoBm0GbgZvBmwGcQZyBnMGcAZ1BnYGdwZ0B
|
||||
nkGegZ7BngGfQZ+Bn8GfAaBBoIGgwaABoUGhgaHBoQGiQaKBosGiAaNBo4GjwaMBpEGkgaTBpAGl
|
||||
QaWBpcGlAaZBpoGmwaYBp0GngafBpwGoQaiBqMGoAalBqYGpwakBqkGqgarBqgGrQauBq8GrAaxB
|
||||
rIGswawBrUGtga3BrQGuQa6BrsGuAa9Br4Gvwa8BsEGwgbDBsAGxQbGBscGxAbJBsoGywbIBs0Gz
|
||||
gbPBswG0QbSBtMG0AbVBtYG1wbUBtkG2gbbBtgG3QbeBt8G3AbhBuIG4wbgBuUG5gbnBuQG6QbqB
|
||||
usG6AbtBu4G7wbsBvEG8gbzBvAG9Qb2BvcG9Ab5BvoG+wb4Bv0G/gb/BvwDAQMCAwMDAAMFAwYDB
|
||||
wMEAwkDCgMLAwgDDQMOAw8DDAMRAxIDEwMQAxUDFgMXAxQDGQMaAxsDGAMdAx4DHwMcAyEDIgMjA
|
||||
yADJQMmAycDJAMpAyoDKwMoAy0DLgMvAywDMQMyAzMDMAM1AzYDNwM0AzkDOgM7AzgDPQM+Az8DP
|
||||
ANBA0IDQwNAA0UDRgNHA0QDSQNKA0sDSANNA04DTwNMA1EDUgNTA1ADVQNWA1cDVANZA1oDWwNYA
|
||||
10DXgNfA1wDYQNiA2MDYANlA2YDZwNkA2kDagNrA2gDbQNuA28DbANxA3IDcwNwA3UDdgN3A3QDe
|
||||
QN6A3sDeAN9A34DfwN8A4EDggODA4ADhQOGA4cDhAOJA4oDiwOIA40DjgOPA4wDkQOSA5MDkAOVA
|
||||
5YDlwOUA5kDmgObA5gDnQOeA58DnAOhA6IDowOgA6UDpgOnA6QDqQOqA6sDqAOtA64DrwOsA7EDs
|
||||
gOzA7ADtQO2A7cDtAO5A7oDuwO4A70DvgO/A7wDwQPCA8MDwAPFA8YDxwPEA8kDygPLA8gDzQPOA
|
||||
88DzAPRA9ID0wPQA9UD1gPXA9QD2QPaA9sD2APdA94D3wPcA+ED4gPjA+AD5QPmA+cD5APpA+oD6
|
||||
wPoA+0D7gPvA+wD8QPyA/MD8AP1A/YD9wP0A/kD+gP7A/gD/QP+A/8D/AABAAIAAwAAAAUABgAHA
|
||||
AQACQAKAAsACAANAA4ADwAMABEAEgATABAAFQAWABcAFAAZABoAGwAYAB0AHgAfABwAIQAiACMAI
|
||||
AAlACYAJwAkACkAKgArACgALQAuAC8ALAAxADIAMwAwADUANgA3ADQAOQA6ADsAOAA9AD4APwA8A
|
||||
EEAQgBDAEAARQBGAEcARABJAEoASwBIAE0ATgBPAEwAUQBSAFMAUABVAFYAVwBUAFkAWgBbAFgAX
|
||||
QBeAF8AXABhAGIAYwBgAGUAZgBnAGQAaQBqAGsAaABtAG4AbwBsAHEAcgBzAHAAdQB2AHcAdAB5A
|
||||
HoAewB4AH0AfgB/AHwAgQCCAIMAgACFAIYAhwCEAIkAigCLAIgAjQCOAI8AjACRAJIAkwCQAJUAl
|
||||
gCXAJQAmQCaAJsAmACdAJ4AnwCcAKEAogCjAKAApQCmAKcApACpAKoAqwCoAK0ArgCvAKwAsQCyA
|
||||
LMAsAC1ALYAtwC0ALkAugC7ALgAvQC+AL8AvADBAMIAwwDAAMUAxgDHAMQAyQDKAMsAyADNAM4Az
|
||||
wDMANEA0gDTANAA1QDWANcA1ADZANoA2wDYAN0A3gDfANwA4QDiAOMA4ADlAOYA5wDkAOkA6gDrA
|
||||
OgA7QDuAO8A7ADxAPIA8wDwAPUA9gD3APQA+QD6APsA+AD9AP4A/wD8AQD9Af0C/QP9AP0F/Qb9B
|
||||
/0E/Qn9Cv0L/Qj9Df0O/Q/9DP0R/RL9E/0Q/RX9Fv0X/RT9Gf0a/Rv9GP0d/R79H/0c/SH9Iv0j/
|
||||
SD9Jf0m/Sf9JP0p/Sr9K/0o/S39Lv0v/Sz9Mf0y/TP9MP01/Tb9N/00/Tn9Ov07/Tj9Pf0+/T/9P
|
||||
P1B/UL9Q/1A/UX9Rv1H/UT9Sf1K/Uv9SP1N/U79T/1M/VH9Uv1T/VD9Vf1W/Vf9VP1Z/Vr9W/1Y/
|
||||
V39Xv1f/Vz9Yf1i/WP9YP1l/Wb9Z/1k/Wn9av1r/Wj9bf1u/W/9bP1x/XL9c/1w/XX9dv13/XT9e
|
||||
f16/Xv9eP19/X79f/18/YH9gv2D/YD9hf2G/Yf9hP2J/Yr9i/2I/Y39jv2P/Yz9kf2S/ZP9kP2V/
|
||||
Zb9l/2U/Zn9mv2b/Zj9nf2e/Z/9nP2h/aL9o/2g/aX9pv2n/aT9qf2q/av9qP2t/a79r/2s/bH9s
|
||||
v2z/bD9tf22/bf9tP25/br9u/24/b39vv2//bz9wf3C/cP9wP3F/cb9x/3E/cn9yv3L/cj9zf3O/
|
||||
c/9zP3R/dL90/3Q/dX91v3X/dT92f3a/dv92P3d/d793/3c/eH94v3j/eD95f3m/ef95P3p/er96
|
||||
/3o/e397v3v/ez98f3y/fP98P31/fb99/30/fn9+v37/fj9/f3+/fw==
|
||||
169
tests/TestFiles/wavetables_embedded.sfz
Normal file
169
tests/TestFiles/wavetables_embedded.sfz
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
<region> sample=ramp_wave.wav oscillator=on
|
||||
<region> sample=ramp_wave.wav oscillator=on oscillator_multi=3
|
||||
<region> sample=ramp_wave.wav oscillator=off
|
||||
<region> sample=ramp_wave.wav oscillator=off oscillator_multi=3
|
||||
<region> sample=wavetables/surge.wav
|
||||
<region> oscillator=auto sample=wavetables/surge.wav
|
||||
<region> sample=short_non_wavetable.wav
|
||||
<sample> name=ramp_wave.wav base64data=
|
||||
UklGRiQIAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAIAAABgEGAgYDBgAGBQYGB
|
||||
gcGBAYJBgoGCwYIBg0GDgYPBgwGEQYSBhMGEAYVBhYGFwYUBhkGGgYbBhgGHQYeBh8GHAYhBiIGI
|
||||
wYgBiUGJgYnBiQGKQYqBisGKAYtBi4GLwYsBjEGMgYzBjAGNQY2BjcGNAY5BjoGOwY4Bj0GPgY/B
|
||||
jwGQQZCBkMGQAZFBkYGRwZEBkkGSgZLBkgGTQZOBk8GTAZRBlIGUwZQBlUGVgZXBlQGWQZaBlsGW
|
||||
AZdBl4GXwZcBmEGYgZjBmAGZQZmBmcGZAZpBmoGawZoBm0GbgZvBmwGcQZyBnMGcAZ1BnYGdwZ0B
|
||||
nkGegZ7BngGfQZ+Bn8GfAaBBoIGgwaABoUGhgaHBoQGiQaKBosGiAaNBo4GjwaMBpEGkgaTBpAGl
|
||||
QaWBpcGlAaZBpoGmwaYBp0GngafBpwGoQaiBqMGoAalBqYGpwakBqkGqgarBqgGrQauBq8GrAaxB
|
||||
rIGswawBrUGtga3BrQGuQa6BrsGuAa9Br4Gvwa8BsEGwgbDBsAGxQbGBscGxAbJBsoGywbIBs0Gz
|
||||
gbPBswG0QbSBtMG0AbVBtYG1wbUBtkG2gbbBtgG3QbeBt8G3AbhBuIG4wbgBuUG5gbnBuQG6QbqB
|
||||
usG6AbtBu4G7wbsBvEG8gbzBvAG9Qb2BvcG9Ab5BvoG+wb4Bv0G/gb/BvwDAQMCAwMDAAMFAwYDB
|
||||
wMEAwkDCgMLAwgDDQMOAw8DDAMRAxIDEwMQAxUDFgMXAxQDGQMaAxsDGAMdAx4DHwMcAyEDIgMjA
|
||||
yADJQMmAycDJAMpAyoDKwMoAy0DLgMvAywDMQMyAzMDMAM1AzYDNwM0AzkDOgM7AzgDPQM+Az8DP
|
||||
ANBA0IDQwNAA0UDRgNHA0QDSQNKA0sDSANNA04DTwNMA1EDUgNTA1ADVQNWA1cDVANZA1oDWwNYA
|
||||
10DXgNfA1wDYQNiA2MDYANlA2YDZwNkA2kDagNrA2gDbQNuA28DbANxA3IDcwNwA3UDdgN3A3QDe
|
||||
QN6A3sDeAN9A34DfwN8A4EDggODA4ADhQOGA4cDhAOJA4oDiwOIA40DjgOPA4wDkQOSA5MDkAOVA
|
||||
5YDlwOUA5kDmgObA5gDnQOeA58DnAOhA6IDowOgA6UDpgOnA6QDqQOqA6sDqAOtA64DrwOsA7EDs
|
||||
gOzA7ADtQO2A7cDtAO5A7oDuwO4A70DvgO/A7wDwQPCA8MDwAPFA8YDxwPEA8kDygPLA8gDzQPOA
|
||||
88DzAPRA9ID0wPQA9UD1gPXA9QD2QPaA9sD2APdA94D3wPcA+ED4gPjA+AD5QPmA+cD5APpA+oD6
|
||||
wPoA+0D7gPvA+wD8QPyA/MD8AP1A/YD9wP0A/kD+gP7A/gD/QP+A/8D/AABAAIAAwAAAAUABgAHA
|
||||
AQACQAKAAsACAANAA4ADwAMABEAEgATABAAFQAWABcAFAAZABoAGwAYAB0AHgAfABwAIQAiACMAI
|
||||
AAlACYAJwAkACkAKgArACgALQAuAC8ALAAxADIAMwAwADUANgA3ADQAOQA6ADsAOAA9AD4APwA8A
|
||||
EEAQgBDAEAARQBGAEcARABJAEoASwBIAE0ATgBPAEwAUQBSAFMAUABVAFYAVwBUAFkAWgBbAFgAX
|
||||
QBeAF8AXABhAGIAYwBgAGUAZgBnAGQAaQBqAGsAaABtAG4AbwBsAHEAcgBzAHAAdQB2AHcAdAB5A
|
||||
HoAewB4AH0AfgB/AHwAgQCCAIMAgACFAIYAhwCEAIkAigCLAIgAjQCOAI8AjACRAJIAkwCQAJUAl
|
||||
gCXAJQAmQCaAJsAmACdAJ4AnwCcAKEAogCjAKAApQCmAKcApACpAKoAqwCoAK0ArgCvAKwAsQCyA
|
||||
LMAsAC1ALYAtwC0ALkAugC7ALgAvQC+AL8AvADBAMIAwwDAAMUAxgDHAMQAyQDKAMsAyADNAM4Az
|
||||
wDMANEA0gDTANAA1QDWANcA1ADZANoA2wDYAN0A3gDfANwA4QDiAOMA4ADlAOYA5wDkAOkA6gDrA
|
||||
OgA7QDuAO8A7ADxAPIA8wDwAPUA9gD3APQA+QD6APsA+AD9AP4A/wD8AQD9Af0C/QP9AP0F/Qb9B
|
||||
/0E/Qn9Cv0L/Qj9Df0O/Q/9DP0R/RL9E/0Q/RX9Fv0X/RT9Gf0a/Rv9GP0d/R79H/0c/SH9Iv0j/
|
||||
SD9Jf0m/Sf9JP0p/Sr9K/0o/S39Lv0v/Sz9Mf0y/TP9MP01/Tb9N/00/Tn9Ov07/Tj9Pf0+/T/9P
|
||||
P1B/UL9Q/1A/UX9Rv1H/UT9Sf1K/Uv9SP1N/U79T/1M/VH9Uv1T/VD9Vf1W/Vf9VP1Z/Vr9W/1Y/
|
||||
V39Xv1f/Vz9Yf1i/WP9YP1l/Wb9Z/1k/Wn9av1r/Wj9bf1u/W/9bP1x/XL9c/1w/XX9dv13/XT9e
|
||||
f16/Xv9eP19/X79f/18/YH9gv2D/YD9hf2G/Yf9hP2J/Yr9i/2I/Y39jv2P/Yz9kf2S/ZP9kP2V/
|
||||
Zb9l/2U/Zn9mv2b/Zj9nf2e/Z/9nP2h/aL9o/2g/aX9pv2n/aT9qf2q/av9qP2t/a79r/2s/bH9s
|
||||
v2z/bD9tf22/bf9tP25/br9u/24/b39vv2//bz9wf3C/cP9wP3F/cb9x/3E/cn9yv3L/cj9zf3O/
|
||||
c/9zP3R/dL90/3Q/dX91v3X/dT92f3a/dv92P3d/d793/3c/eH94v3j/eD95f3m/ef95P3p/er96
|
||||
/3o/e397v3v/ez98f3y/fP98P31/fb99/30/fn9+v37/fj9/f3+/fw==
|
||||
<sample> name=wavetables/surge.wav base64data=
|
||||
UklGRjgEAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAc3JnZQgAAAABAAAAAAEAAGRhdGH8
|
||||
AwAAAAAkA0gGagmMDKsPyBLiFfkYCxwaHyMiKCUmKB8rES77MN8zujaMOVY8Fz/OQXpEHEe0ST9M
|
||||
v04zUZtT9VVCWIJas1zXXutg8WLoZM9mpmhtaiNsyW1eb+JwVHK1cwR1QXZrd4R4iXl8elx7KXzj
|
||||
fIl9HX6cfgl/YX+mf9h/9X//f/V/2H+mf2F/CX+cfh1+iX3jfCl8XHt8eol5hHhrd0F2BHW1c1Ry
|
||||
4nBeb8ltI2xtaqZoz2boZPFi62DXXrNcglpCWPVVm1MzUb9OP0y0SRxHekTOQRc/VjyMObo23zP7
|
||||
MBEuHysmKCglIyIaHwsc+RjiFcgSqw+MDGoJSAYkAwAA3Py4+Zb2dPNV8DjtHuoH5/Xj5uDd3dja
|
||||
2tfh1O/RBc8hzEbJdMaqw+nAMr6Gu+S4TLbBs0Gxza5lrAuqvqd+pU2jKaEVnw+dGJsxmVqXk5Xd
|
||||
kzeSopAej6yNS4z8ir+JlYh8h3eGhIWkhNeDHYN3guOBZIH3gJ+AWoAogAuAAYALgCiAWoCfgPeA
|
||||
ZIHjgXeCHYPXg6SEhIV3hnyHlYi/ifyKS4ysjR6PopA3kt2Tk5ValzGZGJsPnRWfKaFNo36lvqcL
|
||||
qmWsza5BscGzTLbkuIa7Mr7pwKrDdMZGySHMBc/v0eHU2tfY2t3d5uD14wfnHuo47VXwdPOW9rj5
|
||||
AAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsA
|
||||
HAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADMANAA1ADYANwA4
|
||||
ADkAOgA7ADwAPQA+AD8AQP9A/0H/Qv9D/0T/Rf9G/0f/SP9J/0r/S/9M/03/Tv9P/1D/Uf9S/1P/
|
||||
VP9V/1b/V/9Y/1n/Wv9b/1z/Xf9e/1//YP9h/2L/Y/9k/2X/Zv9n/2j/af9q/2v/bP9t/27/b/9w
|
||||
/3H/cv9z/3T/df92/3f/eP95/3r/e/98/33/fgGAAYEBggGDAYQBhQGGAYcBiAGJAYoBiwGMAY0B
|
||||
jgGPAZABkQGSAZMBlAGVAZYBlwGYAZkBmgGbAZwBnQGeAZ8BoAGhAaIBowGkAaUBpgGnAagBqQGq
|
||||
AasBrAGtAa4BrwGwAbEBsgGzAbQBtQG2AbcBuAG5AboBuwG8Ab0BvgG/AMAAwQDCAMMAxADFAMYA
|
||||
xwDIAMkAygDLAMwAzQDOAM8A0ADRANIA0wDUANUA1gDXANgA2QDaANsA3ADdAN4A3wDgAOEA4gDj
|
||||
AOQA5QDmAOcA6ADpAOoA6wDsAO0A7gDvAPAA8QDyAPMA9AD1APYA9wD4APkA+gD7APwA/QD+
|
||||
<sample> name=short_non_wavetable.wav base64data=
|
||||
UklGRtwWAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YbgWAAABAAIAAwAIAPn/DQD3
|
||||
/woA+/8FAAIA//8IAP3/BgAAAAQAAwADAAEABgD+/wcA/v8EAP//BgD+/wcA+/8GAP//AgACAAIA
|
||||
BAABAAAAAgD//wQAAAACAAEAAwACAAIAAQAEAP//BAADAAMAAQAAAAIA/v8IAPr/CwD3/w4A9v8K
|
||||
APr/BgABAAYA/v8AAP//AgACAAIAAAAAAAMA//8EAPz/CQD8/wUA+v8HAAEABAAAAAEAAQABAAIA
|
||||
AAACAAAABAABAAEABAD9/wQA/v8AAAMA//8FAPz/CAD7/wUAAQAAAAEABQD//w8ACwAOAAgACAAJ
|
||||
AA8ADgAVABUAIQAlACcAIgAgACkALQAyADQAOABEADoARwA9AFIATABUAE8AWABSAGAAVQBgAGEA
|
||||
YgBkAGEAZABtAHsAeQB+AHsAhACHAJEAjACYAJcApQCyALYAwQC/AMsA3QDhAO8A6AD4AAUBDAEV
|
||||
ARoBJgExAUABPwFXAVMBagFnAXcBhQGUAbIBwAHhAeAB+wH7ARYCFgIkAiwCPAJLAmECewKbAsQC
|
||||
0QLsAt4C9wIBAyADMAM9A04DXwOBA5QDtAPDA9YD7gMHBBYEMgQ/BGYEgASbBLsEygTnBAIFJwU+
|
||||
BWAFdwWNBacFrAXKBd4FCwYoBk4GXgaBBp4GvwbeBvsGHQcwBzwHVQdlB5MHnQeuB7gHwgfZB/AH
|
||||
DQgiCD4IWwiFCJcIrQi4CNYI/QgJCSYJIAlDCUUJYgltCYEJkQmYCasJrwnICdMJ5wnjCfYJ9QkI
|
||||
CgYKDwoLChUKCQoICgQKGQoQChUKAQoJCgYKAQrwCfQJ5QnqCdQJ1gnYCc0JxgmrCaYJkAlzCVUJ
|
||||
OgkjCQ4J7wjjCMgItwibCHYIWgg2CBYI6gfFB5EHfQdQBy0HBwfeBsEGkAZvBjoGJwbyBcQFjwVb
|
||||
BS4F9wTIBIsEWgQhBN0DnQNPAx8D2QKNAksC/wHJAXUBPgHwALsAZAAUAMv/dv8q/8f+fP4i/tD9
|
||||
af0M/bn8XfwP/KH7Tfvj+p/6Qvrm+YT5JfnI+Fv4+/eM9zz30fZt9vP1kfUt9dP0ZvT985DzJ/PI
|
||||
8mLy8vGL8QrxmPAf8LXvRe/a7mfu/u2H7SDtrOxW7OfrjesW67XqRur16YHpK+mf6Evowudp5+vm
|
||||
kuYz5s3lbeUL5bDkWOT545rjQePi4pDiGuK+4VThEOG+4G/gGuC9323fIN/T3oreOt7s3abdXt0T
|
||||
3c3ch9xK3Azc1tud22fbKdvx2q3ae9oy2gfaz9mo2XDZR9kU2e7Yydip2IrYcdhS2DnYJdgc2A7Y
|
||||
BNj11/HX5Nfd197X5dfh1/LX6df31/XXA9gc2DDYUNhZ2IXYj9jD2NjYANkp2U3Zb9mm2dXZDto+
|
||||
2m3ap9rj2iPbXdua2+LbHdxr3K7c9Nw+3Ynd39063pPe7N5D36rfAeBx4MHgNeGL4fHhYuLX4kjj
|
||||
wuM+5LzkPeWv5SDmouYq57bnPujO6F7p/OmT6jLryutj7Pfsku0t7szuZO8W8LLwWPEQ8svydfMG
|
||||
9JH0PfX19aH2UPf597P4c/lQ+hz76/uq/GH9EP7Q/o//SAALAdkBpwJmAwwEwgSvBYgGSQfAB0UI
|
||||
7gjaCdkKvguCDCsN4w21DoQPUhAbEd8RrhJcExkU1hS1FZMWaBcfGOsYnBldGgsbzxuMHEMdEB4N
|
||||
H/wfpSAmIakhhyJRI/ojcCT1JLMliyZZJxIo1CiTKUcq0ipxKwMsliwzLectmC47L78vhTA4MdIx
|
||||
ETJjMswyaTPxM240CzWlNTY2nDYRN5s3JziFOME4AzljObg5HTpoOrw6GTuHO/g7VDyEPLQ84Dwl
|
||||
PW897D1EPnI+cj5+PrQ+7D4cPyg/VD+TP78/qj+DP30/iT+rP+Q/JUAcQNw/qz+oP4Q/Wj8ePxE/
|
||||
Bz8nP2Q/Uj+7Pvw9qD3KPeo9qT0APYA8Xzx0PGk8MDzbO087rDoSOsM5pTleOew4XzjfN0836jar
|
||||
NkU2hTWINOMzjzNbM5UyszH9MLgwhzAWMDAvRC5ZLb4sRSzrK1krpyq/KRcpvih1KPkn3SZ1Jf8j
|
||||
GiPaIqwi6yGwIEkffR4xHvAdRR1eHGobgRqcGe8YVRibF5gWlxXfFE0UgRNjEggRCBA1D9gOfg4W
|
||||
DhQNmws6CksJzQhfCJYHawYnBTkEsQNIA3kCXAExAFn/hv6n/cT8DPxQ+4X6g/mb+PT3YPe59sj1
|
||||
s/Sz8/PyUfKB8b3w8O8o72Hudu1+7LrrNOvG6g3qO+lp6H7n1uY65v3liuXx5MjjkuKw4TPh8eCe
|
||||
4EHgf9+u3gLerN043ZjcvNs12wLbwdoh2mHZythC2LfXLtcL1y7XG9dk1nzV8dSr1HnUHtS+01/T
|
||||
BNOm0iTSndEv0RzRItH+0ITQKtD7z/LP5s/4z8fPI89szvbNzM3bzR/OTc4MzmPNrcyvzG/NCM7r
|
||||
zXLNCs0PzTPNPM0KzcHMxczfzOfMn8ybzPDMXc1EzdvM2cxSzcHN0s30zfrN182czczNJM5nzn7O
|
||||
mM7Wzg3PYM+1z/zPENDqz7vP1c810JXQ89BX0cHRHdJP0o3S1dLz0n/Tc9R71W3Vx9Sd1C/VtNXa
|
||||
1ZzVpNXI1UfWLdfr12rYhdjI2GLZ99le2pXaz9ou21bbrNsB3GzcuNwK3Xrd/N2d3jXfz99a4OXg
|
||||
UuHD4f/hUeLV4obj5OPu4yPksuQ25Xnlz+V55irns+cJ6IroNun86YDqy+r36hLrbOsO7KfsA+1b
|
||||
7ejtiu4O75PvDfBm8KDwuPAP8YrxFvKp8iXzm/Pt8yL0jvQo9av1HvaS9gj3h/cZ+L/4IflD+TP5
|
||||
m/kd+qP61/oz+7L7YPy4/Oz8V/0J/qz+2f7H/u7+vf+RACABRAE8AU4BtwFSAtACZQPvA0MENQQt
|
||||
BJ0EGQVqBXoFxwUnBmgGfQbUBoIHQgikCJ8IjgjHCFoJ+gk+CisKIgqMCk8L+wssDBwMAAxCDMQM
|
||||
Tg2FDY4Ntg0mDpgOxg7YDtcOHw+fDx4QPBAiEC8QSxBWEGgQxRBJEaQRzBHzER0SMBI1EjwSohII
|
||||
E1ETSxNkE5oTCRRIFHYUghTKFCEVeBVvFUsVFBVTFb8VLxYpFgsWORaTFtAW4hYQF1sXlhepF9AX
|
||||
AxgUGO8X0BfXFwQYJxhPGDsYQhi3GKwZhBqjGjUa6BkgGm0amxpPGiMaAxo9Gqwa6hrKGn4ashpc
|
||||
G80bqxtWG0UblhvLG84bxRvEG+cb7Rv5G+Qb8hsHHEocahyXHMkcAh0PHeQclBxlHI0cER2tHQAe
|
||||
8x2YHXkdkB2wHYkdJR0sHasdFx4THvIdFB5PHmQeHB7nHdYdAh4yHlYeHB7vHcMd8x00HkweTR5X
|
||||
HoYelR55HlAe/x3PHdcd/x3aHWcdCB1MHaEdth1fHSYdJB0THd0chxyGHIocqByfHL4cwRylHH4c
|
||||
QBwxHDkcQBwKHK0bLBvRGqkauBrQGqcaURoLGhoaJhonGvYZyBmQGUcZ1BhJGMgXlRemF+QX/Beo
|
||||
FyMXsxZ2FjwW8RWrFWwVIRXeFJgUcBQeFL4TZhMZE+ESfxIbEq4RXxEfEcYQbBDxD4EPSA8vDwkP
|
||||
0A5VDgMOlw1UDdsMdgweDOALlAsiC6cKPAq8CR0JqwiXCLEIcAjLByMHqAZVBhcG3gWaBQEFMwSE
|
||||
AzYDBQPcApYCTQLTAVcB+gC4AGUA3f9S/+7+jf5E/u39ev0B/WP8/fub+0/77Pp++h76zvl0+QP5
|
||||
l/g5+Mj3P/en9if20/WN9Vb13PRc9NfzhvNR8zjzHfP18qXyNPLS8WTx3/Bh8Pjvue9s7/3ule4v
|
||||
7urtqu1+7T7tCu2q7FvsE+zz69TrnetB68XqXuoe6vTpxOl46TXp7ujK6J/odehE6Afo1+ew54nn
|
||||
auc+5yrnB+e65m3mSOY45vPljeVR5W/lU+Ui5d3kCOU55Sfl0+SX5IrkiOSI5IzkluR65FTkIuQD
|
||||
5OHjr+Nr41PjYeOb47vj5uPt4+LjvuOo46rju+PW4+bj5+PS47zj2eP84yHk/+P2497jBeQl5EXk
|
||||
TuR65MHkAuUr5SrlQeVV5W7lZeV75X/lj+WG5b7l+uU35kvmduaL5sLm9eZI54jngudj53znzOcb
|
||||
6D/oSeiE6Mno/Oga6UPpf+m/6eHpCOoq6lzqd+qR6p/q0+ot65jr1Ovv6wzsYuzB7PfsBu0i7Wft
|
||||
ue3u7QvuLO517q7u9+4975/v7u808H7wr/C98MbwAfGD8eXxHvI88ory9PJC83bzi/PG8xf0cfSe
|
||||
9L307vRt9dj1T/Z19qH2p/a19uX2OPek9w34UfiN+NX4Hvlz+ZH51PkC+mf6o/q7+tT6+/pF+4/7
|
||||
2Psx/Ij8xvzk/BD9bf3U/Rv+RP5q/qz+6P4Z/0f/fP+4/w8AUwC2APkARwGIAc4BEgJhApsC3wIF
|
||||
AyMDRANkA7ED6QMgBFMElQTtBCAFbwWzBf0FLQZNBnoGqgbyBh0HVQdyB60H+wdHCIAIeAiZCL4I
|
||||
EQlpCZQJwQnhCR0KWgqYCsgK6goCCxgLYgvAC/ELAAz/Cx0MUgyDDKQMxgzjDAsNPA1yDZMNqg24
|
||||
DeoNKg5wDoQOpg7LDv8OMA9ID2MPeg9/D2sPhA+5DxMQRBBsEIUQlBCPEI4QpxDFEPIQABElESUR
|
||||
PRE+EVERVhFrEZURxhH0ERASGBItEkASZxJ7Eo4SgBJ+EnMScxJ9EoYSnBKyEtgS5RLqEsgSuhK8
|
||||
Er4S2xL1Eg8TCRPvEuIS4xLzEvQS7xLoEtES0RK4EroSlhKQEokSlRKnEqgSqhKwEoESaxJNElkS
|
||||
dRJbEi4S6hHHEcIRzxHLEdIRvxHGEb8RthGpEZURYRE4EfoQ7RDfENoQyxDDELQQpRBvEFQQHRAV
|
||||
EAIQ8Q/sD9UPuA93Dz4PEg/5DucOyA7DDrgOnw5vDjoOCQ7bDbYNlw1zDTcN4wy0DLQMmgxoDBMM
|
||||
3AvPC6oLkQtlCzsLFAvtCsoKmgp0Cl8KUAozCgUK1AmoCX0JSwkZCfcIyQiOCEsIFwj3B/EH1Qe3
|
||||
B6EHZQcqB+MGvAakBoYGRQYKBs4FlQViBRwFDAXpBOMElQRPBAgE+gPsA+QDkgNgAyYDKwMdA/UC
|
||||
tQJfAiYC7QHXAa0BdwE3AQIB7wDSAKEAYwAyABsA/v++/4r/Zv9G/x3/4P6o/mr+Qv4a/gr+3v3i
|
||||
/cv9vP2A/UP9Ff36/OT8ufyM/E38LvwV/AP85/ut+3z7Tvsq+xD76PrI+oT6Zfo6+kD6LPoO+tv5
|
||||
tvmK+Wj5Kvka+fX46fi3+Jv4iPh9+FT4MfgE+Pv31Pem93n3V/dM90D3LvcD9+r23fbg9sX2nvZy
|
||||
9mf2TfYu9gT23/W99aX1ffVy9Uj1T/U+9UD1LfUK9f/07PTh9Mz0ofR89GH0WvRR9Er0MPQb9Pzz
|
||||
6vPb89bz1/PF88LzuPO084zzb/NT81bzTfM28xXzGPMl8zDzNPMk8yfzCPPy8sryr/Kw8r3y3fLn
|
||||
8uzy2fK78p/yfPJj8nfyhvKV8n7yafJz8nDygvJp8nTydfJ98mvyX/Jq8nryb/JP8j/yQ/JP8kfy
|
||||
PPI88kHySvJO8kbyP/I38lrybvKE8oTyh/Ku8sby0/LJ8r3yzfLc8u3y9fL88v/yBfP28v7y8fIQ
|
||||
8yDzQPNc817zbfNw83zzfvOi87jz4vPS883z0/Pu8yL0OvRR9Ev0YPRp9Hz0gvSk9MD03PTr9Af1
|
||||
EPUn9Sz1RvVf9X/1lfWm9cb19/Uz9lD2XPZU9nT2i/a09sH25vb89hL3Jvc/92z3ivet97r34vcA
|
||||
+Cj4UPiE+Lz47/gV+S/5P/lN+Vz5e/m2+eH5Ffoi+kL6XPqG+rv66foq+z37VPtV+5L7wPv6+wv8
|
||||
I/ws/D78YPyV/M/8+/wr/Uf9a/18/ZP9uP3z/SD+Rv5q/pP+vf7i/hD/Of9h/5H/w//n//n/HQBe
|
||||
AJ4AsADIANwAJwFRAYcBnwG0AcwBAAJHAoMCsALGAv8CMQNkA4YDqwPNA/QDAgQkBEIEcwSZBMoE
|
||||
8gQuBVAFfgV8BZcFrAXoBRIGSgZ8BrAG2AbrBgwHFgc7B2QHiwe5B9IHBAgUCEAISwhtCHYIiQif
|
||||
CNIICAlCCVAJdAmRCdIJ/wkbCiEKMQpKCmAKgQqPCqAKqgrNCuoKFws4C1QLgQuOC60LyQvoCwkM
|
||||
CgwWDB0MNQxNDGMMdQyHDJ4Mpgy0DMEM1gzzDPcMDQ0YDSsNQw1MDWQNZw2IDYUNkQ1+DZANnw24
|
||||
DbUNqQ2dDZsNuA3hDeUN5g3QDecN6Q33Dd0N6A3jDeIN6A3cDeYN5g3xDfEN8g3tDesN7Q3bDdcN
|
||||
xg3DDbcNrg2gDZwNmA2NDZYNmw2SDYQNXQ1FDT0NPw1FDTMNGw0IDf8M3gzKDKUMnwyTDI0MeQx1
|
||||
DGAMRgwuDBQM/gvoC7oLqQuTC5ALdgtMCyoLIwsRCwALxgqLCnEKSwpHChwKCgrmCcYJqwl5CV8J
|
||||
GAkECdUIzQilCIcIZwhECBcI7wfHB7MHiQdNBwsHygaxBocGgAZWBkgGDQbmBbMFjQVbBTcFCQXa
|
||||
BLEEfARcBCgEBATeA58DdgMuAxMD4QLPAqICfgJQAigCBALSAaIBXAEyAfAA2gCOAFkACADt/9H/
|
||||
u/+F/1b/H/8P/9L+mf5T/hj++/3R/a79fP1Z/Sn9/fzF/Iz8Y/wt/Av82fu3+437b/s/+xf78Pq7
|
||||
+oz6WPoi+vn5xPmw+Y/5fflL+R/54/jJ+KX4kPhu+EL4Ifj+99b3sPd291j3RPc49yz3CPfk9sT2
|
||||
rfaX9nz2Q/YP9t/1w/W79an1mPV/9XX1ZvVX9TT1GPX29Nr0tfSa9HT0WfQ49Dn0NPQ99Dn0KfQl
|
||||
9B30G/QQ9PDz1PPH87TzyvO887nzl/OR85Lzo/Oe85Xzm/OW85/zjPOT85bzpvOe867zpPO587Lz
|
||||
wPPM89/z8vPx8+vz7PPu8wn0EvQe9CH0M/RQ9FX0Y/Re9Hj0ivSZ9K70s/TC9M703/T29AD1CvUk
|
||||
9T/1a/WE9Z71q/XG9d/17vUM9ib2QvZW9mn2avaF9p/2zPb59h33PfdP93T3mPew98r30vfy9xv4
|
||||
R/hy+In4pfi0+N347PgU+Tf5WvmG+aj5y/ni+QT6HvpR+mz6lfqx+t36DPs3+1X7bPuF+577xPva
|
||||
+wf8Gvwx/E78a/ym/Mn8/vwE/Sz9R/13/aL9zf3t/QH+Gv4c/jX+S/58/qr+zf7w/gT/Mv9J/2n/
|
||||
gf+j/8T/4f/9/xAAKQBAAFkAhQCqAM0A4AD2APwAEgEgAUABYQGHAZcBvwG7Ad8B9wEYAkACTQJu
|
||||
AnUCiwKSArQCxgLcAuEC4AL4AgYDJAMzA08DagNyA3cDVgNsA2oDkwOsA8AD4QPoA/cD/wMFBAkE
|
||||
FgQkBDsERQRLBEQEOwRABDwEPAQ0BDYEQARJBGIEbAR7BHAEagRnBGEEbARTBFYERgRHBFEEXARa
|
||||
BFQESQRFBGcEZQR3BFwEUwRJBFAEWARVBEwERAQ/BEAELwQxBCEELAQnBCYEMAQiBAkE9gPeA+QD
|
||||
1APCA7YDrQO+A7MDwQOrA64DpgOSA3wDYQNXA2cDbwNuA1UDPwMdAwoD8QLpAt8C3gLgAs8CzwK3
|
||||
ArgCsgK5Ap8ClAKBAmcCYAJIAlICWgJeAlsCRwIwAiYCIgInAiICHAIVAgIC8wHdAc0BxwHAAcwB
|
||||
wgHMAbMBpwGjAaQBqQGfAYUBhAFzAXwBeAF1AXkBcAF+AYEBhgF4AXMBYgFjAQ==
|
||||
|
|
@ -8,6 +8,8 @@
|
|||
#include "sfizz/FileMetadata.h"
|
||||
#include "sfizz/MathHelpers.h"
|
||||
#include "catch2/catch.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
|
|
@ -51,10 +53,10 @@ TEST_CASE("[Wavetables] Frequency ranges")
|
|||
|
||||
TEST_CASE("[Wavetables] Wavetable sound files: Surge")
|
||||
{
|
||||
sfz::FileMetadataReader reader;
|
||||
sfz::FileMetadataReader reader { "tests/TestFiles/wavetables/surge.wav" };
|
||||
sfz::WavetableInfo wt;
|
||||
|
||||
REQUIRE(reader.open("tests/TestFiles/wavetables/surge.wav"));
|
||||
REQUIRE(reader.open());
|
||||
REQUIRE(reader.extractWavetableInfo(wt));
|
||||
|
||||
REQUIRE(wt.tableSize == 256);
|
||||
|
|
@ -62,10 +64,10 @@ TEST_CASE("[Wavetables] Wavetable sound files: Surge")
|
|||
|
||||
TEST_CASE("[Wavetables] Wavetable sound files: Clm")
|
||||
{
|
||||
sfz::FileMetadataReader reader;
|
||||
sfz::FileMetadataReader reader { "tests/TestFiles/wavetables/clm.wav" };
|
||||
sfz::WavetableInfo wt;
|
||||
|
||||
REQUIRE(reader.open("tests/TestFiles/wavetables/clm.wav"));
|
||||
REQUIRE(reader.open());
|
||||
REQUIRE(reader.extractWavetableInfo(wt));
|
||||
|
||||
REQUIRE(wt.tableSize == 256);
|
||||
|
|
@ -73,9 +75,57 @@ TEST_CASE("[Wavetables] Wavetable sound files: Clm")
|
|||
|
||||
TEST_CASE("[Wavetables] Non-wavetable sound files")
|
||||
{
|
||||
sfz::FileMetadataReader reader;
|
||||
sfz::FileMetadataReader reader { "tests/TestFiles/snare.wav" };
|
||||
sfz::WavetableInfo wt;
|
||||
|
||||
REQUIRE(reader.open("tests/TestFiles/snare.wav"));
|
||||
REQUIRE(reader.open());
|
||||
REQUIRE(!reader.extractWavetableInfo(wt));
|
||||
}
|
||||
|
||||
std::vector<char> readWholeFile(const fs::path& path)
|
||||
{
|
||||
std::ifstream file(path, std::ios::binary | std::ios::ate);
|
||||
std::streamsize size = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<char> buffer(size);
|
||||
if (!file.read(buffer.data(), size))
|
||||
buffer.clear();
|
||||
|
||||
return buffer;
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("[Wavetables] Wavetable sound files: Surge, from memory")
|
||||
{
|
||||
auto file = readWholeFile("tests/TestFiles/wavetables/surge.wav");
|
||||
sfz::MemoryMetadataReader reader { file.data(), file.size() };
|
||||
sfz::WavetableInfo wt;
|
||||
|
||||
REQUIRE(reader.open());
|
||||
REQUIRE(reader.extractWavetableInfo(wt));
|
||||
|
||||
REQUIRE(wt.tableSize == 256);
|
||||
}
|
||||
|
||||
TEST_CASE("[Wavetables] Wavetable sound files: Clm, from memory")
|
||||
{
|
||||
auto file = readWholeFile("tests/TestFiles/wavetables/clm.wav");
|
||||
sfz::MemoryMetadataReader reader { file.data(), file.size() };
|
||||
sfz::WavetableInfo wt;
|
||||
|
||||
REQUIRE(reader.open());
|
||||
REQUIRE(reader.extractWavetableInfo(wt));
|
||||
|
||||
REQUIRE(wt.tableSize == 256);
|
||||
}
|
||||
|
||||
TEST_CASE("[Wavetables] Non-wavetable sound files, from memory")
|
||||
{
|
||||
auto file = readWholeFile("tests/TestFiles/snare.wav");
|
||||
sfz::MemoryMetadataReader reader { file.data(), file.size() };
|
||||
sfz::WavetableInfo wt;
|
||||
|
||||
REQUIRE(reader.open());
|
||||
REQUIRE(!reader.extractWavetableInfo(wt));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue