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

Custom IR selection in Binaural Monitoring plugin #266

Closed
wants to merge 66 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
66f273c
Correct output bus width after 128 ch update
firthm01 Jan 5, 2024
3be2607
Correct isBusesLayoutSupported after 128ch update
firthm01 Jan 8, 2024
11488c3
Fix missing default return in updateChannelCounts
firthm01 Jan 5, 2024
0ac8bc1
canClearSelection in EarComboBox
firthm01 Jan 9, 2024
25b60c1
EarComboBoxEntry ID's can be variant type
firthm01 Jan 9, 2024
358de81
getBearDataFileDirectory function
firthm01 Jan 4, 2024
5848d46
bearDataFileDir prop
firthm01 Jan 5, 2024
c84f90b
getCustomBearDataFiles func
firthm01 Jan 5, 2024
801daa7
BearStatus to track startup of bear and log error
firthm01 Jan 5, 2024
a331d42
statusLabel in UI footer
firthm01 Jan 5, 2024
77302ba
Initial text colours for different states
firthm01 Jan 5, 2024
9f8a3e7
rn rendererError to rendererStarted
firthm01 Jan 6, 2024
12000ee
Pass BearStatus to frontend connector
firthm01 Jan 8, 2024
95f7963
Frontend Connector gets access to status UI label
firthm01 Jan 8, 2024
4069c5e
Construct label shared_ptr
firthm01 Jan 8, 2024
f3abb01
Correct Status colour names
firthm01 Jan 9, 2024
077c2d5
Proper UI status text
firthm01 Jan 9, 2024
fa81bb3
Remove unnecessary assert
firthm01 Jan 9, 2024
f8385f2
Display data file in status on error
firthm01 Jan 9, 2024
64605eb
Initial combobox UI element for showing filter sets
firthm01 Jan 9, 2024
65e3646
Pass data file component and combobox handles to FE connector
firthm01 Jan 10, 2024
26dc62d
Plumbing up frontend connector for data file combo box
firthm01 Jan 12, 2024
3a49bc2
DataFileManager class
firthm01 Jan 12, 2024
a9d01c0
DataFileManager used by FE conn via proc
firthm01 Jan 12, 2024
9e915df
Pull data file metadata via bear
firthm01 Jan 14, 2024
fed7739
onSelectedDataFileChange callback
firthm01 Jan 15, 2024
a2792db
setSelectedDataFileDefault func
firthm01 Jan 15, 2024
e62567a
onSelectedDataFileChange callback triggers restart of BEAR
firthm01 Jan 15, 2024
6caf864
Remove dummy data
firthm01 Jan 15, 2024
6819712
Terminology
firthm01 Jan 15, 2024
3af34bb
Minor tidy of setSelectedDataFileDefault
firthm01 Jan 15, 2024
539b464
Avoid creating new insts of DataFile in updateAvailableFiles
firthm01 Jan 15, 2024
3af5c42
Better entry labelling
firthm01 Jan 15, 2024
0b11e0c
Fix dataFileValueBox visibility and placement
firthm01 Jan 15, 2024
59f6e40
Strip out BinauralRendererErrorOverlay
firthm01 Jan 15, 2024
14e3fbd
Fix wrong ext in CMakeLists headers
firthm01 Jan 15, 2024
477a2d7
Tidy comments and redundant code
firthm01 Jan 15, 2024
ae6b72a
value_box_data_file can be header only
firthm01 Jan 15, 2024
778a026
Zero output if processor/renderer not started
firthm01 Jan 15, 2024
fb7442e
Minor setRendererStatus improvements
firthm01 Jan 18, 2024
7d7cc81
Fix logic around silencing output
firthm01 Jan 19, 2024
b367cbc
Inform user of renderer restating in status text
firthm01 Jan 19, 2024
10a2f76
Remove redundant (and incorrect) method
firthm01 Jan 19, 2024
65adbbd
Change label wording
firthm01 Jan 19, 2024
59eee08
Sort data file entries by released and then by filename
firthm01 Jan 19, 2024
5fad750
Label first in data file list and mark custom ones
firthm01 Jan 19, 2024
d424662
Fix really silly logic mistake in rendererStarted
firthm01 Jan 21, 2024
e36b930
DataFileManager may as well set paths. dataFileManager no need to be …
firthm01 Jan 22, 2024
2dd522c
Remove unused method
firthm01 Jan 22, 2024
fb9492d
Support separate path for custom TFs. Reference DataFile entries by f…
firthm01 Jan 22, 2024
0e9a881
Fix item initial selection
firthm01 Jan 22, 2024
c8af109
Fix no default HRTF set if prefs file not found
firthm01 Jan 23, 2024
2ce5a45
Correct data file path on MacOS
firthm01 Jan 24, 2024
4f557ef
Simplify FEC setRendererStatus overloads
firthm01 Jan 26, 2024
f381667
EarComboBoxTextWithSubtextEntry class
firthm01 Jan 21, 2024
9c27a8f
Fit multiline subtext in to entry
firthm01 Jan 21, 2024
4b52131
Increase text brightness
firthm01 Jan 21, 2024
87765e7
Remove nonsense dummy text
firthm01 Jan 21, 2024
42f5a59
Consts for padding
firthm01 Jan 21, 2024
5518594
Take in to account padding for width calc
firthm01 Jan 21, 2024
53a91a8
Comment fix
firthm01 Jan 22, 2024
03f6ce1
addTextWithSubtextEntry supporting StringArray
firthm01 Jan 22, 2024
ea0ec6c
Support description in bear data file metadata
firthm01 Jan 22, 2024
1ff29cd
Use existing addLines func to replace own code
firthm01 Jan 23, 2024
b4f9728
Make wordwrapping code more readable
firthm01 Jan 23, 2024
ece9fe4
Handle multiple consecutive spaces in word wrapping logic
firthm01 Jan 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
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
Expand Up @@ -3,14 +3,16 @@ 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 +27,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 +50,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 +64,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 +85,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,151 @@
#include "bear_data_files.hpp"
#include <bear/api.hpp>

