Skip to content

Commit

Permalink
Act as ODDSound MTS Main ('Master') (surge-synthesizer#6771)
Browse files Browse the repository at this point in the history
This allows you to have a single surge instance act as an
oddsound MTS-ESP Master (which we call Main) component.
In this mode, the tunign editor features stay active but
are broadcast to all other MTS-ESP clients on your system
if the master is initializable.
  • Loading branch information
baconpaul authored Jan 8, 2023
1 parent 09e61ca commit 2039036
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 76 deletions.
3 changes: 2 additions & 1 deletion libs/oddsound-mts/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ project(oddsound-mts VERSION 0.0.0 LANGUAGES CXX)

add_library(${PROJECT_NAME}
MTS-ESP/Client/libMTSClient.cpp
MTS-ESP/Master/libMTSMaster.cpp
)

target_include_directories(${PROJECT_NAME} PUBLIC MTS-ESP/Client)
target_include_directories(${PROJECT_NAME} PUBLIC MTS-ESP/Client MTS-ESP/Master)
target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_DL_LIBS})
add_library(surge::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
24 changes: 23 additions & 1 deletion src/common/SurgePatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1800,6 +1800,23 @@ void SurgePatch::load_xml(const void *data, int datasize, bool is_preset)
}
}

auto mts_main =
TINYXML_SAFE_TO_ELEMENT(nonparamconfig->FirstChild("oddsound_mts_active_as_main"));
if (mts_main)
{
int tv;

if (tam->QueryIntAttribute("v", &tv) == TIXML_SUCCESS)
{
if (tv)
{
#ifndef SURGE_SKIP_ODDSOUND_MTS
storage->connect_as_oddsound_main();
#endif
}
}
}

auto *hcs = TINYXML_SAFE_TO_ELEMENT(nonparamconfig->FirstChild("hardclipmodes"));

if (hcs)
Expand Down Expand Up @@ -3046,7 +3063,7 @@ unsigned int SurgePatch::save_xml(void **data) // allocates mem, must be freed b

// Revision 16 adds the TAM
TiXmlElement tam("tuningApplicationMode");
if (storage->oddsound_mts_active)
if (storage->oddsound_mts_active_as_client)
{
tam.SetAttribute("v", (int)(storage->patchStoredTuningApplicationMode));
}
Expand All @@ -3056,6 +3073,11 @@ unsigned int SurgePatch::save_xml(void **data) // allocates mem, must be freed b
}
nonparamconfig.InsertEndChild(tam);

// Revision 21 adds MTS as main
TiXmlElement oam("oddsound_mts_active_as_main");
oam.SetAttribute("v", (int)(storage->oddsound_mts_active_as_main));
nonparamconfig.InsertEndChild(oam);

patch.InsertEndChild(nonparamconfig);

TiXmlElement eod("extraoscdata");
Expand Down
49 changes: 45 additions & 4 deletions src/common/SurgeStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "sst/plugininfra/strnatcmp.h"
#ifndef SURGE_SKIP_ODDSOUND_MTS
#include "libMTSClient.h"
#include "libMTSMaster.h"
#endif
#include "FxPresetAndClipboardManager.h"
#include "ModulatorPresetManager.h"
Expand Down Expand Up @@ -522,7 +523,7 @@ SurgeStorage::SurgeStorage(const SurgeStorage::SurgeStorageConfig &config) : oth
else
{
oddsound_mts_client = nullptr;
oddsound_mts_active = false;
oddsound_mts_active_as_client = false;
}
#endif

Expand Down Expand Up @@ -1995,6 +1996,9 @@ void SurgeStorage::load_midi_controllers()
SurgeStorage::~SurgeStorage()
{
#ifndef SURGE_SKIP_ODDSOUND_MTS
if (oddsound_mts_active_as_main)
disconnect_as_oddsound_main();

deinitialize_oddsound();
#endif
}
Expand Down Expand Up @@ -2261,6 +2265,7 @@ bool SurgeStorage::resetToCurrentScaleAndMapping()
table_note_omega[1][i] =
(float)cos(2 * M_PI * min(0.5, 440 * table_pitch[i] * dsamplerate_os_inv));
}
tuningUpdates++;
return true;
}

