Skip to content

Commit

Permalink
Add bass and banjo chords
Browse files Browse the repository at this point in the history
Change superstring so it uses the RGBW colour handling for slightly different behaviours. There is some risk of impact in this change.
  • Loading branch information
keithsw1111 committed Apr 10, 2023
1 parent d573f98 commit 004e2d7
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 46 deletions.
111 changes: 81 additions & 30 deletions xLights/effects/GuitarEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ std::vector<GuitarNotes>

std::vector<GuitarNotes>
banjo = {
{ 0, 0, 50 }, // D3
{ 1, 0, 55 }, // G3
{ 2, 0, 59 }, // B4
{ 3, 0, 62 }, // D4
{ 0, 0, 64 }, // D4
{ 1, 0, 50 }, // D3
{ 2, 0, 55 }, // G3
{ 3, 0, 59 }, // B4
{ 4, 0, 62 }, // D4
{ 0, 0, 62 }, // D4
};

class Chordx
Expand Down Expand Up @@ -179,6 +179,51 @@ std::list<Chordx> __guitarChords = {
{ "CAB7", { 51, 56, 60, 66 }, { { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 2 } } }, // G#7 / Ab7
};

std::list<Chordx> __bassChords = {
// Major Chords
{ "CA", { 33, 37, 40, 45 }, { { 0, 5 }, { 1, 4 }, { 2, 2 }, { 3, 3 } } }, // A
{ "CB", { 30, 35, 39, 47 }, { { 0, 2 }, { 1, 2 }, { 2, 1 }, { 3, 4 } } }, // B
{ "CC", { 31, 36, 40, 48 }, { { 0, 3 }, { 1, 3 }, { 2, 2 }, { 3, 5 } } }, // C
{ "CD", { 30, 38, 39, 45 }, { { 0, 2 }, { 1, 5 }, { 2, 0 }, { 3, 2 } } }, // D
{ "CE", { 28, 35, 40, 44 }, { { 0, 0 }, { 1, 2 }, { 2, 2 }, { 3, 1 } } }, // E
{ "CF", { 29, 36, 41, 45 }, { { 0, 1 }, { 1, 3 }, { 2, 3 }, { 3, 2 } } }, // F
{ "CG", { 31, 35, 38, 43 }, { { 0, 3 }, { 1, 2 }, { 2, 0 }, { 3, 0 } } }, // G
// Minor Chords
{ "CAM", { 33, 36, 40, 45 }, { { 0, 5 }, { 1, 3 }, { 2, 2 }, { 3, 3 } } }, // Am
{ "CBM", { 30, 35, 38, 47 }, { { 0, 2 }, { 1, 2 }, { 2, 0 }, { 3, 4 } } }, // Bm
{ "CCM", { 31, 36, 39, 48 }, { { 0, 3 }, { 1, 3 }, { 2, 1 }, { 3, 5 } } }, // Cm
{ "CDM", { 29, 38, 39, 45 }, { { 0, 1 }, { 1, 5 }, { 2, 0 }, { 3, 2 } } }, // Dm
{ "CEM", { 28, 35, 40, 43 }, { { 0, 0 }, { 1, 2 }, { 2, 2 }, { 3, 0 } } }, // Em
{ "CFM", { 29, 36, 41, 44 }, { { 0, 1 }, { 1, 3 }, { 2, 3 }, { 3, 1 } } }, // Fm
{ "CGM", { 31, 34, 38, 43 }, { { 0, 3 }, { 1, 1 }, { 2, 0 }, { 3, 0 } } }, // Gm
// Seventh Chords
{ "CA7", { 31, 37, 40, 45 }, { { 0, 3 }, { 1, 4 }, { 2, 2 }, { 3, 3 } } }, // A7
{ "CB7", { 30, 35, 39, 45 }, { { 0, 2 }, { 1, 2 }, { 2, 1 }, { 3, 2 } } }, // B7
{ "CC7", { 31, 36, 40, 46 }, { { 0, 3 }, { 1, 3 }, { 2, 2 }, { 3, 3 } } }, // C7
{ "CD7", { 30, 36, 39, 45 }, { { 0, 2 }, { 1, 3 }, { 2, 0 }, { 3, 2 } } }, // D7
{ "CE7", { 28, 35, 38, 44 }, { { 0, 0 }, { 1, 2 }, { 2, 0 }, { 3, 1 } } }, // E7
{ "CF7", { 29, 36, 39, 45 }, { { 0, 1 }, { 1, 3 }, { 2, 1 }, { 3, 2 } } }, // F7
{ "CG7", { 29, 35, 38, 43 }, { { 0, 1 }, { 1, 2 }, { 2, 0 }, { 3, 0 } } }, // G7
};

