Skip to content

Commit

Permalink
Add the region sets (hierarchy)
Browse files Browse the repository at this point in the history
Link the voice lifecycle into region sets and polyphony groups
Respect crudely the polyphony limits without stealing for now
  • Loading branch information
paulfd committed Jun 15, 2020
1 parent 62d7a09 commit 1ab8361
Show file tree
Hide file tree
Showing 8 changed files with 528 additions and 34 deletions.
40 changes: 40 additions & 0 deletions src/sfizz/PolyphonyGroup.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once
#include "Region.h"
#include "Voice.h"
#include "absl/algorithm/container.h"

namespace sfz
{
class PolyphonyGroup {
public:
void setPolyphonyLimit(unsigned limit)
{
polyphonyLimit = limit;
voices.reserve(limit);
}
unsigned getPolyphonyLimit() const { return polyphonyLimit; }
void registerVoice(Voice* voice)
{
if (absl::c_find(voices, voice) == voices.end())
voices.push_back(voice);
}
void removeVoice(const Voice* voice)
{
auto it = absl::c_find(voices, voice);
if (it == voices.end())
return;

auto last = voices.end() - 1;
if (it != last)
std::iter_swap(it, last);

voices.pop_back();
}
const std::vector<Voice*>& getActiveVoices() const { return voices; }
std::vector<Voice*>& getActiveVoices() { return voices; }
private:
unsigned polyphonyLimit { config::maxVoices };
std::vector<Voice*> voices;
};

}
4 changes: 4 additions & 0 deletions src/sfizz/Region.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
DBG("Unkown off mode:" << std::string(opcode.value));
}
break;
case hash("polyphony"):
if (auto value = readOpcode(opcode.value, Default::polyphonyRange))
polyphony = *value;
break;
case hash("note_polyphony"):
if (auto value = readOpcode(opcode.value, Default::polyphonyRange))
notePolyphony = *value;
Expand Down
8 changes: 7 additions & 1 deletion src/sfizz/Region.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include <vector>

namespace sfz {

class RegionSet;

/**
* @brief Regions are the basic building blocks for the SFZ parsing and handling code.
* All SFZ files are made of regions that are activated when a key is pressed or a CC
Expand Down Expand Up @@ -272,7 +275,8 @@ struct Region {
uint32_t group { Default::group }; // group
absl::optional<uint32_t> offBy {}; // off_by
SfzOffMode offMode { Default::offMode }; // off_mode
absl::optional<uint32_t> notePolyphony {};
absl::optional<uint32_t> notePolyphony {}; // note_polyphony
unsigned polyphony { config::maxVoices }; // polyphony
SfzSelfMask selfMask { Default::selfMask };

// Region logic: key mapping
Expand Down Expand Up @@ -357,6 +361,8 @@ struct Region {
// Effects
std::vector<float> gainToEffect;

// Parent
RegionSet* parent { nullptr };
private:
const MidiState& midiState;
bool keySwitched { true };
Expand Down
74 changes: 74 additions & 0 deletions src/sfizz/RegionSet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#pragma once
#include "Region.h"
#include "Voice.h"
#include <vector>

namespace sfz
{

class RegionSet {
public:
void setPolyphonyLimit(unsigned limit)
{
polyphonyLimit = limit;
voices.reserve(limit);
}
unsigned getPolyphonyLimit() const { return polyphonyLimit; }
void addRegion(Region* region)
{
if (absl::c_find(regions, region) == regions.end())
regions.push_back(region);
}
void addSubset(RegionSet* group)
{
if (absl::c_find(subsets, group) == subsets.end())
subsets.push_back(group);
}
void registerVoice(Voice* voice)
{
if (absl::c_find(voices, voice) == voices.end())
voices.push_back(voice);
}
void removeVoice(const Voice* voice)
{
auto it = absl::c_find(voices, voice);
if (it == voices.end())
return;

auto last = voices.end() - 1;
if (it != last)
std::iter_swap(it, last);

voices.pop_back();
DBG("Active voices size " << voices.size());
}
static void registerVoiceInHierarchy(const Region* region, Voice* voice)
{
auto parent = region->parent;
while (parent != nullptr) {
parent->registerVoice(voice);
parent = parent->getParent();
}
}
static void removeVoiceFromHierarchy(const Region* region, const Voice* voice)
{
auto parent = region->parent;
while (parent != nullptr) {
parent->removeVoice(voice);
parent = parent->getParent();
}
}
RegionSet* getParent() const { return parent; }
void setParent(RegionSet* parent) { this->parent = parent; }
const std::vector<Voice*>& getActiveVoices() const { return voices; }
const std::vector<Region*>& getRegions() const { return regions; }
const std::vector<RegionSet*>& getSubsets() const { return subsets; }
private:
RegionSet* parent { nullptr };
std::vector<Region*> regions;
std::vector<RegionSet*> subsets;
std::vector<Voice*> voices;
unsigned polyphonyLimit { config::maxVoices };
};

}
Loading

0 comments on commit 1ab8361

Please sign in to comment.