Skip to content

Commit db93ec3

Browse files
committed
Adds source code
1 parent c79a8a0 commit db93ec3

21 files changed

Lines changed: 2877 additions & 0 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
builds/
2+
/JuceLibraryCode

3dti_AudioToolkit_Plugin.jucer

Lines changed: 489 additions & 0 deletions
Large diffs are not rendered by default.

Resources/About.txt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
3D Tune-In Toolkit VST plugin V1.0
2+
3+
The 3D Tune-In Toolkit VST plugin was developed by Ragnar Hrafnkelsson, under the supervision of Lorenzo Picinali and Arcadio Reyes-Lecuona, as a VST interface for the 3D Tune-In Toolkit. For technical details, please refer to:
4+
5+
Picinali, L., Hrafnkelsson, R., & Reyes-Lecuona, A. (2019, March). The 3D Tune-In Toolkit VST Binaural Audio Plugin. In Audio Engineering Society Conference: 2019 AES International Conference on Immersive and Interactive Audio. Audio Engineering Society.
6+
7+
More information about the 3D Tune-In Toolkit can be found in the open-source GitHub repository at https://github.com/3DTune-In/3dti_AudioToolkit/. Technical details about the 3D Tune-In Toolkit spatialiser are described in:
8+
9+
Cuevas-Rodríguez M, Picinali L, González-Toledo D, Garre C, de la Rubia-Cuestas E, Molina-Tanco L and Reyes-Lecuona A. (2019) 3D Tune-In Toolkit: An open-source library for real-time binaural spatialisation. PLOS ONE 14(3): e0211899. https://doi.org/10.1371/journal.pone.0211899
10+
11+
More information about the 3D Tune-In project can be found at http://3d-tune-in.eu/.
12+
13+
HRTF files are extracted from the IRCAM LISTEN databased and processed to remove ITDs.
14+
BRIR files were created within the 3D Tune-In project.
15+
16+
17+
Copyright and License
18+
19+
The 3D Tune-In Toolkit VST plugin, Copyright (c) 2019 Imperial College London and University of Malaga, is distributed as open source under GPLv3.
20+
21+
You may use this program to generate 3D sounds without additional restrictions to those imposed by the license of the original audio. You are not compelled to make any mention to this software or the 3D Tune-In project when using or distributing these audio files, but we would highly appreciate if you could kindly acknowledge the use of the 3D Tune-In Toolkit.
22+
23+
24+
Acknowledgements
25+
26+
This project has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreements No 644051 and 726765.
27+
We would also like to acknowledge Angel Rodríguez-Rivero for his help in testing the first release of this software.
28+
29+
30+
Contact
31+
32+
Lorenzo Picinali (l.picinali@imperial.ac.uk) and Arcadio Reyes-Lecuona (areyes@uma.es).

Resources/Images/3DTI_Logo.png

12.4 KB
Loading

Resources/Images/Imperial_Logo.png

9.15 KB
Loading

Resources/Images/UMA_Logo.png

14.2 KB
Loading

Source/AnechoicControls.cpp

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/**
2+
* \class AnechoicControls
3+
*
4+
* \brief Declaration of AnechoicControls interface.
5+
* \date June 2019
6+
*
7+
* \authors Reactify Music LLP: R. Hrafnkelsson ||
8+
* Coordinated by , A. Reyes-Lecuona (University of Malaga) and L.Picinali (Imperial College London) ||
9+
* \b Contact: areyes@uma.es and l.picinali@imperial.ac.uk
10+
*
11+
* \b Project: 3DTI (3D-games for TUNing and lEarnINg about hearing aids) ||
12+
* \b Website: http://3d-tune-in.eu/
13+
*
14+
* \b Copyright: University of Malaga and Imperial College London - 2019
15+
*
16+
* \b Licence: This copy of the 3D Tune-In Toolkit Plugin is licensed to you under the terms described in the LICENSE.md file included in this distribution.
17+
*
18+
* \b Acknowledgement: This project has received funding from the European Union's Horizon 2020 research and innovation programme under grant agreements No 644051 and 726765.
19+
*/
20+
21+
#include "AnechoicControls.h"
22+
23+
AnechoicControls::AnechoicControls(Toolkit3dtiPluginAudioProcessor& processor)
24+
: mProcessor(processor),
25+
mCore(processor.getCore()),
26+
distanceAttenuationLabel("Distance Label", "dB attenuation per double distance")
27+
{
28+
for ( int i = 0; i < BundledHRTFs.size(); i++ ) {
29+
hrtfMenu.addItem( BundledHRTFs[i], i+1 ); // IDs must be non-zero
30+
}
31+
hrtfMenu.onChange = [this] { hrtfMenuChanged(); };
32+
hrtfMenu.setSelectedItemIndex(0, dontSendNotification);
33+
addAndMakeVisible( hrtfMenu );
34+
35+
headCircumferenceToggle.setButtonText( "Custom Head Circumference" );
36+
headCircumferenceToggle.onClick = [this] { updateHeadCircumference(); };
37+
addAndMakeVisible(headCircumferenceToggle);
38+
39+
mapParameterToSlider( headCircumferenceSlider, mCore.headCircumference );
40+
headCircumferenceSlider.setTextValueSuffix(" mm");
41+
headCircumferenceSlider.setTextBoxStyle( Slider::TextBoxRight, false, 65, 24 );
42+
headCircumferenceSlider.addListener( this );
43+
headCircumferenceSlider.setValue( mCore.headCircumference, dontSendNotification );
44+
addAndMakeVisible( headCircumferenceSlider );
45+
46+
headCircumferenceSlider.setEnabled( headCircumferenceToggle.getToggleState() );
47+
48+
bypassToggle.setButtonText("On/Off");
49+
bypassToggle.setToggleState(true, dontSendNotification);
50+
bypassToggle.onClick = [this] { updateBypass(); };
51+
addAndMakeVisible( bypassToggle );
52+
53+
nearFieldToggle.setButtonText( "Near field correction (IIR)" );
54+
nearFieldToggle.onClick = [this] { updateNearFieldCorrection(); };
55+
addAndMakeVisible( nearFieldToggle );
56+
57+
farFieldToggle.setButtonText( "Far field correction (IIR)" );
58+
farFieldToggle.onClick = [this] { updateFarFieldCorrection(); };
59+
addAndMakeVisible( farFieldToggle );
60+
61+
distanceAttenuationToggle.setButtonText("On/Off");
62+
distanceAttenuationToggle.setToggleState(true, dontSendNotification);
63+
distanceAttenuationToggle.onClick = [this] { updateDistanceAttenuation(); };
64+
addAndMakeVisible( distanceAttenuationToggle );
65+
66+
qualityToggle.setButtonText( "High Quality" );
67+
qualityToggle.onClick = [this] { updateQualitySetting(); };
68+
// addAndMakeVisible( qualityToggle );
69+
70+
setLabelStyle( distanceAttenuationLabel );
71+
distanceAttenuationLabel.setJustificationType( Justification::left );
72+
addAndMakeVisible( distanceAttenuationLabel );
73+
74+
mapParameterToSlider( distanceAttenuationSlider, mCore.sourceDistanceAttenuation );
75+
distanceAttenuationSlider.setTextValueSuffix(" dB");
76+
distanceAttenuationSlider.setTextBoxStyle( Slider::TextBoxRight, false, 65, 24 );
77+
distanceAttenuationSlider.addListener( this );
78+
addAndMakeVisible( distanceAttenuationSlider );
79+
80+
updateGui();
81+
}
82+
83+
void AnechoicControls::updateGui() {
84+
headCircumferenceToggle.setToggleState( mCore.enableCustomizedITD, dontSendNotification );
85+
headCircumferenceSlider.setValue( mCore.headCircumference, dontSendNotification );
86+
headCircumferenceSlider.setEnabled( headCircumferenceToggle.getToggleState() );
87+
88+
if ( !mCore.getSources().empty() ) {
89+
auto source = mCore.getSources().front();
90+
bypassToggle.setToggleState(source->IsAnechoicProcessEnabled(), dontSendNotification);
91+
92+
bool distanceAttenuationEnabled = source->IsDistanceAttenuationEnabledAnechoic();
93+
distanceAttenuationToggle.setToggleState(distanceAttenuationEnabled, dontSendNotification);
94+
distanceAttenuationSlider.setValue(mCore.sourceDistanceAttenuation, dontSendNotification);
95+
distanceAttenuationLabel.setEnabled(distanceAttenuationEnabled);
96+
distanceAttenuationSlider.setEnabled(distanceAttenuationEnabled);
97+
}
98+
99+
nearFieldToggle.setToggleState( mCore.enableNearDistanceEffect, dontSendNotification);
100+
farFieldToggle.setToggleState( mCore.enableFarDistanceEffect, dontSendNotification);
101+
qualityToggle.setToggleState( mCore.spatializationMode, dontSendNotification);
102+
103+
auto hrtfIndex = mCore.getHrtfIndex();
104+
if ( hrtfIndex != hrtfMenu.getSelectedItemIndex() && hrtfIndex < BundledHRTFs.size()-2 ) { // Show filename if custom file is selected
105+
hrtfMenu.setSelectedItemIndex(hrtfIndex, dontSendNotification);
106+
}
107+
}
108+
109+
void AnechoicControls::resized() {
110+
auto area = getLocalBounds();
111+
bypassToggle.setBounds( 10, 4, 80, 24 );
112+
hrtfMenu.setBounds( 12, 40, area.getWidth()-24, 22 );
113+
headCircumferenceToggle.setBounds( 10, hrtfMenu.getBottom() + 8, area.getWidth()-20, 26);
114+
headCircumferenceSlider.setBounds( 6, headCircumferenceToggle.getBottom(), area.getWidth()-18, 24);
115+
nearFieldToggle.setBounds(10, headCircumferenceSlider.getBottom(), area.getWidth()-20, 32);
116+
farFieldToggle.setBounds(10, nearFieldToggle.getBottom(), area.getWidth()-20, 32);
117+
// qualityToggle.setBounds(10, farFieldToggle.getBottom(), area.getWidth()-20, 30);
118+
distanceAttenuationToggle.setBounds( 10, farFieldToggle.getBottom() + 4, 80, 24);
119+
distanceAttenuationLabel.setBounds( 94, distanceAttenuationToggle.getY(), area.getWidth()-100, 24);
120+
distanceAttenuationSlider.setBounds( 6, distanceAttenuationToggle.getBottom() + 4, area.getWidth()-20, 24);
121+
}
122+
123+
void AnechoicControls::updateBypass() {
124+
bool enabled = bypassToggle.getToggleState();
125+
if ( enabled ) {
126+
mCore.getSources().front()->EnableAnechoicProcess();
127+
} else {
128+
mCore.getSources().front()->DisableAnechoicProcess();
129+
}
130+
setAlpha( enabled + 0.4f );
131+
}
132+
133+
void AnechoicControls::hrtfMenuChanged() {
134+
auto text = hrtfMenu.getText();
135+
// Note(Ragnar): Windows FileChooser will only accept
136+
// one filetype at at time se we provide separate options
137+
if ( text == "Load 3DTI" ) {
138+
loadCustomHrtf("*.3dti-hrtf");
139+
} else if ( text == "Load SOFA" ) {
140+
loadCustomHrtf("*.sofa");
141+
} else {
142+
mCore.loadHRTF(hrtfMenu.getSelectedItemIndex());
143+
}
144+
}
145+
146+
void AnechoicControls::loadCustomHrtf(String fileTypes) {
147+
fc.reset (new FileChooser ("Choose a file to open...",
148+
HRTFDirectory(),
149+
fileTypes,
150+
true));
151+
152+
fc->launchAsync(FileBrowserComponent::openMode | FileBrowserComponent::canSelectFiles,
153+
[this] (const FileChooser& chooser)
154+
{
155+
String chosen;
156+
auto results = chooser.getURLResults();
157+
158+
auto result = results.getFirst();
159+
160+
chosen << (result.isLocalFile() ? result.getLocalFile().getFullPathName()
161+
: result.toString (false));
162+
163+
if ( mCore.loadHRTF(File(chosen.removeCharacters("\n"))) ) {
164+
updateHrtfLabelText();
165+
};
166+
});
167+
}
168+
169+
void AnechoicControls::updateHeadCircumference() {
170+
bool enabled = headCircumferenceToggle.getToggleState();
171+
mCore.enableCustomizedITD = enabled;
172+
mCore.headCircumference = headCircumferenceSlider.getValue();
173+
174+
// TODO: Show circumference in mm
175+
// IM.slHeadCircumference.footer = "mm (r: " + Utils.FloatToString(r_cm, 1) + " cm)";
176+
headCircumferenceSlider.setEnabled(enabled);
177+
}
178+
179+
void AnechoicControls::updateHrtfLabelText() {
180+
auto hrtf = mCore.getHrtfPath().getFileNameWithoutExtension().upToLastOccurrenceOf("_", false, false);;
181+
hrtfMenu.setText(hrtf, dontSendNotification);
182+
}
183+
184+
void AnechoicControls::updateNearFieldCorrection() {
185+
mCore.enableNearDistanceEffect = nearFieldToggle.getToggleState();
186+
}
187+
188+
void AnechoicControls::updateFarFieldCorrection() {
189+
mCore.enableFarDistanceEffect = farFieldToggle.getToggleState();
190+
}
191+
192+
void AnechoicControls::updateQualitySetting() {
193+
auto mode = qualityToggle.getToggleState() ? Binaural::HighQuality : Binaural::HighPerformance;
194+
mCore.spatializationMode = mode;
195+
}
196+
197+
void AnechoicControls::updateDistanceAttenuation() {
198+
auto source = mCore.getSources().front();
199+
if ( distanceAttenuationToggle.getToggleState() ) {
200+
source->EnableDistanceAttenuationAnechoic();
201+
} else {
202+
source->DisableDistanceAttenuationAnechoic();
203+
}
204+
}

