Skip to content

Commit

Permalink
flow.histogram added
Browse files Browse the repository at this point in the history
related to #157
  • Loading branch information
uliss committed May 8, 2024
1 parent 0fd36eb commit 4a9bcc9
Show file tree
Hide file tree
Showing 7 changed files with 482 additions and 5 deletions.
1 change: 1 addition & 0 deletions ceammc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## [0.9.8]
### Added:
- new objects:
- flow.histogram (with flow.hist alias) - for runtime flow histogram calculation
- hw.gamepad - gamepad support
- hw.printer - simple printing support (only PDF files)
- msg.unpack - unpack message to selector and arguments
Expand Down
1 change: 1 addition & 0 deletions ceammc/ext/src/flow/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ ceammc_flow_external(gate)
ceammc_flow_external(greater)
ceammc_flow_external(greater_eq)
ceammc_flow_external(group)
ceammc_flow_external(histogram)
ceammc_flow_external(interval)
ceammc_flow_external(less)
ceammc_flow_external(less_eq)
Expand Down
137 changes: 137 additions & 0 deletions ceammc/ext/src/flow/flow_histogram.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*****************************************************************************
* Copyright 2024 Serge Poltavski. All rights reserved.
*
* This file may be distributed under the terms of GNU Public License version
* 3 (GPL v3) as defined by the Free Software Foundation (FSF). A copy of the
* license should have been included with this file, or the project in which
* this file belongs to. You may also find the details of GPL v3 at:
* http://www.gnu.org/licenses/gpl-3.0.txt
*
* If you have any questions regarding the use of this file, feel free to
* contact the author of this file, or the owner of the project in which
* this file belongs to.
*****************************************************************************/
#include "flow_histogram.h"
#include "ceammc_factory.h"

#include <cassert>
#include <numeric>

FlowHistogram::FlowHistogram(const PdArgs& args)
: BaseObject(args)
{
normalize_ = new BoolProperty("@norm", true);
addProperty(normalize_);

inner_bins_ = new BoolProperty("@inner_bins", true);
addProperty(inner_bins_);

sync_ = new BoolProperty("@sync", true);
addProperty(sync_);

bins_ = new ListProperty("@bins", AtomList { 0. });
bins_->setArgIndex(0);
bins_->setListCheckFn([this](const AtomListView& lv) {
return lv.size() > 0 && lv.allOf(isFloat);
});
bins_->setSuccessFn([this](Property* p) {
auto& val = bins_->value();
val.sort();

counters_.assign(val.size() + 1, 0.0);
output_.resizePad(counters_.size(), 0.);
output_.fill(0.0);

fbins_.resize(val.size() + 2);
fbins_.front() = std::numeric_limits<t_float>::lowest();
fbins_.back() = std::numeric_limits<t_float>::max();

for (size_t i = 0; i < val.size(); i++) {
fbins_[i + 1] = val[i].asT<t_float>();
}
});
addProperty(bins_);

createOutlet();
}

void FlowHistogram::onBang()
{
output();
}

void FlowHistogram::onFloat(t_float f)
{
if (fbins_.empty()) {
return;
}

// find bin index
// O=log2(N)+O(1)
auto it = std::upper_bound(fbins_.begin(), fbins_.end(), f);
// should not happen
if (it == fbins_.end())
return;

// bin index
auto idx = (it - fbins_.begin()) - 1;

// should not happen
if (idx < 0 || idx >= counters_.size())
return;

counters_[idx]++;
output_[idx] = counters_[idx];

if (sync_->value())
output();
}

void FlowHistogram::m_clear(t_symbol*, const AtomListView&)
{
clear();
}

void FlowHistogram::clear()
{
std::fill(counters_.begin(), counters_.end(), 0.0);
output_.fill(0.0);
}

void FlowHistogram::output()
{
if (normalize_->value()) {
// O=O(N) max(N−1,0)
std::uint64_t max = 0;
if (inner_bins_->value()) {
if (counters_.size() >= 2) {
auto it = std::max_element(counters_.begin() + 1, counters_.end() - 1);
if (it != counters_.end())
max = *it;
}
} else {
auto it = std::max_element(counters_.begin(), counters_.end());
if (it != counters_.end())
max = *it;
}

if (max > 0) {
// O=O(N)
for (size_t i = 0; i < counters_.size(); i++)
output_[i] = static_cast<double>(counters_[i]) / max;
}
}

if (inner_bins_->value())
listTo(0, output_.view(1, output_.size() - 2));
else
listTo(0, output_);
}

