Added the background loading thread and the sample rate in the file
This commit is contained in:
parent
2a493873ae
commit
d0264f3416
5 changed files with 73 additions and 4 deletions
|
|
@ -63,6 +63,10 @@ if (WIN32)
|
||||||
target_include_directories(sndfile INTERFACE "${WIN_SNDFILE_PATH}/include")
|
target_include_directories(sndfile INTERFACE "${WIN_SNDFILE_PATH}/include")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Export MoodyCamel's queue as a library
|
||||||
|
add_library(readerwriterqueue INTERFACE)
|
||||||
|
target_include_directories(readerwriterqueue INTERFACE "external/readerwriterqueue")
|
||||||
|
|
||||||
# Export the compile_commands.json file
|
# Export the compile_commands.json file
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
|
@ -121,7 +125,7 @@ add_executable(sfizz sources/Main.cpp ${COMMON_SOURCES})
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
target_link_libraries(sfizz stdc++fs)
|
target_link_libraries(sfizz stdc++fs)
|
||||||
endif(UNIX)
|
endif(UNIX)
|
||||||
target_link_libraries(sfizz absl::strings cxxopts sndfile absl::flat_hash_map)
|
target_link_libraries(sfizz absl::strings cxxopts sndfile absl::flat_hash_map readerwriterqueue)
|
||||||
|
|
||||||
###############################
|
###############################
|
||||||
# Test application
|
# Test application
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(
|
||||||
SndfileHandle sndFile ( reinterpret_cast<const char*>(file.c_str()) );
|
SndfileHandle sndFile ( reinterpret_cast<const char*>(file.c_str()) );
|
||||||
FileInformation returnedValue;
|
FileInformation returnedValue;
|
||||||
returnedValue.end = static_cast<uint32_t>(sndFile.frames());
|
returnedValue.end = static_cast<uint32_t>(sndFile.frames());
|
||||||
|
returnedValue.sampleRate = static_cast<double>(sndFile.samplerate());
|
||||||
SF_INSTRUMENT instrumentInfo;
|
SF_INSTRUMENT instrumentInfo;
|
||||||
sndFile.command(SFC_GET_INSTRUMENT, &instrumentInfo, sizeof(instrumentInfo));
|
sndFile.command(SFC_GET_INSTRUMENT, &instrumentInfo, sizeof(instrumentInfo));
|
||||||
|
|
||||||
|
|
@ -27,4 +27,40 @@ std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(
|
||||||
// sndFile.command(SFC_GET_LOG_INFO, buffer, sizeof(buffer)) ;
|
// sndFile.command(SFC_GET_LOG_INFO, buffer, sizeof(buffer)) ;
|
||||||
// DBG(buffer);
|
// DBG(buffer);
|
||||||
return returnedValue;
|
return returnedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sfz::FilePool::enqueueLoading(Voice* voice, std::string_view sample, int numFrames)
|
||||||
|
{
|
||||||
|
if (!loadingQueue.try_enqueue({ voice, sample, numFrames }))
|
||||||
|
DBG("Problem enqueuing a file read for file " << sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sfz::FilePool::loadingThread()
|
||||||
|
{
|
||||||
|
FileLoadingInformation fileToLoad;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
loadingQueue.wait_dequeue(fileToLoad);
|
||||||
|
if (fileToLoad.voice == nullptr)
|
||||||
|
{
|
||||||
|
DBG("Background thread error: voice is null.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG("Background loading of: " << fileToLoad.sample);
|
||||||
|
std::filesystem::path file { rootDirectory / fileToLoad.sample };
|
||||||
|
if (!std::filesystem::exists(file))
|
||||||
|
{
|
||||||
|
DBG("Background thread: no file " << fileToLoad.sample << " exists.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SndfileHandle sndFile ( reinterpret_cast<const char*>(file.c_str()) );
|
||||||
|
auto fileLoaded = std::make_unique<StereoBuffer<float>>(fileToLoad.numFrames);
|
||||||
|
auto readBuffer = std::make_unique<Buffer<float>>(fileToLoad.numFrames * 2);
|
||||||
|
sndFile.readf(readBuffer->data(), fileToLoad.numFrames);
|
||||||
|
fileLoaded->readInterleaved<SIMDConfig::useSIMD>(readBuffer->data(), fileToLoad.numFrames);
|
||||||
|
fileToLoad.voice->setFileData(std::move(fileLoaded));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,19 +1,26 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "StereoBuffer.h"
|
#include "StereoBuffer.h"
|
||||||
#include "Defaults.h"
|
#include "Defaults.h"
|
||||||
|
#include "Voice.h"
|
||||||
#include <sndfile.hh>
|
#include <sndfile.hh>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <absl/container/flat_hash_map.h>
|
#include <absl/container/flat_hash_map.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <readerwriterqueue.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz
|
||||||
{
|
{
|
||||||
class FilePool
|
class FilePool
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FilePool() = default;
|
FilePool()
|
||||||
|
: fileLoadingThread(std::thread(&FilePool::loadingThread, this))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
void setRootDirectory(const std::filesystem::path& directory) { rootDirectory = directory; }
|
void setRootDirectory(const std::filesystem::path& directory) { rootDirectory = directory; }
|
||||||
size_t getNumPreloadedSamples() { return preloadedData.size(); }
|
size_t getNumPreloadedSamples() { return preloadedData.size(); }
|
||||||
|
|
||||||
|
|
@ -22,11 +29,22 @@ public:
|
||||||
uint32_t end { Default::sampleEndRange.getEnd() };
|
uint32_t end { Default::sampleEndRange.getEnd() };
|
||||||
uint32_t loopBegin { Default::loopRange.getStart() };
|
uint32_t loopBegin { Default::loopRange.getStart() };
|
||||||
uint32_t loopEnd { Default::loopRange.getEnd() };
|
uint32_t loopEnd { Default::loopRange.getEnd() };
|
||||||
|
double sampleRate { config::defaultSampleRate };
|
||||||
std::shared_ptr<StereoBuffer<float>> preloadedData;
|
std::shared_ptr<StereoBuffer<float>> preloadedData;
|
||||||
};
|
};
|
||||||
std::optional<FileInformation> getFileInformation(std::string_view filename);
|
std::optional<FileInformation> getFileInformation(std::string_view filename);
|
||||||
|
void enqueueLoading(Voice* voice, std::string_view sample, int numFrames);
|
||||||
private:
|
private:
|
||||||
std::filesystem::path rootDirectory;
|
std::filesystem::path rootDirectory;
|
||||||
|
struct FileLoadingInformation
|
||||||
|
{
|
||||||
|
Voice* voice;
|
||||||
|
std::string_view sample;
|
||||||
|
int numFrames;
|
||||||
|
};
|
||||||
|
moodycamel::BlockingReaderWriterQueue<FileLoadingInformation> loadingQueue;
|
||||||
|
void loadingThread();
|
||||||
|
std::thread fileLoadingThread;
|
||||||
Buffer<float> tempReadBuffer { config::preloadSize * 2 };
|
Buffer<float> tempReadBuffer { config::preloadSize * 2 };
|
||||||
// std::map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData;
|
// std::map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData;
|
||||||
absl::flat_hash_map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData;
|
absl::flat_hash_map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData;
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename)
|
||||||
region->sampleEnd = std::min(region->sampleEnd, fileInformation->end);
|
region->sampleEnd = std::min(region->sampleEnd, fileInformation->end);
|
||||||
region->loopRange.shrinkIfSmaller(fileInformation->loopBegin, fileInformation->loopEnd);
|
region->loopRange.shrinkIfSmaller(fileInformation->loopBegin, fileInformation->loopEnd);
|
||||||
region->preloadedData = fileInformation->preloadedData;
|
region->preloadedData = fileInformation->preloadedData;
|
||||||
|
region->sampleRate = fileInformation->sampleRate;
|
||||||
|
|
||||||
for (auto note = region->keyRange.getStart(); note <= region->keyRange.getEnd(); note++)
|
for (auto note = region->keyRange.getStart(); note <= region->keyRange.getEnd(); note++)
|
||||||
noteActivationLists[note].push_back(*currentRegion);
|
noteActivationLists[note].push_back(*currentRegion);
|
||||||
|
|
@ -156,7 +157,7 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename)
|
||||||
|
|
||||||
currentRegion++;
|
currentRegion++;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG("Removed " << regions.size() - std::distance(regions.begin(), lastRegion) - 1 << " out of " << regions.size() << " regions.");
|
DBG("Removed " << regions.size() - std::distance(regions.begin(), lastRegion) - 1 << " out of " << regions.size() << " regions.");
|
||||||
regions.resize(std::distance(regions.begin(), lastRegion) + 1);
|
regions.resize(std::distance(regions.begin(), lastRegion) + 1);
|
||||||
return parserReturned;
|
return parserReturned;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,20 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "StereoBuffer.h"
|
||||||
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace sfz
|
namespace sfz
|
||||||
{
|
{
|
||||||
class Voice
|
class Voice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
void setFileData(std::unique_ptr<StereoBuffer<float>> file)
|
||||||
|
{
|
||||||
|
fileData = std::move(file);
|
||||||
|
dataReady.store(true);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
|
std::atomic<bool> dataReady;
|
||||||
|
std::unique_ptr<StereoBuffer<float>> fileData;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Loading…
Add table
Reference in a new issue