namespace {
bool operator==(const ear::plugin::DataFileManager::DataFile& lhs,
const ear::plugin::DataFileManager::DataFile& rhs) {
return (lhs.filename == rhs.filename) && (lhs.fullPath == rhs.fullPath) &&
(lhs.isBearRelease == rhs.isBearRelease) && (lhs.label == rhs.label) &&
(lhs.description == rhs.description);
}

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();
}

void DataFileManager::updateAvailableFiles() {
// Start a new vec and copy existing shared_ptrs of unchanged files
// This retains shared_ptrs unlike clear() and rebuild
std::vector<std::shared_ptr<DataFileManager::DataFile>> dfs;
// Lookup tfs where we expect to find custom files
auto files = getCustomDataFileDirectory().findChildFiles(
juce::File::TypesOfFileToFind::findFiles,
false, "*.tf");
// add our expected released files
for(auto const& bearReleaseFile : bearReleaseFiles_) {
if (bearReleaseFile.existsAsFile()) {
// note that in win, the released bear dir is the same as the custom
// dir, so we might have already found this with findChildFiles
files.addIfNotAlreadyThere(bearReleaseFile);
}
}
for (const auto& file : files) {
auto newDf = std::make_shared<DataFile>();
newDf->fullPath = file;
newDf->filename = file.getFileName();
try {
auto md = bear::DataFileMetadata::read_from_file(
file.getFullPathName().toStdString());
if (md.has_metadata()) {
newDf->label = md.get_label();
newDf->description = md.get_description();
newDf->isBearRelease = md.is_released();
}
} catch (std::exception) {
}
// Use the existing struct where possible (exists and is identical)
// -- this retains the same inst and shared_ptr
auto existingDf = getDataFileInfo(file.getFileName());
if (existingDf && *existingDf == *newDf) {
dfs.push_back(existingDf);
} else {
dfs.push_back(newDf);
}
}
availableDataFiles_ = dfs;
}

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

std::vector<std::shared_ptr<DataFileManager::DataFile>>
DataFileManager::getAvailableDataFiles() {
return availableDataFiles_;
}

int DataFileManager::getAvailableDataFilesCount() {
return availableDataFiles_.size();
}

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

bool DataFileManager::setSelectedDataFile(const juce::File& fullPath) {
auto found = getDataFileInfo(fullPath);
if (found == nullptr) return false;
if (found != selectedDataFile_) {
selectedDataFile_ = found;
if (selectedDataFileChangeCallback_) {
selectedDataFileChangeCallback_(selectedDataFile_);
}
}
return true;
}

bool DataFileManager::setSelectedDataFileDefault() {
updateAvailableFiles();
// look for any released by order
for (auto const& bearReleaseFile : bearReleaseFiles_) {
if (setSelectedDataFile(bearReleaseFile)) {
return true;
}
}
return false;
}

std::shared_ptr<DataFileManager::DataFile> DataFileManager::getDataFileInfo(
const juce::String& fullPath) {
return getDataFileInfo(juce::File(fullPath));
}

std::shared_ptr<DataFileManager::DataFile> DataFileManager::getDataFileInfo(
const juce::File& fullPath) {
auto it = std::find_if(availableDataFiles_.begin(), availableDataFiles_.end(),
[&fullPath](const std::shared_ptr<DataFile>& elm) {
return elm->fullPath == fullPath;
});

return it == availableDataFiles_.end() ? nullptr : *it;
}

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

} // namespace plugin
} // namespace ear
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once
#include "JuceHeader.h"
#include <memory>
#include <vector>
#include <functional>

namespace ear {
namespace plugin {

class DataFileManager {
public:
DataFileManager();

struct DataFile {
juce::String filename;
juce::File fullPath;
juce::String label;
juce::String description;
bool isBearRelease{false};
};

void updateAvailableFiles();
std::shared_ptr<DataFile> getSelectedDataFileInfo();
std::vector<std::shared_ptr<DataFile>> getAvailableDataFiles();
int getAvailableDataFilesCount();
bool setSelectedDataFile(const juce::String& fullPath);
bool setSelectedDataFile(const juce::File& fullPath);
bool setSelectedDataFileDefault();
std::shared_ptr<DataFile> getDataFileInfo(const juce::String& fullPath);
std::shared_ptr<DataFile> getDataFileInfo(const juce::File& fullPath);
void onSelectedDataFileChange(
std::function<void(std::shared_ptr<DataFile>)> callback);

private:
juce::Array<juce::File> bearReleaseFiles_;
std::shared_ptr<DataFile> selectedDataFile_;
std::vector<std::shared_ptr<DataFile>> availableDataFiles_;
std::function<void(std::shared_ptr<DataFile>)> selectedDataFileChangeCallback_;
};

} // namespace plugin
}

Loading
Loading