Source/AnechoicControls.h

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* \class AnechoicControls
3+
*
4+
* \brief Declaration of AnechoicControls interface.
5+
* \date June 2019
6+
*
7+
* \authors Reactify Music LLP: R. Hrafnkelsson ||
8+
* Coordinated by , A. Reyes-Lecuona (University of Malaga) and L.Picinali (Imperial College London) ||
9+
* \b Contact: areyes@uma.es and l.picinali@imperial.ac.uk
10+
*
11+
* \b Project: 3DTI (3D-games for TUNing and lEarnINg about hearing aids) ||
12+
* \b Website: http://3d-tune-in.eu/
13+
*
14+
* \b Copyright: University of Malaga and Imperial College London - 2019
15+
*
16+
* \b Licence: This copy of the 3D Tune-In Toolkit Plugin is licensed to you under the terms described in the LICENSE.md file included in this distribution.
17+
*
18+
* \b Acknowledgement: This project has received funding from the European Union's Horizon 2020 research and innovation programme under grant agreements No 644051 and 726765.
19+
*/
20+
21+
#pragma once
22+
23+
#include "../JuceLibraryCode/JuceHeader.h"
24+
#include "PluginProcessor.h"
25+
#include "Utils.h"
26+
27+
//==============================================================================
28+
/*
29+
*/
30+
class AnechoicControls : public Component, public Slider::Listener
31+
{
32+
public:
33+
AnechoicControls(Toolkit3dtiPluginAudioProcessor& processor);
34+
35+
~AnechoicControls() {}
36+
37+
void updateGui();
38+
39+
void paint (Graphics& g) override {
40+
g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId)); // clear the background
41+
g.setColour (Colours::grey);
42+
g.drawRect (getLocalBounds(), 1);
43+
g.setColour(Colours::white);
44+
g.setFont(18.0f);
45+
g.drawText("Anechoic Path", getLocalBounds().withTrimmedBottom( getLocalBounds().getHeight() - 32 ),
46+
Justification::centred, true);
47+
}
48+
49+
void resized() override;
50+
51+
void sliderValueChanged(Slider* slider) override {
52+
if ( slider == &headCircumferenceSlider ) {
53+
updateHeadCircumference();
54+
} else {
55+
mCore.sourceDistanceAttenuation = (float)slider->getValue();
56+
}
57+
}
58+
59+
ToggleButton bypassToggle;
60+
61+
private:
62+
63+
void hrtfMenuChanged();
64+
void loadCustomHrtf(String fileTypes);
65+
void updateBypass();
66+
void updateHeadCircumference();
67+
void updateHrtfLabelText();
68+
void updateNearFieldCorrection();
69+
void updateFarFieldCorrection();
70+
void updateQualitySetting();
71+
void updateDistanceAttenuation();
72+
73+
Toolkit3dtiPluginAudioProcessor& mProcessor;
74+
Toolkit3dtiProcessor& mCore;
75+
76+
ComboBox hrtfMenu;
77+
ToggleButton headCircumferenceToggle;
78+
Slider headCircumferenceSlider;
79+
std::unique_ptr<FileChooser> fc;
80+
81+
ToggleButton nearFieldToggle;
82+
ToggleButton farFieldToggle;
83+
ToggleButton qualityToggle;
84+
ToggleButton distanceAttenuationToggle;
85+
Label distanceAttenuationLabel;
86+
Slider distanceAttenuationSlider;
87+
88+
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnechoicControls)
89+
};

