Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BEAR TF selection review #270

Merged
merged 78 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
2038e54
Correct output bus width after 128 ch update
firthm01 Jan 5, 2024
ee65de9
Correct isBusesLayoutSupported after 128ch update
firthm01 Jan 8, 2024
7d47c97
Fix missing default return in updateChannelCounts
firthm01 Jan 5, 2024
25e3051
canClearSelection in EarComboBox
firthm01 Jan 9, 2024
19b58f6
EarComboBoxEntry ID's can be variant type
firthm01 Jan 9, 2024
adcabbe
getBearDataFileDirectory function
firthm01 Jan 4, 2024
50fc57c
bearDataFileDir prop
firthm01 Jan 5, 2024
c6f7c5b
getCustomBearDataFiles func
firthm01 Jan 5, 2024
96f802c
BearStatus to track startup of bear and log error
firthm01 Jan 5, 2024
852cce5
statusLabel in UI footer
firthm01 Jan 5, 2024
466f0ea
Initial text colours for different states
firthm01 Jan 5, 2024
3f7fd6d
rn rendererError to rendererStarted
firthm01 Jan 6, 2024
e082235
Pass BearStatus to frontend connector
firthm01 Jan 8, 2024
be07778
Frontend Connector gets access to status UI label
firthm01 Jan 8, 2024
53277c9
Construct label shared_ptr
firthm01 Jan 8, 2024
c65f2a5
Correct Status colour names
firthm01 Jan 9, 2024
0f07e6b
Proper UI status text
firthm01 Jan 9, 2024
f09f4dd
Remove unnecessary assert
firthm01 Jan 9, 2024
97e3955
Display data file in status on error
firthm01 Jan 9, 2024
95bccd3
Initial combobox UI element for showing filter sets
firthm01 Jan 9, 2024
5ff619d
Pass data file component and combobox handles to FE connector
firthm01 Jan 10, 2024
83501be
Plumbing up frontend connector for data file combo box
firthm01 Jan 12, 2024
f1b3489
DataFileManager class
firthm01 Jan 12, 2024
b15caf6
DataFileManager used by FE conn via proc
firthm01 Jan 12, 2024
e95205a
Pull data file metadata via bear
firthm01 Jan 14, 2024
5cfab16
onSelectedDataFileChange callback
firthm01 Jan 15, 2024
7285d4e
setSelectedDataFileDefault func
firthm01 Jan 15, 2024
81327d9
onSelectedDataFileChange callback triggers restart of BEAR
firthm01 Jan 15, 2024
efcefd5
Remove dummy data
firthm01 Jan 15, 2024
54303a4
Terminology
firthm01 Jan 15, 2024
b564978
Minor tidy of setSelectedDataFileDefault
firthm01 Jan 15, 2024
9a28ee3
Avoid creating new insts of DataFile in updateAvailableFiles
firthm01 Jan 15, 2024
8bd65af
Better entry labelling
firthm01 Jan 15, 2024
d91fb1f
Fix dataFileValueBox visibility and placement
firthm01 Jan 15, 2024
7a580d0
Strip out BinauralRendererErrorOverlay
firthm01 Jan 15, 2024
969a831
Fix wrong ext in CMakeLists headers
firthm01 Jan 15, 2024
c64e66f
Tidy comments and redundant code
firthm01 Jan 15, 2024
8b9f596
value_box_data_file can be header only
firthm01 Jan 15, 2024
d85d625
Zero output if processor/renderer not started
firthm01 Jan 15, 2024
4ba1a83
Minor setRendererStatus improvements
firthm01 Jan 18, 2024
7b55709
Fix logic around silencing output
firthm01 Jan 19, 2024
5244d91
Inform user of renderer restating in status text
firthm01 Jan 19, 2024
ff20334
Remove redundant (and incorrect) method
firthm01 Jan 19, 2024
f4476ee
Change label wording
firthm01 Jan 19, 2024
9d0eeb5
Sort data file entries by released and then by filename
firthm01 Jan 19, 2024
230ae3a
Label first in data file list and mark custom ones
firthm01 Jan 19, 2024
e3d2898
Fix really silly logic mistake in rendererStarted
firthm01 Jan 21, 2024
afca6fe
DataFileManager may as well set paths. dataFileManager no need to be …
firthm01 Jan 22, 2024
c786ce1
Remove unused method
firthm01 Jan 22, 2024
fec15bf
Support separate path for custom TFs. Reference DataFile entries by f…
firthm01 Jan 22, 2024
00a7543
Fix item initial selection
firthm01 Jan 22, 2024
1a82982
Fix no default HRTF set if prefs file not found
firthm01 Jan 23, 2024
15eb7a9
Correct data file path on MacOS
firthm01 Jan 24, 2024
854ac94
Simplify FEC setRendererStatus overloads
firthm01 Jan 26, 2024
c1154c6
EarComboBoxTextWithSubtextEntry class
firthm01 Jan 21, 2024
f4518c7
Fit multiline subtext in to entry
firthm01 Jan 21, 2024
07fac13
Increase text brightness
firthm01 Jan 21, 2024
296eb45
Remove nonsense dummy text
firthm01 Jan 21, 2024
ccb3848
Consts for padding
firthm01 Jan 21, 2024
792f973
Take in to account padding for width calc
firthm01 Jan 21, 2024
146f2d0
Comment fix
firthm01 Jan 22, 2024
cd6cf7e
addTextWithSubtextEntry supporting StringArray
firthm01 Jan 22, 2024
9170478
Support description in bear data file metadata
firthm01 Jan 22, 2024
0515a36
Use existing addLines func to replace own code
firthm01 Jan 23, 2024
0c9c370
Make wordwrapping code more readable
firthm01 Jan 23, 2024
b30a2d8
Handle multiple consecutive spaces in word wrapping logic
firthm01 Jan 23, 2024
c3f2cb3
Tidy by removing reference semantics for DataFile and using maps to s…
rsjbailey Feb 20, 2024
cc29999
Fix missing #include
rsjbailey Feb 21, 2024
b76d815
Bump C++ version
rsjbailey Feb 21, 2024
66cbef5
Really bump c++ version
rsjbailey Feb 21, 2024
1d76975
Fix char* init after c++ version bump
firthm01 Feb 21, 2024
d45d787
Clarify why metadata extraction is wrapped in a try
firthm01 Feb 21, 2024
191302d
Further clarification on why failure to extract metadata is not a wri…
firthm01 Feb 21, 2024
b094b4f
Fix changed/deleted files not updated
firthm01 Feb 23, 2024
0e6ef9b
Check for defaultIsSelected
firthm01 Feb 23, 2024
56b052a
Update bear to main with default TF inc metadata
firthm01 Feb 20, 2024
7b7be18
Check isBearRelease flag rather than assume from path
firthm01 Feb 23, 2024
ec183d1
Don't auto set default if previous TF now missing
firthm01 Feb 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.14)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <vector>
#include <string>
#include <../src/dynamic_renderer.hpp>
#include "variable_block_adapter.hpp"
#include <chrono>
Expand All @@ -9,6 +10,20 @@
namespace ear {
namespace plugin {

enum BearStatusStates {
NOT_ATTEMPTED = 0,
FAILED,
SUCCEEDED
};

struct BearStatus {
bear::Config startupConfig;
BearStatusStates startupSuccess{NOT_ATTEMPTED};
std::string startupErrorDesc;
BearStatusStates listenerDataSetSuccess{NOT_ATTEMPTED};
std::string listenerDataSetErrorDesc;
};

/**
* @brief Binaural monitoring plugin dsp implementation
*
Expand Down Expand Up @@ -47,6 +62,8 @@ class BinauralMonitoringAudioProcessor {
BinauralMonitoringAudioProcessor& operator=(
BinauralMonitoringAudioProcessor&&) = delete;

BearStatus getBearStatus() { return bearStatus; }

template <typename InBuffer, typename OutBuffer>
void process(const InBuffer& in, OutBuffer& out) {
using InTraits = BufferTraits<InBuffer>;
Expand All @@ -67,7 +84,7 @@ class BinauralMonitoringAudioProcessor {
void setListenerOrientation(float quatW, float quatX, float quatY,
float quatZ);

bool rendererError() { return !bearRenderer; }
bool rendererStarted() { return bearRenderer && bearStatus.startupSuccess == SUCCEEDED; }

void setIsPlaying(bool state) { isPlaying = state; }
bool getIsPlaying() { return isPlaying; }
Expand All @@ -84,6 +101,7 @@ class BinauralMonitoringAudioProcessor {
std::shared_ptr<bear::DynamicRenderer> bearRenderer; // TODO - why shared?
std::mutex bearListenerMutex_;
bear::Listener bearListener;
BearStatus bearStatus;

bool listenerQuatsDirty{false};
std::array<double, 4> listenerQuats{1.0, 0.0, 0.0, 0.0};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,25 @@ BinauralMonitoringAudioProcessor::BinauralMonitoringAudioProcessor(

bearListener.set_position_cart(std::array<double, 3>{0.0, 0.0, 0.0});

bearStatus.startupConfig = bearConfig;
try {
bearRenderer = std::make_shared<bear::DynamicRenderer>(
blockSize,
std::max(std::max(maxObjChannels, maxDsChannels), maxHoaChannels));
bearRenderer->set_config_blocking(bearConfig);
bearStatus.startupSuccess = BearStatusStates::SUCCEEDED;
try {
bearRenderer->set_listener(bearListener);
bearStatus.listenerDataSetSuccess = BearStatusStates::SUCCEEDED;
} catch (std::exception &e) {
bearStatus.listenerDataSetSuccess = BearStatusStates::FAILED;
bearStatus.listenerDataSetErrorDesc = e.what();
bearRenderer.reset();
assert(false);
}
} catch (std::exception &e) {
bearStatus.startupSuccess = BearStatusStates::FAILED;
bearStatus.startupErrorDesc = e.what();
bearRenderer.reset();
assert(false);
}
}

Expand Down Expand Up @@ -218,6 +224,7 @@ bool BinauralMonitoringAudioProcessor::updateChannelCounts(
// Do immediate update
bearRenderer->set_config_blocking(bearConfig);
}
return true;
}

} // namespace plugin
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(SOURCES_BINAURAL_MONITORING
${EPS_SHARED_DIR}/binary_data.cpp
${EPS_SHARED_DIR}/components/look_and_feel/slider.cpp
${EPS_SHARED_DIR}/components/ear_header.cpp
${EPS_SHARED_DIR}/components/ear_slider_label.cpp
${EPS_SHARED_DIR}/components/level_meter_calculator.cpp
${EPS_SHARED_DIR}/binary_data.cpp
${EPS_SHARED_DIR}/components/look_and_feel/slider.cpp
${EPS_SHARED_DIR}/components/ear_combo_box.cpp
${EPS_SHARED_DIR}/components/ear_header.cpp
${EPS_SHARED_DIR}/components/ear_slider_label.cpp
${EPS_SHARED_DIR}/components/level_meter_calculator.cpp
src/binaural_monitoring_frontend_connector.cpp
src/binaural_monitoring_plugin_editor.cpp
src/binaural_monitoring_plugin_processor.cpp
src/binaural_monitoring_plugin_editor.cpp
src/binaural_monitoring_plugin_processor.cpp
src/bear_data_files.cpp
src/orientation_osc.cpp
)

Expand All @@ -25,6 +23,7 @@ set(HEADERS_BINAURAL_MONITORING
${EPS_SHARED_DIR}/binary_data.hpp

${EPS_SHARED_DIR}/components/ear_button.hpp
${EPS_SHARED_DIR}/components/ear_combo_box.hpp
${EPS_SHARED_DIR}/components/ear_header.hpp
${EPS_SHARED_DIR}/components/ear_inverted_slider.hpp
${EPS_SHARED_DIR}/components/ear_slider.hpp
Expand All @@ -47,10 +46,11 @@ set(HEADERS_BINAURAL_MONITORING
src/binaural_monitoring_frontend_connector.hpp
src/binaural_monitoring_plugin_editor.hpp
src/binaural_monitoring_plugin_processor.hpp
src/error_overlay.hpp
src/bear_data_files.hpp
src/headphone_channel_meter.hpp
src/headphone_channel_meter_box.hpp
src/orientation_osc.hpp
src/value_box_data_file.hpp
src/value_box_orientation.hpp
src/value_box_osc.hpp
)
Expand All @@ -60,7 +60,7 @@ source_group("Header Files" FILES ${HEADERS_BINAURAL_MONITORING})
add_juce_vst3_plugin(
ear_binaural_monitoring
SOURCES ${SOURCES_BINAURAL_MONITORING} ${HEADERS_BINAURAL_MONITORING}
IDE_FOLDER ${IDE_FOLDER_PLUGINS}
IDE_FOLDER ${IDE_FOLDER_PLUGINS}
CODE_SUFFIX "F0" # Speaker Monitoring suffixes start from A0 and increment. For bin, lets use F0 (Note FF is scene)
DISPLAY_NAME "EAR Binaural Monitoring"
DESCRIPTION "The binaural monitoring plugin"
Expand All @@ -81,7 +81,7 @@ if(APPLE)
add_custom_command(TARGET ear_binaural_monitoring_VST3 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${TENSORFILE_FULLPATH} "$<TARGET_FILE_DIR:ear_binaural_monitoring_VST3>/../Resources/${TENSORFILE_FILENAME}"
)
install(FILES ${TENSORFILE_FULLPATH} DESTINATION "${EPS_PLUGIN_INSTALL_PREFIX}ear-production-suite/EAR Binaural Monitoring.vst3/Contents/Resources")
install(FILES ${TENSORFILE_FULLPATH} DESTINATION "${EPS_PLUGIN_INSTALL_PREFIX}ear-production-suite/EAR Binaural Monitoring.vst3/Contents/Resources")
else()
add_custom_command(TARGET ear_binaural_monitoring_VST3 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${TENSORFILE_FULLPATH} "$<TARGET_FILE_DIR:ear_binaural_monitoring_VST3>/${TENSORFILE_FILENAME}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
#include "bear_data_files.hpp"
#include <bear/api.hpp>

namespace {
juce::File getBearDataFileDirectory() {
auto vstPath = juce::File::getSpecialLocation(
juce::File::SpecialLocationType::currentExecutableFile);
vstPath = vstPath.getParentDirectory();
#ifdef __APPLE__
vstPath = vstPath.getParentDirectory();
vstPath = vstPath.getChildFile("Resources");
#endif
return vstPath;
};

juce::File getCustomDataFileDirectory() {
auto vstPath = juce::File::getSpecialLocation(
juce::File::SpecialLocationType::currentExecutableFile);
vstPath = vstPath.getParentDirectory();
#ifdef __APPLE__
// vstPath is `EAR Binaural Monitoring.vst3/Contents/MacOS` - traverse up x3 to get to dir containing vst3 bundle
vstPath = vstPath.getParentDirectory();
vstPath = vstPath.getParentDirectory();
vstPath = vstPath.getParentDirectory();
#endif
return vstPath;
};

}

namespace ear {
namespace plugin {
DataFileManager::DataFileManager() {
bearReleaseFiles_.add(
getBearDataFileDirectory().getChildFile(BEAR_DATA_FILE));
updateAvailableFiles();
}

namespace {
void setFromMetadata(DataFileManager::DataFile& dataFile) {
try {
auto md = bear::DataFileMetadata::read_from_file(
dataFile.fullPath.getFullPathName().toStdString());
if (md.has_metadata()) {
dataFile.label = md.get_label();
dataFile.description = md.get_description();
dataFile.isBearRelease = md.is_released();
}
}
catch(std::exception const&) {
firthm01 marked this conversation as resolved.
Show resolved Hide resolved
/*
`read_from_file` could throw if;
- the file does not exist, or otherwise unreadable
- the file is not a valid tensorfile
- the metadata within the file is not of the expected structure
In all these cases, and any other, silently skip metadata extraction

Note that a file with bad metadata may still be a usable filter set
so we don't want to strike it off yet, nor is it worth doing deeper
checks here... the user can still select it as the processor will
catch unusable files (unreadable/invalid/corrupt etc) anyway when
it tries to start BEAR with it, and will report the actual error.
*/
}
}