Expand All @@ -2269,7 +2274,7 @@ void SurgeStorage::setTuningApplicationMode(const TuningApplicationMode m)
tuningApplicationMode = m;
patchStoredTuningApplicationMode = m;
resetToCurrentScaleAndMapping();
if (oddsound_mts_active)
if (oddsound_mts_active_as_client)
{
tuningApplicationMode = RETUNE_MIDI_ONLY;
}
Expand Down Expand Up @@ -2449,8 +2454,8 @@ void SurgeStorage::deinitialize_oddsound()

void SurgeStorage::setOddsoundMTSActiveTo(bool b)
{
bool poa = oddsound_mts_active;
oddsound_mts_active = b;
bool poa = oddsound_mts_active_as_client;
oddsound_mts_active_as_client = b;
if (b && b != poa)
{
// Oddsound right now is MIDI_ONLY so force that to avoid lingering problems
Expand All @@ -2461,6 +2466,42 @@ void SurgeStorage::setOddsoundMTSActiveTo(bool b)
tuningApplicationMode = patchStoredTuningApplicationMode;
}
}

void SurgeStorage::connect_as_oddsound_main()
{
if (oddsound_mts_client)
{
deinitialize_oddsound();
}
if (oddsound_mts_active_as_main) // should never happen
{
MTS_DeregisterMaster();
}
oddsound_mts_active_as_main = true;
MTS_RegisterMaster();
lastSentTuningUpdate = -1;
}
void SurgeStorage::disconnect_as_oddsound_main()
{
oddsound_mts_active_as_main = false;
MTS_DeregisterMaster();
initialize_oddsound();
}
void SurgeStorage::send_tuning_update()
{
if (lastSentTuningUpdate == tuningUpdates)
return;

lastSentTuningUpdate = tuningUpdates;
if (!oddsound_mts_active_as_main)
return;

for (int i = 0; i < 128; ++i)
{
MTS_SetNoteTuning(currentTuning.frequencyForMidiNote(i), i);
}
MTS_SetScaleName(currentTuning.scale.description.c_str());
}
#endif

void SurgeStorage::toggleTuningToCache()
Expand Down
16 changes: 12 additions & 4 deletions src/common/SurgeStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ const int FIRoffsetI16 = FIRipolI16_N >> 1;
// added Extend to Delay Feedback parameter (allows negative delay)
// 19 -> 20 (XT 1.1 release) added voice envelope mode, but super late so don't break 19
// 20 -> 21 (XT 1.2 nightlies) added absolutable mode for Combulator Offset 1/2 (to match the behavior of Center parameter)
// oddsound_as_mts_main
// clang-format on

const int ff_revision = 21;
Expand Down Expand Up @@ -1304,6 +1305,7 @@ class alignas(16) SurgeStorage
bool isStandardTuningAndHasNoToggle();
void resetTuningToggle();

