commit
6dbdd1bb14
6 changed files with 105 additions and 4 deletions
|
|
@ -165,6 +165,7 @@ struct Editor::Impl : EditorController::Receiver, IControlListener {
|
||||||
void updateStretchedTuningLabel(float stretchedTuning);
|
void updateStretchedTuningLabel(float stretchedTuning);
|
||||||
|
|
||||||
void updateKeyUsed(unsigned key, bool used);
|
void updateKeyUsed(unsigned key, bool used);
|
||||||
|
void updateKeyswitchUsed(unsigned key, bool used);
|
||||||
void updateCCUsed(unsigned cc, bool used);
|
void updateCCUsed(unsigned cc, bool used);
|
||||||
void updateCCValue(unsigned cc, float value);
|
void updateCCValue(unsigned cc, float value);
|
||||||
void updateCCDefaultValue(unsigned cc, float value);
|
void updateCCDefaultValue(unsigned cc, float value);
|
||||||
|
|
@ -223,6 +224,7 @@ void Editor::open(CFrame& frame)
|
||||||
|
|
||||||
// request the whole Key and CC information
|
// request the whole Key and CC information
|
||||||
impl.sendQueuedOSC("/key/slots", "", nullptr);
|
impl.sendQueuedOSC("/key/slots", "", nullptr);
|
||||||
|
impl.sendQueuedOSC("/sw/slots", "", nullptr);
|
||||||
impl.sendQueuedOSC("/cc/slots", "", nullptr);
|
impl.sendQueuedOSC("/cc/slots", "", nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -249,6 +251,7 @@ void Editor::Impl::uiReceiveValue(EditId id, const EditValue& v)
|
||||||
|
|
||||||
// request the whole Key and CC information
|
// request the whole Key and CC information
|
||||||
sendQueuedOSC("/key/slots", "", nullptr);
|
sendQueuedOSC("/key/slots", "", nullptr);
|
||||||
|
sendQueuedOSC("/sw/slots", "", nullptr);
|
||||||
sendQueuedOSC("/cc/slots", "", nullptr);
|
sendQueuedOSC("/cc/slots", "", nullptr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -410,6 +413,14 @@ void Editor::Impl::uiReceiveMessage(const char* path, const char* sig, const sfi
|
||||||
updateKeyUsed(key, used);
|
updateKeyUsed(key, used);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (Messages::matchOSC("/sw/slots", path, indices) && !strcmp(sig, "b")) {
|
||||||
|
size_t numBits = 8 * args[0].b->size;
|
||||||
|
ConstBitSpan bits { args[0].b->data, numBits };
|
||||||
|
for (unsigned key = 0; key < 128; ++key) {
|
||||||
|
bool used = key < numBits && bits.test(key);
|
||||||
|
updateKeyswitchUsed(key, used);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (Messages::matchOSC("/cc/slots", path, indices) && !strcmp(sig, "b")) {
|
else if (Messages::matchOSC("/cc/slots", path, indices) && !strcmp(sig, "b")) {
|
||||||
size_t numBits = 8 * args[0].b->size;
|
size_t numBits = 8 * args[0].b->size;
|
||||||
ConstBitSpan bits { args[0].b->data, numBits };
|
ConstBitSpan bits { args[0].b->data, numBits };
|
||||||
|
|
@ -983,6 +994,7 @@ void Editor::Impl::changeSfzFile(const std::string& filePath)
|
||||||
|
|
||||||
// request the whole Key and CC information
|
// request the whole Key and CC information
|
||||||
sendQueuedOSC("/key/slots", "", nullptr);
|
sendQueuedOSC("/key/slots", "", nullptr);
|
||||||
|
sendQueuedOSC("/sw/slots", "", nullptr);
|
||||||
sendQueuedOSC("/cc/slots", "", nullptr);
|
sendQueuedOSC("/cc/slots", "", nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1294,6 +1306,12 @@ void Editor::Impl::updateKeyUsed(unsigned key, bool used)
|
||||||
piano->setKeyUsed(key, used);
|
piano->setKeyUsed(key, used);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Editor::Impl::updateKeyswitchUsed(unsigned key, bool used)
|
||||||
|
{
|
||||||
|
if (SPiano* piano = piano_)
|
||||||
|
piano->setKeyswitchUsed(key, used);
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::Impl::updateCCUsed(unsigned cc, bool used)
|
void Editor::Impl::updateCCUsed(unsigned cc, bool used)
|
||||||
{
|
{
|
||||||
if (SControlsPanel* panel = controlsPanel_)
|
if (SControlsPanel* panel = controlsPanel_)
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,18 @@ void SPiano::setKeyUsed(unsigned key, bool used)
|
||||||
invalid();
|
invalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SPiano::setKeyswitchUsed(unsigned key, bool used)
|
||||||
|
{
|
||||||
|
if (key >= 128)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (keyswitchUsed_.test(key) == used)
|
||||||
|
return;
|
||||||
|
|
||||||
|
keyswitchUsed_.set(key, used);
|
||||||
|
invalid();
|
||||||
|
}
|
||||||
|
|
||||||
void SPiano::setKeyValue(unsigned key, float value)
|
void SPiano::setKeyValue(unsigned key, float value)
|
||||||
{
|
{
|
||||||
if (key >= 128)
|
if (key >= 128)
|
||||||
|
|
@ -64,6 +76,19 @@ void SPiano::setKeyValue(unsigned key, float value)
|
||||||
invalid();
|
invalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPiano::KeyRole SPiano::getKeyRole(unsigned key)
|
||||||
|
{
|
||||||
|
if (key >= 128)
|
||||||
|
return KeyRole::Unused;
|
||||||
|
|
||||||
|
if (keyUsed_.test(key))
|
||||||
|
return KeyRole::Note;
|
||||||
|
if (keyswitchUsed_.test(key))
|
||||||
|
return KeyRole::Switch;
|
||||||
|
|
||||||
|
return KeyRole::Unused;
|
||||||
|
}
|
||||||
|
|
||||||
void SPiano::draw(CDrawContext* dc)
|
void SPiano::draw(CDrawContext* dc)
|
||||||
{
|
{
|
||||||
const Dimensions dim = getDimensions(false);
|
const Dimensions dim = getDimensions(false);
|
||||||
|
|
@ -85,12 +110,24 @@ void SPiano::draw(CDrawContext* dc)
|
||||||
if (!black[key % 12]) {
|
if (!black[key % 12]) {
|
||||||
CRect rect = keyRect(key);
|
CRect rect = keyRect(key);
|
||||||
|
|
||||||
SColorHCY hcy(keyUsedHue_, 1.0, whiteKeyLuma_);
|
SColorHCY hcy(0.0, 1.0, whiteKeyLuma_);
|
||||||
if (!keyUsed_[key] || allKeysUsed) {
|
|
||||||
|
switch (getKeyRole(key)) {
|
||||||
|
case KeyRole::Note:
|
||||||
|
if (allKeysUsed)
|
||||||
|
goto whiteKeyDefault;
|
||||||
|
hcy.h = keyUsedHue_;
|
||||||
|
break;
|
||||||
|
case KeyRole::Switch:
|
||||||
|
hcy.h = keySwitchHue_;
|
||||||
|
break;
|
||||||
|
default: whiteKeyDefault:
|
||||||
hcy.y = 1.0;
|
hcy.y = 1.0;
|
||||||
if (keyval_[key])
|
if (keyval_[key])
|
||||||
hcy.c = 0.0;
|
hcy.c = 0.0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyval_[key])
|
if (keyval_[key])
|
||||||
hcy.y = std::max(0.0f, hcy.y - keyLumaPressDelta_);
|
hcy.y = std::max(0.0f, hcy.y - keyLumaPressDelta_);
|
||||||
|
|
||||||
|
|
@ -113,9 +150,22 @@ void SPiano::draw(CDrawContext* dc)
|
||||||
if (black[key % 12]) {
|
if (black[key % 12]) {
|
||||||
CRect rect = keyRect(key);
|
CRect rect = keyRect(key);
|
||||||
|
|
||||||
SColorHCY hcy(keyUsedHue_, 1.0, blackKeyLuma_);
|
SColorHCY hcy(0.0, 1.0, blackKeyLuma_);
|
||||||
if (!keyUsed_[key] || allKeysUsed)
|
|
||||||
|
switch (getKeyRole(key)) {
|
||||||
|
case KeyRole::Note:
|
||||||
|
if (allKeysUsed)
|
||||||
|
goto blackKeyDefault;
|
||||||
|
hcy.h = keyUsedHue_;
|
||||||
|
break;
|
||||||
|
case KeyRole::Switch:
|
||||||
|
hcy.h = keySwitchHue_;
|
||||||
|
break;
|
||||||
|
default: blackKeyDefault:
|
||||||
hcy.c = 0.0;
|
hcy.c = 0.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (keyval_[key])
|
if (keyval_[key])
|
||||||
hcy.y = std::max(0.0f, hcy.y - keyLumaPressDelta_);
|
hcy.y = std::max(0.0f, hcy.y - keyLumaPressDelta_);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,17 @@ public:
|
||||||
void setNumOctaves(unsigned octs);
|
void setNumOctaves(unsigned octs);
|
||||||
|
|
||||||
void setKeyUsed(unsigned key, bool used);
|
void setKeyUsed(unsigned key, bool used);
|
||||||
|
void setKeyswitchUsed(unsigned key, bool used);
|
||||||
void setKeyValue(unsigned key, float value);
|
void setKeyValue(unsigned key, float value);
|
||||||
|
|
||||||
|
enum class KeyRole {
|
||||||
|
Unused,
|
||||||
|
Note,
|
||||||
|
Switch,
|
||||||
|
};
|
||||||
|
|
||||||
|
KeyRole getKeyRole(unsigned key);
|
||||||
|
|
||||||
std::function<void(unsigned, float)> onKeyPressed;
|
std::function<void(unsigned, float)> onKeyPressed;
|
||||||
std::function<void(unsigned, float)> onKeyReleased;
|
std::function<void(unsigned, float)> onKeyReleased;
|
||||||
|
|
||||||
|
|
@ -57,6 +66,7 @@ private:
|
||||||
unsigned octs_ {};
|
unsigned octs_ {};
|
||||||
std::vector<float> keyval_;
|
std::vector<float> keyval_;
|
||||||
std::bitset<128> keyUsed_;
|
std::bitset<128> keyUsed_;
|
||||||
|
std::bitset<128> keyswitchUsed_;
|
||||||
unsigned mousePressedKey_ = ~0u;
|
unsigned mousePressedKey_ = ~0u;
|
||||||
|
|
||||||
CCoord innerPaddingX_ = 4.0;
|
CCoord innerPaddingX_ = 4.0;
|
||||||
|
|
@ -67,6 +77,7 @@ private:
|
||||||
float backgroundRadius_ = 5.0;
|
float backgroundRadius_ = 5.0;
|
||||||
|
|
||||||
float keyUsedHue_ = 0.55;
|
float keyUsedHue_ = 0.55;
|
||||||
|
float keySwitchHue_ = 0.0;
|
||||||
float whiteKeyLuma_ = 0.9;
|
float whiteKeyLuma_ = 0.9;
|
||||||
float blackKeyLuma_ = 0.5;
|
float blackKeyLuma_ = 0.5;
|
||||||
float keyLumaPressDelta_ = 0.2;
|
float keyLumaPressDelta_ = 0.2;
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,7 @@ void Synth::Impl::clear()
|
||||||
changedCCsThisCycle_.clear();
|
changedCCsThisCycle_.clear();
|
||||||
keyLabels_.clear();
|
keyLabels_.clear();
|
||||||
keySlots_.clear();
|
keySlots_.clear();
|
||||||
|
swSlots_.clear();
|
||||||
keyswitchLabels_.clear();
|
keyswitchLabels_.clear();
|
||||||
globalOpcodes_.clear();
|
globalOpcodes_.clear();
|
||||||
masterOpcodes_.clear();
|
masterOpcodes_.clear();
|
||||||
|
|
@ -745,6 +746,18 @@ void Synth::Impl::finalizeSfzLoad()
|
||||||
for (unsigned key = loKey; key <= hiKey; ++key)
|
for (unsigned key = loKey; key <= hiKey; ++key)
|
||||||
keySlots_.set(key);
|
keySlots_.set(key);
|
||||||
}
|
}
|
||||||
|
// cache the set of keyswitches assigned
|
||||||
|
for (const RegionPtr& regionPtr : regions_) {
|
||||||
|
if (absl::optional<uint8_t> sw = regionPtr->lastKeyswitch) {
|
||||||
|
swSlots_.set(*sw);
|
||||||
|
}
|
||||||
|
else if (absl::optional<Range<uint8_t>> swRange = regionPtr->lastKeyswitchRange) {
|
||||||
|
unsigned loKey = swRange->getStart();
|
||||||
|
unsigned hiKey = swRange->getEnd();
|
||||||
|
for (unsigned key = loKey; key <= hiKey; ++key)
|
||||||
|
swSlots_.set(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Synth::loadScalaFile(const fs::path& path)
|
bool Synth::loadScalaFile(const fs::path& path)
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,14 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
MATCH("/sw/slots", "") {
|
||||||
|
const BitArray<128>& switches = impl.swSlots_;
|
||||||
|
sfizz_blob_t blob { switches.data(), static_cast<uint32_t>(switches.byte_size()) };
|
||||||
|
client.receive<'b'>(delay, path, &blob);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
MATCH("/cc/slots", "") {
|
MATCH("/cc/slots", "") {
|
||||||
const BitArray<config::numCCs>& ccs = impl.currentUsedCCs_;
|
const BitArray<config::numCCs>& ccs = impl.currentUsedCCs_;
|
||||||
sfizz_blob_t blob { ccs.data(), static_cast<uint32_t>(ccs.byte_size()) };
|
sfizz_blob_t blob { ccs.data(), static_cast<uint32_t>(ccs.byte_size()) };
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,7 @@ struct Synth::Impl final: public Parser::Listener {
|
||||||
std::map<int, size_t> ccLabelsMap_;
|
std::map<int, size_t> ccLabelsMap_;
|
||||||
std::vector<NoteNamePair> keyLabels_;
|
std::vector<NoteNamePair> keyLabels_;
|
||||||
BitArray<128> keySlots_;
|
BitArray<128> keySlots_;
|
||||||
|
BitArray<128> swSlots_;
|
||||||
std::vector<NoteNamePair> keyswitchLabels_;
|
std::vector<NoteNamePair> keyswitchLabels_;
|
||||||
|
|
||||||
// Set as sw_default if present in the file
|
// Set as sw_default if present in the file
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue