2#include <Fx/Looper/TakeWriter.hpp>
3#include <Fx/Looper/ValueLoop.hpp>
5#include <ossia/network/value/value.hpp>
53 static constexpr int max_items = value_loop::max_events;
60 std::array<item, max_items> items{};
65 int meter_numerator{4};
66 int meter_denominator{4};
73 for(
int i = 0; i < count; i++)
74 items[i].value.reset();
77 void add(int64_t pos,
const value_slot& v,
bool impulse)
79 if(count >= max_items)
81 auto& it = items[count++];
91 static bool is_number(
const ossia::value& v)
noexcept
93 const auto t = v.get_type();
94 return t == ossia::val_type::FLOAT || t == ossia::val_type::INT
95 || t == ossia::val_type::BOOL;
105 case ossia::val_type::FLOAT:
106 case ossia::val_type::INT:
107 case ossia::val_type::BOOL:
109 case ossia::val_type::VEC2F:
111 case ossia::val_type::VEC3F:
113 case ossia::val_type::VEC4F:
115 case ossia::val_type::LIST: {
116 const auto& l = v.get<std::vector<ossia::value>>();
117 for(
const auto& e : l)
120 return int(l.size());
127 static double number(
const ossia::value& v,
int component)
noexcept
131 case ossia::val_type::LIST: {
132 const auto& l = v.get<std::vector<ossia::value>>();
133 return component >= 0 && component < int(l.size()) ?
number(l[component], 0) : 0.;
135 case ossia::val_type::FLOAT:
136 return v.get<
float>();
137 case ossia::val_type::INT:
139 case ossia::val_type::BOOL:
140 return v.get<
bool>() ? 1. : 0.;
141 case ossia::val_type::VEC2F:
142 return v.get<ossia::vec2f>()[std::clamp(component, 0, 1)];
143 case ossia::val_type::VEC3F:
144 return v.get<ossia::vec3f>()[std::clamp(component, 0, 2)];
145 case ossia::val_type::VEC4F:
146 return v.get<ossia::vec4f>()[std::clamp(component, 0, 3)];
158 for(
int i = 0; i < count; i++)
162 const int k =
numbers_of(items[i].value.get());
170 std::string to_json()
const
173 out.reserve(256 + std::size_t(count) * 32);
174 out +=
"{\n \"format\": \"score-value-take\",\n \"version\": 1,\n \"rate\": ";
175 write_number(out, rate);
176 out +=
",\n \"frames\": ";
177 out += std::to_string(length);
178 out +=
",\n \"tempo\": ";
179 write_number(out, tempo);
180 out +=
",\n \"meter\": [";
181 out += std::to_string(meter_numerator);
183 out += std::to_string(meter_denominator);
184 out +=
"],\n \"components\": ";
186 out += std::to_string(n);
189 std::array<double, max_components> lo, hi;
190 std::array<bool, max_components> seen{};
193 for(
int i = 0; i < count; i++)
195 const auto& v = items[i].value.get();
197 for(
int c = 0; c < k; c++)
199 const double x = number(v, c);
200 lo[c] = !seen[c] ? x : std::min(lo[c], x);
201 hi[c] = !seen[c] ? x : std::max(hi[c], x);
205 for(
const auto& [name, arr] : {std::pair{
",\n \"min\": [", &lo}, {
"],\n \"max\": [", &hi}})
208 for(
int c = 0; c < n; c++)
212 write_number(out, (*arr)[c]);
217 out +=
",\n \"events\": [";
218 for(
int i = 0; i < count; i++)
220 out += i == 0 ?
"\n [" :
",\n [";
221 out += std::to_string(items[i].pos);
223 out +=
", \"impulse\"";
231 out += count > 0 ?
"\n ]\n}\n" :
"]\n}\n";
235 static void write_number(std::string& out,
double x)
237 if(!std::isfinite(x))
242 fmt::format_to(std::back_inserter(out),
"{}", x);
244 static void write_number(std::string& out,
float x)
246 if(!std::isfinite(x))
251 fmt::format_to(std::back_inserter(out),
"{}", x);
253 static void write_string(std::string& out, std::string_view s)
276 if(
static_cast<unsigned char>(ch) < 0x20)
279 std::snprintf(buf,
sizeof(buf),
"\\u%04x", ch);
291 static void write_typed(std::string& out,
const ossia::value& v,
bool flat)
295 auto vec = [&](
const char* name,
const auto& a) {
299 for(std::size_t i = 0; i < a.size(); i++)
303 write_number(out, a[i]);
309 case ossia::val_type::FLOAT:
310 out +=
"\"float\", ";
311 write_number(out, v.get<
float>());
313 case ossia::val_type::INT:
315 out += std::to_string(v.get<
int>());
317 case ossia::val_type::BOOL:
318 out += v.get<
bool>() ?
"\"bool\", true" :
"\"bool\", false";
320 case ossia::val_type::STRING:
321 out +=
"\"string\", ";
322 write_string(out, v.get<std::string>());
324 case ossia::val_type::VEC2F:
325 vec(
"vec2f", v.get<ossia::vec2f>());
327 case ossia::val_type::VEC3F:
328 vec(
"vec3f", v.get<ossia::vec3f>());
330 case ossia::val_type::VEC4F:
331 vec(
"vec4f", v.get<ossia::vec4f>());
333 case ossia::val_type::LIST: {
334 out +=
"\"list\", [";
336 for(
const auto& e : v.get<std::vector<ossia::value>>())
346 case ossia::val_type::MAP: {
349 for(
const auto& [k, e] : v.get<ossia::value_map_type>())
354 write_string(out, k);
361 case ossia::val_type::IMPULSE:
363 out +=
"\"impulse\"";
379 tl.
update(snap, 0, scratch, item, item, item < 0,
true);
381 for(
int i = 0; i < tl.count; i++)
382 if(tl.points[i].event >= 0)
383 e.add(tl.points[i].pos, snap.events[tl.points[i].event].value,
false);
384 for(
int i = 0; i < snap.event_count; i++)
386 const auto& ev = snap.events[i];
387 if(!ev.impulse || !snap.
heard(ev, item < 0) || (item >= 0 && ev.pass != item))
389 const int64_t period = snap.period_for(ev.pass);
390 for(int64_t q = ev.pos % period; q < snap.
length; q += period)
391 e.add(q, ev.value,
true);
393 std::sort(e.items.begin(), e.items.begin() + e.count, [](
const auto& a,
const auto& b) {
394 return a.pos != b.pos ? a.pos < b.pos : a.impulse < b.impulse;
407 int meter_numerator{4};
408 int meter_denominator{4};
410 std::atomic_bool in_use{};
415 std::shared_ptr<take_writer> writer;
416 std::shared_ptr<value_export> data;
419 std::shared_ptr<value_stop_take>
stop;
432 bool write(
const value_export& e)
434 const std::string bytes = e.to_json();
435 const auto& path = writer->next_path(slot,
number, layer);
437 std::filesystem::path{std::u8string_view{
438 reinterpret_cast<const char8_t*
>(path.data()), path.size()}},
439 std::ios::binary | std::ios::trunc};
440 f.write(bytes.data(), std::streamsize(bytes.size()));
453 ~release() { e.in_use =
false; }
455 if(!writer || data->length <= 0)
458 nothing = data->count == 0;
476 bool ok = writer && s.loop.length > 0;
477 bool placeable =
true;
480 auto e = std::make_unique<value_export>();
481 auto tl = std::make_unique<held_timeline>();
482 auto scratch = std::make_unique<held_scratch>();
485 e->meter_numerator = s.meter_numerator;
486 e->meter_denominator = s.meter_denominator;
488 for(layer = -1; ok && layer < s.loop.count; layer++)
493 if(layer < 0 || e->count > 0)
494 placeable = placeable && e->components() > 0;
502 s.notice.written(*writer, slot, ok, s.loop.count, placeable);
Definition ValueLoop.hpp:26
Definition AudioLayers.hpp:14
void fill_value_export(const value_loop &snap, int item, held_timeline &tl, held_scratch &scratch, value_export &e)
Definition ValueTake.hpp:374
Definition ValueLoop.hpp:415
Definition ValueLoop.hpp:500
void update(const value_loop &loop, uint16_t key, held_scratch &scratch, int first=-1, int last=-1, bool own_mute=true, bool force=false) noexcept
Definition ValueLoop.hpp:533
int64_t length
Frames in the loop.
Definition PassStack.hpp:79
Definition TakeWriter.hpp:153
Definition ValueTake.hpp:55
Definition ValueTake.hpp:52
static double number(const ossia::value &v, int component) noexcept
Number component of a value, which it has.
Definition ValueTake.hpp:127
static constexpr int max_components
Definition ValueTake.hpp:89
static void write_typed(std::string &out, const ossia::value &v, bool flat)
Definition ValueTake.hpp:291
int components() const noexcept
Definition ValueTake.hpp:155
static int numbers_of(const ossia::value &v) noexcept
Definition ValueTake.hpp:101
std::atomic_bool in_use
Definition ValueTake.hpp:69
Definition ValueLoop.hpp:117
bool heard(const T &e, bool own_mute=true) const noexcept
Definition ValueLoop.hpp:214
Definition ValueTake.hpp:403
Definition ValueTake.hpp:414
int number
Number of the take, 0 for a new one; -1 for the mix, else the pass.
Definition ValueTake.hpp:422
int components
Definition ValueTake.hpp:429
std::shared_ptr< value_stop_take > stop
Definition ValueTake.hpp:419
bool run_stop()
Definition ValueTake.hpp:464