Source/ElevationDial.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* \class ElevationDial
3+
*
4+
* \brief Declaration of ElevationDial interface.
5+
* \date June 2019
6+
*
7+
* \authors Reactify Music LLP: R. Hrafnkelsson ||
8+
* Coordinated by , A. Reyes-Lecuona (University of Malaga) and L.Picinali (Imperial College London) ||
9+
* \b Contact: areyes@uma.es and l.picinali@imperial.ac.uk
10+
*
11+
* \b Project: 3DTI (3D-games for TUNing and lEarnINg about hearing aids) ||
12+
* \b Website: http://3d-tune-in.eu/
13+
*
14+
* \b Copyright: University of Malaga and Imperial College London - 2019
15+
*
16+
* \b Licence: This copy of the 3D Tune-In Toolkit Plugin is licensed to you under the terms described in the LICENSE.md file included in this distribution.
17+
*
18+
* \b Acknowledgement: This project has received funding from the European Union's Horizon 2020 research and innovation programme under grant agreements No 644051 and 726765.
19+
*/
20+
21+
#pragma once
22+
23+
#include "../JuceLibraryCode/JuceHeader.h"
24+
25+
//==============================================================================
26+
/*
27+
*/
28+
29+
class ElevationDial : public Slider {
30+
public:
31+
32+
// TODO(Ragnar): Better implementation of this
33+
bool hitTest (int x, int y) override {
34+
// const int thumbHeight = getLookAndFeel().getSliderThumbRadius(*this);
35+
const int thumbCentre = valueToProportionOfLength (getValue()) * getHeight();
36+
// DBG("Thumb centre: " + String(thumbCentre));
37+
// return (std::abs(y - thumbCentre) < thumbHeight);
38+
bool isAtEdges = (thumbCentre < 25 || thumbCentre > 95);
39+
int cutoff = isAtEdges ? 50 : 65;
40+
return x > cutoff;
41+
}
42+
43+
};

0 commit comments

Comments
 (0)