std::list<Chordx> __banjoChords = {
// Major Chords
{ "CA", { 52, 57, 61, 64 }, { { 1, 2 }, { 2, 2 }, { 3, 2 }, { 4, 2 } } }, // A
{ "CA#", { 53, 58, 62, 65 }, { { 1, 3 }, { 2, 3 }, { 3, 3 }, { 4, 3 } } }, // A#
{ "CBB", { 53, 58, 62, 65 }, { { 1, 3 }, { 2, 3 }, { 3, 3 }, { 4, 3 } } }, // Bb
{ "CD", { 50, 57, 62, 66 }, { { 1, 0 }, { 2, 2 }, { 3, 3 }, { 4, 4 } } }, // D
{ "CE", { 52, 56, 59, 64 }, { { 1, 2 }, { 2, 1 }, { 3, 0 }, { 4, 2 } } }, // E
{ "CF", { 53, 57, 60, 65 }, { { 1, 3 }, { 2, 2 }, { 3, 1 }, { 4, 3 } } }, // F
{ "CG", { 50, 55, 59, 62 }, { { 1, 0 }, { 2, 0 }, { 3, 0 }, { 4, 0 } } }, // G
// Minor Chords
{ "CAM", { 52, 57, 60, 64 }, { { 1, 2 }, { 2, 2 }, { 3, 1 }, { 4, 2 } } }, // Am
{ "CDM", { 53, 57, 62, 65 }, { { 1, 3 }, { 2, 2 }, { 3, 3 }, { 4, 3 } } }, // Dm
{ "CEM", { 52, 55, 59, 64 }, { { 1, 2 }, { 2, 0 }, { 3, 0 }, { 4, 2 } } }, // Em
// Seventh Chords
{ "CD7", { 50, 57, 60, 62 }, { { 1, 0 }, { 2, 2 }, { 3, 1 }, { 4, 0 } } }, // D7
{ "CG7", { 50, 55, 59, 65 }, { { 1, 0 }, { 2, 0 }, { 3, 0 }, { 4, 3 } } }, // G7
};