void updateFile(juce::File const& file, DataFileManager::FileMap& file_map,
bool mustBeRelease) {
DataFileManager::DataFile df{.filename = file.getFileName(),
.fullPath = file};
setFromMetadata(df);
if (!mustBeRelease || df.isBearRelease) {
file_map.insert({file, std::move(df)});
}
}
} // namespace

bool DataFileManager::onlyContainsDefault() const {
return customDataFiles.empty() && releasedDataFiles.size() == 1u;
}

bool DataFileManager::defaultIsSelected() const {
return selectedDataFile_.has_value() &&
releasedDataFiles.contains(selectedDataFile_->fullPath);
}

void DataFileManager::updateAvailableFiles() {
releasedDataFiles.clear();
customDataFiles.clear();

// add our expected released files
for (auto const& file : bearReleaseFiles_) {
firthm01 marked this conversation as resolved.
Show resolved Hide resolved
if (file.existsAsFile()) {
updateFile(file, releasedDataFiles, true);
firthm01 marked this conversation as resolved.
Show resolved Hide resolved
}
}

auto custom_files = getCustomDataFileDirectory().findChildFiles(
juce::File::TypesOfFileToFind::findFiles, false, "*.tf");
for (const auto& file : custom_files) {
if (!releasedDataFiles.contains(file)) { // on windows the custom / release
// dirs are the same
updateFile(file, customDataFiles, false);
}
}
}

