Skip to content

Commit

Permalink
patternist: add support for accent and slide out
Browse files Browse the repository at this point in the history
  • Loading branch information
jcelerier committed Dec 27, 2024
1 parent 446df82 commit b12d486
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 10 deletions.
24 changes: 22 additions & 2 deletions src/lib/score/graphics/widgets/QGraphicsNoteChooser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,19 @@ QGraphicsNoteChooser::QGraphicsNoteChooser(QGraphicsItem* parent)

void QGraphicsNoteChooser::setValue(int v)
{
m_value = ossia::clamp(v, m_min, m_max);
switch(v)
{
case 255:
m_value = -1;
break;
case 254:
m_value = -2;
break;
default:
m_value = ossia::clamp(v, m_min, m_max);
break;
}

update();
}

Expand Down Expand Up @@ -91,7 +103,15 @@ static QString noteText(int n)
{
static constexpr QStringView lit[12]{u"C", u"C#", u"D", u"D#", u"E", u"F",
u"F#", u"G", u"G#", u"A", u"A#", u"B"};
return QString{"%1%2"}.arg(lit[n % 12]).arg(n / 12 - 1);
switch(n)
{
case -1:
return "AC";
case -2:
return "SL";
default:
return QString{"%1%2"}.arg(lit[n % 12]).arg(n / 12 - 1);
}
}

