Skip to content

Commit

Permalink
Throttle engine -> serial -> ui macro update messages (#1118)
Browse files Browse the repository at this point in the history
* Throttle engine -> serial -> ui macro update messages

bitwig can set a macro every 64 samples.
A ui can show a knob at around 120hz
so we should compress those messages, which we do here in the
serializatoin thread.

Closes #1115

* also 1b for knob rings
  • Loading branch information
baconpaul authored Aug 15, 2024
1 parent 48a51ea commit a74ad9d
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src-ui/components/SCXTEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ void SCXTEditor::drainCallbackQueue()
#if BUILD_IS_DEBUG
inboundMessageCount++;
inboundMessageBytes += queueMsg.size();
if (inboundMessageCount % 100 == 0)
if (inboundMessageCount % 500 == 0)
{
SCLOG("Serial -> Client Message Count: "
<< inboundMessageCount << " size: " << inboundMessageBytes
Expand Down
2 changes: 1 addition & 1 deletion src-ui/theme/ThemeApplier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ void applyColors(const sheet_t::ptr_t &base, const ColorMap &cols)
base->setColour(PushButton::styleClass, PushButton::fill_pressed,
cols.getHover(ColorMap::bg_1));

base->setColour(ValueBearing::styleClass, ValueBearing::value, cols.get(ColorMap::accent_1a));
base->setColour(ValueBearing::styleClass, ValueBearing::value, cols.get(ColorMap::accent_1b));
base->setColour(ValueBearing::styleClass, ValueBearing::value_hover,
cols.getHover(ColorMap::accent_1a));
base->setColour(ValueBearing::styleClass, ValueBearing::valuelabel,
Expand Down
35 changes: 31 additions & 4 deletions src/messaging/messaging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,8 @@ void MessageController::parseAudioMessageOnSerializationThread(
int16_t pt = as.payload.i[0];
int16_t idx = as.payload.i[1];

serializationSendToClient(client::s2c_update_macro_value,
messaging::client::macroValue_t{
pt, idx, engine.getPatch()->getPart(pt)->macros[idx].value},
*this);
macroSetValueCompressorUsed = true;
macroSetValueCompressor[pt][idx] = true;
}
break;
case audio::a2s_processor_refresh:
Expand Down Expand Up @@ -214,6 +212,7 @@ void MessageController::runSerialization()

// TODO: Drain SerToAudioQ if there's no audio thread
bool tryToDrain{true};
prepareSerializationThreadForAudioQueueDrain();
while (tryToDrain && !audioToSerializationQueue.empty())
{
auto msgopt = audioToSerializationQueue.pop();
Expand All @@ -225,6 +224,7 @@ void MessageController::runSerialization()
else
tryToDrain = false;
}
serializationThreadPostAudioQueueDrain();
}
else
{
Expand Down Expand Up @@ -321,4 +321,31 @@ void MessageController::reportErrorToClient(const std::string &title, const std:
*(this));
}

void MessageController::prepareSerializationThreadForAudioQueueDrain()
{
assert(!macroSetValueCompressorUsed);
}
void MessageController::serializationThreadPostAudioQueueDrain()
{
if (macroSetValueCompressorUsed)
{
for (int pt = 0; pt < numParts; ++pt)
{
for (int idx = 0; idx < macrosPerPart; ++idx)
{
if (macroSetValueCompressor[pt][idx])
{
serializationSendToClient(
client::s2c_update_macro_value,
messaging::client::macroValue_t{
pt, idx, engine.getPatch()->getPart(pt)->macros[idx].value},
*this);
macroSetValueCompressor[pt][idx] = false;
}
}
}

macroSetValueCompressorUsed = false;
}
}
} // namespace scxt::messaging
11 changes: 10 additions & 1 deletion src/messaging/messaging.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ struct MessageController : MoveableOnly<MessageController>
{
serializationToAudioQueue.subscribe();
audioToSerializationQueue.subscribe();

for (auto &ma : macroSetValueCompressor)
for (auto &m : ma)
m = false;
}
~MessageController();

Expand Down Expand Up @@ -326,14 +330,19 @@ struct MessageController : MoveableOnly<MessageController>
uint64_t inboundClientMessageCount{0};
void runSerialization();
void parseAudioMessageOnSerializationThread(const audio::AudioToSerialization &as);
void prepareSerializationThreadForAudioQueueDrain();
void serializationThreadPostAudioQueueDrain();
bool macroSetValueCompressorUsed{false};
std::array<std::array<bool, scxt::macrosPerPart>, scxt::numParts> macroSetValueCompressor{};

// serialization thread only please
AudioThreadCallback *getAudioThreadCallback();
void returnAudioThreadCallback(AudioThreadCallback *);
std::stack<AudioThreadCallback *> cbStore;

sst::cpputils::SimpleRingBuffer<serializationToAudioMessage_t, 1024> serializationToAudioQueue;
sst::cpputils::SimpleRingBuffer<audioToSerializationMessage_t, 1024> audioToSerializationQueue;
sst::cpputils::SimpleRingBuffer<audioToSerializationMessage_t, 1024 * 16>
audioToSerializationQueue;

public:
// Some engine events are passed onto the hosting processor. This
Expand Down

0 comments on commit a74ad9d

Please sign in to comment.