std::optional<DataFileManager::DataFile>
DataFileManager::getSelectedDataFileInfo() const {
return selectedDataFile_;
}

std::vector<DataFileManager::DataFile>
DataFileManager::getAvailableDataFiles() const {
std::vector<DataFile> files;
files.reserve(getAvailableDataFilesCount());
auto fileExtractor = [](auto const& file) { return file.second; };
std::transform(releasedDataFiles.begin(), releasedDataFiles.end(), std::back_inserter(files), fileExtractor);
std::transform(customDataFiles.begin(), customDataFiles.end(), std::back_inserter(files), fileExtractor);
return files;
}

std::size_t DataFileManager::getAvailableDataFilesCount() const {
return releasedDataFiles.size() + customDataFiles.size();
}

void DataFileManager::setSelectedDataFile(DataFile const& file) {
if(!selectedDataFile_ || file != *selectedDataFile_) {
selectedDataFile_ = file;
selectedDataFileChangeCallback_(file);
}
}

bool DataFileManager::setSelectedDataFile(const juce::String& fullPath) {
return setSelectedDataFile(juce::File(fullPath));
}

bool DataFileManager::setSelectedDataFile(const juce::File& fullPath) {
auto const found = getDataFileInfo(fullPath);
if (found) {
setSelectedDataFile(*found);
}
return static_cast<bool>(found);
}

bool DataFileManager::setSelectedDataFileDefault() {
updateAvailableFiles();
auto found = false;
if(!releasedDataFiles.empty()) {
setSelectedDataFile(releasedDataFiles.begin()->second);
found = true;
}
return found;
}

namespace {
std::optional<DataFileManager::DataFile> getDataFile(DataFileManager::FileMap const& map, juce::File const& file) {
std::optional<DataFileManager::DataFile> dataFile;
if(auto it = map.find(file); it != map.end()) {
dataFile = it->second;
}
return dataFile;
}
}

std::optional<DataFileManager::DataFile> DataFileManager::getDataFileInfo(
const juce::File& fullPath) const {
auto file = getDataFile(releasedDataFiles, fullPath);
if(!file) {
file = getDataFile(customDataFiles, fullPath);
}
return file;
}

void DataFileManager::onSelectedDataFileChange(
std::function<void(DataFile const&)> callback) {
selectedDataFileChangeCallback_ = std::move(callback);
}

} // namespace plugin
} // namespace ear
Loading
Loading