std::atomic<uint64_t> tuningUpdates{2}; // the 'last sent' starts at 0. just a different value
bool retuneToScale(const Tunings::Scale &s)
{
currentScale = s;
Expand Down Expand Up @@ -1393,10 +1395,16 @@ class alignas(16) SurgeStorage
void initialize_oddsound();
void deinitialize_oddsound();
void setOddsoundMTSActiveTo(bool b);

void connect_as_oddsound_main();
void disconnect_as_oddsound_main();
uint64_t lastSentTuningUpdate{0}; // since tuning udpate starts at 2
void send_tuning_update();
#endif
MTSClient *oddsound_mts_client = nullptr;
std::atomic<bool> oddsound_mts_active{false};
std::atomic<bool> oddsound_mts_active_as_client{false};
uint32_t oddsound_mts_on_check = 0;
std::atomic<bool> oddsound_mts_active_as_main{false};
enum OddsoundRetuneMode
{
RETUNE_CONSTANT = 0,
Expand All @@ -1409,9 +1417,9 @@ class alignas(16) SurgeStorage
*/
inline bool tuningTableIs12TET()
{
if ((isStandardTuning) || // nothing changed
(oddsound_mts_client && oddsound_mts_active) || // MTS in command
tuningApplicationMode == RETUNE_MIDI_ONLY // tune the keyboard, not the tables
if ((isStandardTuning) || // nothing changed
(oddsound_mts_client && oddsound_mts_active_as_client) || // MTS in command
tuningApplicationMode == RETUNE_MIDI_ONLY // tune the keyboard, not the tables
)
return true;
return false;
Expand Down
6 changes: 3 additions & 3 deletions src/common/SurgeSynthesizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ void SurgeSynthesizer::playNote(char channel, char key, char velocity, char detu
}

#ifndef SURGE_SKIP_ODDSOUND_MTS
if (storage.oddsound_mts_client && storage.oddsound_mts_active)
if (storage.oddsound_mts_client && storage.oddsound_mts_active_as_client)
{
if (MTS_ShouldFilterNote(storage.oddsound_mts_client, key, channel))
{
Expand Down Expand Up @@ -4104,10 +4104,10 @@ void SurgeSynthesizer::processControl()
storage.oddsound_mts_on_check = (storage.oddsound_mts_on_check + 1) & (1024 - 1);
if (storage.oddsound_mts_on_check == 0)
{
bool prior = storage.oddsound_mts_active;
bool prior = storage.oddsound_mts_active_as_client;
storage.setOddsoundMTSActiveTo(MTS_HasMaster(storage.oddsound_mts_client));

if (prior != storage.oddsound_mts_active)
if (prior != storage.oddsound_mts_active_as_client)
{
refresh_editor = true;
}
Expand Down
10 changes: 5 additions & 5 deletions src/common/dsp/SurgeVoice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ float SurgeVoiceState::getPitch(SurgeStorage *storage)
auto res = key + /* mainChannelState->pitchBendInSemitones + */ mpeBend + detune;

#ifndef SURGE_SKIP_ODDSOUND_MTS
if (storage->oddsound_mts_client && storage->oddsound_mts_active)
if (storage->oddsound_mts_client && storage->oddsound_mts_active_as_client)
{
if (storage->oddsoundRetuneMode == SurgeStorage::RETUNE_CONSTANT ||
key != keyRetuningForKey)
Expand Down Expand Up @@ -80,7 +80,7 @@ float SurgeVoice::channelKeyEquvialent(float key, int channel, bool isMpeEnabled
SurgeStorage *storage, bool remapKeyForTuning)
{
float res = key;
if (storage->mapChannelToOctave && !storage->oddsound_mts_active && !isMpeEnabled)
if (storage->mapChannelToOctave && !storage->oddsound_mts_active_as_client && !isMpeEnabled)
{
if (remapKeyForTuning)
{
Expand Down Expand Up @@ -390,7 +390,7 @@ void SurgeVoice::legato(int key, int velocity, char detune)

void SurgeVoice::retriggerPortaIfKeyChanged()
{
if (!storage->oddsound_mts_active &&
if (!storage->oddsound_mts_active_as_client &&
(storage->isStandardTuning || storage->tuningApplicationMode == SurgeStorage::RETUNE_ALL))
{
if (floor(state.pkey + 0.5) != state.priorpkey)
Expand All @@ -406,7 +406,7 @@ void SurgeVoice::retriggerPortaIfKeyChanged()
};

#ifndef SURGE_SKIP_ODDSOUND_MTS
if (storage->oddsound_mts_client && storage->oddsound_mts_active)
if (storage->oddsound_mts_client && storage->oddsound_mts_active_as_client)
{
v4k = [this](int k) {
return log2f(MTS_NoteToFrequency(storage->oddsound_mts_client, k, state.channel) /
Expand Down Expand Up @@ -1485,7 +1485,7 @@ void SurgeVoice::resetPortamentoFrom(int key, int channel)
{
float lk = key;
#ifndef SURGE_SKIP_ODDSOUND_MTS
if (storage->oddsound_mts_client && storage->oddsound_mts_active)
if (storage->oddsound_mts_client && storage->oddsound_mts_active_as_client)
{
lk += MTS_RetuningInSemitones(storage->oddsound_mts_client, lk, channel);
state.portasrc_key = lk;
Expand Down
2 changes: 1 addition & 1 deletion src/common/dsp/oscillators/TwistOscillator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ TwistOscillator::TwistOscillator(SurgeStorage *storage, OscillatorStorage *oscda
float TwistOscillator::tuningAwarePitch(float pitch)
{
if (storage->tuningApplicationMode == SurgeStorage::RETUNE_ALL &&
!(storage->oddsound_mts_client && storage->oddsound_mts_active) &&
!(storage->oddsound_mts_client && storage->oddsound_mts_active_as_client) &&
!(storage->isStandardTuning))
{
auto idx = (int)floor(pitch);
Expand Down
Loading

0 comments on commit 2039036

Please sign in to comment.