void setup_flow_histogram()
{
ObjectFactory<FlowHistogram> obj("flow.histogram");
obj.addAlias("flow.hist");

obj.addMethod("clear", &FlowHistogram::m_clear);
}
45 changes: 45 additions & 0 deletions ceammc/ext/src/flow/flow_histogram.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*****************************************************************************
* Copyright 2024 Serge Poltavski. All rights reserved.
*
* This file may be distributed under the terms of GNU Public License version
* 3 (GPL v3) as defined by the Free Software Foundation (FSF). A copy of the
* license should have been included with this file, or the project in which
* this file belongs to. You may also find the details of GPL v3 at:
* http://www.gnu.org/licenses/gpl-3.0.txt
*
* If you have any questions regarding the use of this file, feel free to
* contact the author of this file, or the owner of the project in which
* this file belongs to.
*****************************************************************************/
#ifndef FLOW_HISTOGRAM_H
#define FLOW_HISTOGRAM_H

#include "ceammc_object.h"
using namespace ceammc;

class FlowHistogram : public BaseObject {
std::vector<std::uint64_t> counters_;
std::vector<t_float> fbins_;
AtomList output_;

BoolProperty* normalize_ { nullptr };
BoolProperty* inner_bins_ { nullptr };
BoolProperty* sync_ { nullptr };
ListProperty* bins_ { nullptr };

public:
FlowHistogram(const PdArgs& args);

void onBang() final;
void onFloat(t_float f) final;

void m_clear(t_symbol*, const AtomListView&);

private:
void clear();
void output();
};

void setup_flow_histogram();

#endif // FLOW_HISTOGRAM_H
12 changes: 7 additions & 5 deletions ceammc/ext/src/flow/mod_flow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

void setup_flow_append();
void setup_flow_delay();
void setup_flow_histogram();
void setup_flow_match();
void setup_flow_pipe();
void setup_flow_prepend();
Expand All @@ -50,18 +51,18 @@ void setup_flow_space();
void setup_seq_arp();
void setup_seq_bangs();
void setup_seq_counter();
void setup_seq_life();
void setup_seq_matrix();
void setup_seq_nbangs();
void setup_seq_phasor();
void setup_seq_sequencer();
void setup_seq_toggles();
void setup_seq_life();

void setup_route_any();
void setup_route_bang();
void setup_route_cycle();
void setup_route_float();
void setup_route_data();
void setup_route_float();
void setup_route_list();
void setup_route_prop();
void setup_route_random();
Expand All @@ -82,11 +83,11 @@ void ceammc_flow_setup()
setup_flow_greater();
setup_flow_greater_eq();
setup_flow_group();
setup_flow_histogram();
setup_flow_interval();
setup_flow_less();
setup_flow_less_eq();
setup_flow_list2many();
setup_flow_ring();
setup_flow_loop();
setup_flow_match();
setup_flow_mem();
Expand All @@ -104,6 +105,7 @@ void ceammc_flow_setup()
setup_flow_record();
setup_flow_reject();
setup_flow_reject_if();
setup_flow_ring();
setup_flow_route();
setup_flow_select();
setup_flow_seqdelay();
Expand All @@ -118,18 +120,18 @@ void ceammc_flow_setup()
setup_seq_arp();
setup_seq_bangs();
setup_seq_counter();
setup_seq_life();
setup_seq_matrix();
setup_seq_nbangs();
setup_seq_phasor();
setup_seq_sequencer();
setup_seq_toggles();
setup_seq_life();

setup_route_any();
setup_route_bang();
setup_route_cycle();
setup_route_float();
setup_route_data();
setup_route_float();
setup_route_list();
setup_route_prop();
setup_route_random();
Expand Down
1 change: 1 addition & 0 deletions ceammc/ext/tests/flow/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ add_flow_test(dollar)
add_flow_test(dup)
add_flow_test(gate)
add_flow_test(group)
add_flow_test(histogram)
add_flow_test(less)
add_flow_test(less_eq)
add_flow_test(match)
Expand Down
Loading

0 comments on commit 4a9bcc9

Please sign in to comment.