void QGraphicsNoteChooser::paint(
Expand Down
4 changes: 2 additions & 2 deletions src/lib/score/graphics/widgets/QGraphicsNoteChooser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SCORE_LIB_BASE_EXPORT QGraphicsNoteChooser final
W_OBJECT(QGraphicsNoteChooser)
SCORE_GRAPHICS_ITEM_TYPE(120)

static constexpr int m_min = 0;
static constexpr int m_min = -2;
static constexpr int m_max = 127;
static constexpr double m_width = 30;
static constexpr double m_height = 28;
Expand All @@ -28,7 +28,7 @@ class SCORE_LIB_BASE_EXPORT QGraphicsNoteChooser final
bool m_grab{};

public:
QGraphicsNoteChooser(QGraphicsItem* parent);
explicit QGraphicsNoteChooser(QGraphicsItem* parent);

void setValue(int v);
int value() const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ MovePoint::MovePoint(
// another
if(std::abs(m_oldPoint.x() - m_newPoint.x()) < 0.0001)
{
qDebug() << m_oldPoint.x() - m_newPoint.x();
m_newPoint.rx() = m_oldPoint.x();
}

Expand Down
25 changes: 24 additions & 1 deletion src/plugins/score-plugin-midi/Patternist/PatternExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class pattern_node : public ossia::nonowning_graph_node
{
public:
ossia::midi_outlet out;
ossia::value_outlet accent_out;
ossia::value_outlet slide_out;
Pattern pattern;
ossia::flat_set<uint8_t> in_flight;

Expand All @@ -28,6 +30,8 @@ class pattern_node : public ossia::nonowning_graph_node
{
in_flight.reserve(32);
m_outlets.push_back(&out);
m_outlets.push_back(&accent_out);
m_outlets.push_back(&slide_out);
}

std::string label() const noexcept override { return "pattern_node"; }
Expand Down Expand Up @@ -65,13 +69,32 @@ class pattern_node : public ossia::nonowning_graph_node

for(Lane& lane : pattern.lanes)
{
if(lane.pattern[current])
if(lane.note <= 127 && lane.pattern[current])
{
mess.push_back(libremidi::channel_events::note_on(channel, lane.note, 64));
mess.back().timestamp = date;
in_flight.insert(lane.note);
}
}

for(Lane& lane : pattern.lanes)
{
if(lane.note == 255)
{
if(lane.pattern[current])
accent_out->write_value(1., date);
else
accent_out->write_value(0., date);
}
else if(lane.note == 254)
{
if(lane.pattern[current])
slide_out->write_value(1., date);
else
slide_out->write_value(0., date);
}
}

current = (current + 1) % pattern.length;
}
}
Expand Down
35 changes: 31 additions & 4 deletions src/plugins/score-plugin-midi/Patternist/PatternModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ namespace Patternist
ProcessModel::ProcessModel(
const TimeVal& duration, const Id<Process::ProcessModel>& id, QObject* parent)
: Process::
ProcessModel{duration, id, Metadata<ObjectKey_k, ProcessModel>::get(), parent}
ProcessModel{duration, id, Metadata<ObjectKey_k, ProcessModel>::get(), parent}
, outlet{Process::make_midi_outlet(Id<Process::Port>(0), this)}
, accent{Process::make_value_outlet(Id<Process::Port>(1), this)}
, slide{Process::make_value_outlet(Id<Process::Port>(2), this)}
{
Pattern pattern;
pattern.length = 4;
Expand All @@ -37,7 +39,6 @@ ProcessModel::ProcessModel(
const Id<Process::ProcessModel>& id, QObject* parent)
: Patternist::ProcessModel{duration, id, parent}
{

if(QFile f{customData}; f.open(QIODevice::ReadOnly))
if(auto data = score::mapAsByteArray(f); !data.isEmpty())
if(auto pat = parsePattern(data); pat.lanes.size() > 0)
Expand All @@ -47,6 +48,8 @@ ProcessModel::ProcessModel(
void ProcessModel::init()
{
m_outlets.push_back(outlet.get());
m_outlets.push_back(accent.get());
m_outlets.push_back(slide.get());
}

ProcessModel::~ProcessModel() { }
Expand Down Expand Up @@ -196,7 +199,8 @@ void JSONWriter::write(Patternist::Pattern& proc)
template <>
void DataStreamReader::read(const Patternist::ProcessModel& proc)
{
m_stream << *proc.outlet << proc.m_channel << proc.m_currentPattern << proc.m_patterns;
m_stream << *proc.outlet << *proc.accent << *proc.slide << proc.m_channel
<< proc.m_currentPattern << proc.m_patterns;

insertDelimiter();
}
Expand All @@ -205,7 +209,8 @@ template <>
void DataStreamWriter::write(Patternist::ProcessModel& proc)
{
proc.outlet = Process::load_midi_outlet(*this, &proc);
m_stream >> proc.m_channel >> proc.m_currentPattern >> proc.m_patterns;
m_stream >> proc.m_channel >> *proc.accent >> *proc.slide >> proc.m_currentPattern
>> proc.m_patterns;

checkDelimiter();
}
Expand All @@ -214,6 +219,8 @@ template <>
void JSONReader::read(const Patternist::ProcessModel& proc)
{
obj["Outlet"] = *proc.outlet;
obj["Accent"] = *proc.accent;
obj["Slide"] = *proc.slide;
obj["Channel"] = proc.m_channel;
obj["Pattern"] = proc.m_currentPattern;
obj["Patterns"] = proc.m_patterns;
Expand All @@ -226,6 +233,26 @@ void JSONWriter::write(Patternist::ProcessModel& proc)
JSONWriter writer{obj["Outlet"]};
proc.outlet = Process::load_midi_outlet(writer, &proc);
}

if(auto port = obj.tryGet("Accent"))
{
JSONWriter writer{*port};
proc.accent = Process::load_value_outlet(writer, &proc);
}
else
{
proc.accent = Process::make_value_outlet(Id<Process::Port>(1), &proc);
}

if(auto port = obj.tryGet("Slide"))
{
JSONWriter writer{*port};
proc.slide = Process::load_value_outlet(writer, &proc);
}
else
{
proc.slide = Process::make_value_outlet(Id<Process::Port>(2), &proc);
}
proc.m_channel = obj["Channel"].toInt();
proc.m_currentPattern = obj["Pattern"].toInt();
proc.m_patterns <<= obj["Patterns"];
Expand Down
6 changes: 6 additions & 0 deletions src/plugins/score-plugin-midi/Patternist/PatternModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

#include <verdigris>

namespace Process
{
class ValueOutlet;
}
namespace Patternist
{
struct Lane
Expand Down Expand Up @@ -68,6 +72,8 @@ class SCORE_PLUGIN_MIDI_EXPORT ProcessModel final : public Process::ProcessModel
const std::vector<Pattern>& patterns() const noexcept;

std::unique_ptr<Process::MidiOutlet> outlet;
std::unique_ptr<Process::Outlet> accent;
std::unique_ptr<Process::Outlet> slide;

public:
void channelChanged(int arg_1) W_SIGNAL(channelChanged, arg_1);
Expand Down
11 changes: 11 additions & 0 deletions src/plugins/score-plugin-midi/Patternist/PatternParsing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ Pattern parsePattern(const QByteArray& data) noexcept
Lane lane;
bool ok = false;
lane.note = split[0].toInt(&ok);
if(!ok && split[0] == "AC")
{
lane.note = 255;
ok = true;
}
if(!ok && split[0] == "SL")
{
lane.note = 254;
ok = true;
}

if(ok)
{
p.length = split[1].size();
Expand Down

0 comments on commit b12d486

Please sign in to comment.