bool centresort(const GuitarTiming* first, const GuitarTiming* second)
{
return first->GetPositionCentre() < second->GetPositionCentre();
Expand Down Expand Up @@ -369,20 +414,26 @@ class NoteTiming

bool CheckChords(const std::string& type)
{
if (type != "Guitar") {
for (auto& it : __guitarChords) {
if (it._notes.size() == _notes.size()) {
if (listsMatch(it._notes, _notes)) {
auto t = new GuitarTiming(_startMS, _endMS);
for (auto it2 : it._guitarTiming) {
t->AddFingerPos(it2.first, it2.second);
}
_possibleTimings.push_back(t);
return true;
auto chords = __guitarChords;

if (type == "Bass")
chords = __bassChords;
else if (type == "Banjo")
chords = __banjoChords;

for (auto& it : chords) {
if (it._notes.size() == _notes.size()) {
if (listsMatch(it._notes, _notes)) {
auto t = new GuitarTiming(_startMS, _endMS);
for (auto it2 : it._guitarTiming) {
t->AddFingerPos(it2.first, it2.second);
}
_possibleTimings.push_back(t);
return true;
}
}
}

return false;
}

Expand Down Expand Up @@ -1100,23 +1151,23 @@ std::list<NoteTiming*> GuitarEffect::LoadTimingTrack(const std::string& track, i
std::string label = el->GetEffect(j)->GetEffectName();
std::list<std::string> notelabels = ExtractNotes(label);
for (const auto& s : notelabels) {

bool chord = false;
if (type == "Guitar") {

// If the label matches one of our chord names then use the chord notes
std::string n = s;
std::transform(n.begin(), n.end(), n.begin(), ::toupper);
for (const auto& c : __guitarChords)
{
if (n == c._name)
{
for (auto nn : c._notes)
{
notes.push_back(nn);
}
chord = true;
auto chords = __guitarChords;

if (type == "Bass")
chords = __bassChords;
else if (type == "Banjo")
chords = __banjoChords;

// If the label matches one of our chord names then use the chord notes
std::string n = s;
std::transform(n.begin(), n.end(), n.begin(), ::toupper);
for (const auto& c : chords) {
if (n == c._name) {
for (auto nn : c._notes) {
notes.push_back(nn);
}
chord = true;
}
}

Expand Down
2 changes: 1 addition & 1 deletion xLights/models/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4183,7 +4183,7 @@ void Model::SetNodeCount(size_t NumStrings, size_t NodesPerString, const std::st
}
else if (StringType == "Superstring") {
for (n = 0; n < NumStrings; n++) {
Nodes.push_back(NodeBaseClassPtr(new NodeClassSuperString(n, NodesPerString, superStringColours, GetNextName())));
Nodes.push_back(NodeBaseClassPtr(new NodeClassSuperString(n, NodesPerString, superStringColours, rgbwHandlingType, GetNextName())));
Nodes.back()->model = this;
}
} else if (StringType=="Single Color Blue") {
Expand Down
128 changes: 115 additions & 13 deletions xLights/models/Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ void NodeClassSuperString::GetForChannels(unsigned char* buf) const
bool y = c[0] > 0 && c[0] == c[1] && c[2] == 0;
bool cy = c[1] > 0 && c[1] == c[2] && c[0] == 0;
bool m = c[0] > 0 && c[0] == c[2] && c[1] == 0;
uint8_t common = std::min(c[0], std::min(c[1], c[2]));

bool primary = r || g || b || y || w || cy || m;
int singleColour = -1;
Expand All @@ -253,23 +254,124 @@ void NodeClassSuperString::GetForChannels(unsigned char* buf) const
}
}

if (singleColour == -1) {
switch (rgbwHandling) {
case RGB_HANDLING_RGB:
// only update rgb
for (int i = 0; i < _superStringColours.size(); i++) {
// this needs work
xlColor cc = _superStringColours[i];
float r = cc.red == 0 ? 1 : (float)c[0] / cc.red;
float g = cc.green == 0 ? 1 : (float)c[1] / cc.green;
float b = cc.blue == 0 ? 1 : (float)c[2] / cc.blue;
float in = std::min(r, std::min(g, std::min(1.0f, b)));
buf[i] = in * 255;
// if this is a white super string
if (_superStringColours[i].red != _superStringColours[i].green || _superStringColours[i].red != _superStringColours[i].blue) {
// this needs work
xlColor cc = _superStringColours[i];
float r = cc.red == 0 ? 1 : (float)c[0] / cc.red;
float g = cc.green == 0 ? 1 : (float)c[1] / cc.green;
float b = cc.blue == 0 ? 1 : (float)c[2] / cc.blue;
float in = std::min(r, std::min(g, std::min(1.0f, b)));
buf[i] = in * 255;
}
}
} else {
break;

case RGB_HANDLING_WHITE:
// only populate the white channel

for (int i = 0; i < _superStringColours.size(); i++) {
if (i == singleColour) {
buf[i] = std::max(c[0], std::max(c[1], c[2]));
} else {
buf[i] = 0;
if (_superStringColours[i].red == _superStringColours[i].green && _superStringColours[i].red == _superStringColours[i].blue) {
buf[i] = common;
}
}
break;

case RGB_HANDLING_ALL:
// this is how it used to work
if (singleColour == -1) {
for (int i = 0; i < _superStringColours.size(); i++) {
// this needs work
xlColor cc = _superStringColours[i];
float r = cc.red == 0 ? 1 : (float)c[0] / cc.red;
float g = cc.green == 0 ? 1 : (float)c[1] / cc.green;
float b = cc.blue == 0 ? 1 : (float)c[2] / cc.blue;
float in = std::min(r, std::min(g, std::min(1.0f, b)));
buf[i] = in * 255;
}
} else {
for (int i = 0; i < _superStringColours.size(); i++) {
if (i == singleColour) {
buf[i] = std::max(c[0], std::max(c[1], c[2]));
} else {
buf[i] = 0;
}
}
}
break;
case RGB_HANDLING_ADVANCED:
// set white the common amount

for (int i = 0; i < _superStringColours.size(); i++) {
// if this is a white super string
if (_superStringColours[i].red != _superStringColours[i].green || _superStringColours[i].red != _superStringColours[i].blue) {
if (singleColour == -1) {
// this needs work
xlColor cc = _superStringColours[i];
float r = cc.red == 0 ? 1 : (float)(c[0] - common) / cc.red;
float g = cc.green == 0 ? 1 : (float)(c[1] - common) / cc.green;
float b = cc.blue == 0 ? 1 : (float)(c[2] - common) / cc.blue;
float in = std::min(r, std::min(g, std::min(1.0f, b)));
buf[i] = in * 255;
} else {
if (i == singleColour) {
buf[i] = std::max(c[0], std::max(c[1], c[2]));
} else {
buf[i] = 0;
}
}
}
else
{
buf[i] = common;
}
}

break;

default: // RGB_HANDLING_NORMAL

// when r==g==b only light up white
if (w)
{
for (int i = 0; i < _superStringColours.size(); i++) {
// if this is a white super string
if (_superStringColours[i].red == _superStringColours[i].green && _superStringColours[i].red == _superStringColours[i].blue)
{
xlColor cc = _superStringColours[i];
float r = cc.red == 0 ? 1 : (float)c[0] / cc.red;
float g = cc.green == 0 ? 1 : (float)c[1] / cc.green;
float b = cc.blue == 0 ? 1 : (float)c[2] / cc.blue;
float in = std::min(r, std::min(g, std::min(1.0f, b)));
buf[i] = in * 255;
}
}
} else {
for (int i = 0; i < _superStringColours.size(); i++) {
// if this is a white super string
if (_superStringColours[i].red != _superStringColours[i].green || _superStringColours[i].red != _superStringColours[i].blue) {
if (singleColour == -1) {
// this needs work
xlColor cc = _superStringColours[i];
float r = cc.red == 0 ? 1 : (float)c[0] / cc.red;
float g = cc.green == 0 ? 1 : (float)c[1] / cc.green;
float b = cc.blue == 0 ? 1 : (float)c[2] / cc.blue;
float in = std::min(r, std::min(g, std::min(1.0f, b)));
buf[i] = in * 255;
} else {
if (i == singleColour) {
buf[i] = std::max(c[0], std::max(c[1], c[2]));
} else {
buf[i] = 0;
}
}
}
}
}
break;
}
}
8 changes: 6 additions & 2 deletions xLights/models/Node.h
Original file line number Diff line number Diff line change
Expand Up @@ -470,14 +470,17 @@ class NodeClassRGBW : public NodeBaseClass
class NodeClassSuperString : public NodeBaseClass
{
public:
NodeClassSuperString(int StringNumber, size_t NodesPerString, const std::vector<xlColor>& superStringColours, const std::string& n = xlEMPTY_STRING)
NodeClassSuperString(int StringNumber, size_t NodesPerString, const std::vector<xlColor>& superStringColours, int rgbwtype, const std::string& n = xlEMPTY_STRING)
: NodeBaseClass(StringNumber, NodesPerString, "RGB")
{
chanCnt = superStringColours.size();
SetName(n);
_superStringColours = superStringColours;
rgbwHandling = rgbwtype;
}
NodeClassSuperString(const NodeClassSuperString& c) : NodeBaseClass(c), _superStringColours(c._superStringColours) {}
NodeClassSuperString(const NodeClassSuperString& c) :
NodeBaseClass(c), _superStringColours(c._superStringColours), rgbwHandling(c.rgbwHandling)
{}

virtual void SetFromChannels(const unsigned char* buf) override;
virtual void GetForChannels(unsigned char* buf) const override;
Expand All @@ -487,6 +490,7 @@ class NodeClassSuperString : public NodeBaseClass
}
private:
std::vector<xlColor> _superStringColours;
uint8_t rgbwHandling;
};

typedef std::unique_ptr<NodeBaseClass> NodeBaseClassPtr;

0 comments on commit 004e2d7

Please sign in to comment.