From b1e84d6c5af55f4d62a05b1f8361ff0ed82456db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= Date: Sun, 29 Sep 2024 18:54:49 -0400 Subject: [PATCH] [core] Continue the coroutine purge --- include/avnd/binding/max/audio_processor.hpp | 2 +- include/avnd/binding/ossia/node.hpp | 7 +- include/avnd/binding/ossia/soundfiles.hpp | 8 +- include/avnd/binding/ossia/time_controls.hpp | 2 +- include/avnd/binding/pd/audio_processor.hpp | 2 +- include/avnd/binding/python/processor.hpp | 6 ++ .../avnd/binding/vintage/atomic_controls.hpp | 10 +- include/avnd/wrappers/controls.hpp | 2 +- include/avnd/wrappers/controls_double.hpp | 7 +- include/avnd/wrappers/effect_container.hpp | 99 ++++++++++++------- .../avnd/wrappers/process/per_sample_arg.hpp | 3 +- .../avnd/wrappers/process/per_sample_port.hpp | 4 +- include/halp/audio.hpp | 12 +++ include/halp/controls_fmt.hpp | 15 +++ 14 files changed, 120 insertions(+), 59 deletions(-) diff --git a/include/avnd/binding/max/audio_processor.hpp b/include/avnd/binding/max/audio_processor.hpp index 5b35e44d..3512337b 100644 --- a/include/avnd/binding/max/audio_processor.hpp +++ b/include/avnd/binding/max/audio_processor.hpp @@ -134,7 +134,7 @@ struct audio_processor void process_inlet_control(t_symbol* s, long argc, t_atom* argv) { - for(auto& state : implementation.full_state()) + for(auto state : implementation.full_state()) { switch(argv[0].a_type) { diff --git a/include/avnd/binding/ossia/node.hpp b/include/avnd/binding/ossia/node.hpp index b6eb23de..96ea07d8 100644 --- a/include/avnd/binding/ossia/node.hpp +++ b/include/avnd/binding/ossia/node.hpp @@ -408,8 +408,9 @@ class safe_node_base : public safe_node_base_base template void process_all_ports(Args&&... args) { - for(auto& [impl, i, o] : this->impl.full_state()) + for(auto [impl, i, o] : this->impl.full_state()) { + static_assert(std::is_reference_v); Functor f{*this, impl, args...}; if constexpr(avnd::inputs_type::size > 0) process_inputs_impl(f, i); @@ -826,7 +827,7 @@ class safe_node_base : public safe_node_base_base typename controls_input_queue::i_tuple make_controls_in_tuple() { // We only care about the inputs of the first one, since they're all the same - for(auto& state : this->impl.full_state()) + for(auto state : this->impl.full_state()) { return avnd::control_input_introspection::filter_tuple( state.inputs, [](auto& field) { return field.value; }); @@ -837,7 +838,7 @@ class safe_node_base : public safe_node_base_base typename controls_output_queue::o_tuple make_controls_out_tuple() { // Note that this does not yet make a lot of sens for polyphonic effects - for(auto& state : this->impl.full_state()) + for(auto state : this->impl.full_state()) { return avnd::control_output_introspection::filter_tuple( state.outputs, [](auto& field) { return field.value; }); diff --git a/include/avnd/binding/ossia/soundfiles.hpp b/include/avnd/binding/ossia/soundfiles.hpp index 9e647c5a..adf527aa 100644 --- a/include/avnd/binding/ossia/soundfiles.hpp +++ b/include/avnd/binding/ossia/soundfiles.hpp @@ -120,7 +120,7 @@ struct soundfile_storage : soundfile_input_storage buf[i] = g->data[i].data(); // Update the port - for(auto& state : t.full_state()) + for(auto state : t.full_state()) { auto& port = avnd::pfr::get(state.inputs); port.soundfile.data = buf.data(); @@ -149,7 +149,7 @@ struct soundfile_storage : soundfile_input_storage } // Update the port - for(auto& state : t.full_state()) + for(auto state : t.full_state()) { auto& port = avnd::pfr::get(state.inputs); port.soundfile.data = buf.data(); @@ -216,7 +216,7 @@ struct midifile_storage : midifile_input_storage // Store the handle to keep the memory from being freed std::exchange(g, hdl); - for(auto& state : t.full_state()) + for(auto state : t.full_state()) { avnd::midifile_port auto& port = avnd::pfr::get(state.inputs); @@ -343,7 +343,7 @@ struct raw_file_storage : raw_file_input_storage // Store the handle to keep the memory from being freed std::exchange(g, hdl); - for(auto& state : t.full_state()) + for(auto state : t.full_state()) { avnd::raw_file_port auto& port = avnd::pfr::get(state.inputs); diff --git a/include/avnd/binding/ossia/time_controls.hpp b/include/avnd/binding/ossia/time_controls.hpp index 86452158..40eade62 100644 --- a/include/avnd/binding/ossia/time_controls.hpp +++ b/include/avnd/binding/ossia/time_controls.hpp @@ -54,7 +54,7 @@ struct time_control_storage : time_control_input_storage auto& g = get(this->handles); if(g.sync) { - for(auto& state : t.full_state()) + for(auto state : t.full_state()) { auto& port = avnd::pfr::get(state.inputs); port.value = to_seconds(g.value, new_tempo); diff --git a/include/avnd/binding/pd/audio_processor.hpp b/include/avnd/binding/pd/audio_processor.hpp index 3a4ea3a4..6e092670 100644 --- a/include/avnd/binding/pd/audio_processor.hpp +++ b/include/avnd/binding/pd/audio_processor.hpp @@ -162,7 +162,7 @@ struct audio_processor void process_inlet_control(t_symbol* s, int argc, t_atom* argv) { - for(auto& state : implementation.full_state()) + for(auto state : implementation.full_state()) { switch(argv[0].a_type) { diff --git a/include/avnd/binding/python/processor.hpp b/include/avnd/binding/python/processor.hpp index bba49c98..ba9bd715 100644 --- a/include/avnd/binding/python/processor.hpp +++ b/include/avnd/binding/python/processor.hpp @@ -34,6 +34,12 @@ inline consteval const char* c_str(const char* v) noexcept return v; } +template +inline const char* c_str(const std::array& v) noexcept +{ + return v.data(); +} + namespace py = pybind11; template diff --git a/include/avnd/binding/vintage/atomic_controls.hpp b/include/avnd/binding/vintage/atomic_controls.hpp index 24018633..896f862d 100644 --- a/include/avnd/binding/vintage/atomic_controls.hpp +++ b/include/avnd/binding/vintage/atomic_controls.hpp @@ -113,15 +113,13 @@ struct Controls { std::atomic_thread_fence(std::memory_order_acquire); - [ this, &implementation ]( - std::integer_sequence) - { - for(auto& state : implementation.full_state()) + [this, &implementation]( + std::integer_sequence) { + for(auto state : implementation.full_state()) { (this->write_control(state.effect, state.inputs), ...); } - } - (std::make_index_sequence()); + }(std::make_index_sequence()); } template diff --git a/include/avnd/wrappers/controls.hpp b/include/avnd/wrappers/controls.hpp index 2bdfedce..6dfbe05e 100644 --- a/include/avnd/wrappers/controls.hpp +++ b/include/avnd/wrappers/controls.hpp @@ -47,7 +47,7 @@ static constexpr void init_controls(F& state) template static constexpr void init_controls(avnd::effect_container& effect) { - for(auto& state : effect.full_state()) + for(auto state : effect.full_state()) { init_controls(state); } diff --git a/include/avnd/wrappers/controls_double.hpp b/include/avnd/wrappers/controls_double.hpp index 25138153..134ecf04 100644 --- a/include/avnd/wrappers/controls_double.hpp +++ b/include/avnd/wrappers/controls_double.hpp @@ -2,6 +2,7 @@ /* SPDX-License-Identifier: GPL-3.0-or-later */ +#include #include #include @@ -50,7 +51,8 @@ static constexpr auto map_control_from_double(std::floating_point auto v) template static constexpr auto map_control_from_double(std::floating_point auto v) { - static_assert(std::is_void_v, "Error: unhandled control type"); + // static_assert(std::is_void_v, "Error: unhandled control type"); + return T{}; } template @@ -89,7 +91,8 @@ static constexpr auto map_control_to_double(const auto& value) template static constexpr auto map_control_to_double(const auto& value) { - static_assert(std::is_void_v, "Error: unhandled control type"); + // static_assert(std::is_void_v, "Error: unhandled control type"); + return 0.; } template diff --git a/include/avnd/wrappers/effect_container.hpp b/include/avnd/wrappers/effect_container.hpp index 252cb7ed..ee98bfe2 100644 --- a/include/avnd/wrappers/effect_container.hpp +++ b/include/avnd/wrappers/effect_container.hpp @@ -45,10 +45,16 @@ struct member_iterator_poly_effect } void operator++() noexcept { i++; } - auto& operator*() const noexcept { return self.effect[i]; } + auto& operator*() const noexcept + { + if constexpr(std::is_same_v) + return self.effect[i]; + else + return self.effect[i].effect; + } bool operator==(std::default_sentinel_t) const noexcept { - return i >= self.effects.size(); + return i >= self.effect.size(); } member_iterator_poly_effect begin() const noexcept { return *this; @@ -58,6 +64,26 @@ struct member_iterator_poly_effect } }; +template +struct full_state_iterator +{ + T& self; + int i = 0; + explicit full_state_iterator(T& self) noexcept + : self{self} + { + } + + void operator++() noexcept { i++; } + auto operator*() const noexcept { return self.full_state(i); } + bool operator==(std::default_sentinel_t) const noexcept + { + return i >= self.effect.size(); + } + full_state_iterator begin() const noexcept { return *this; } + auto end() const noexcept { return std::default_sentinel; } +}; + template struct inputs_storage { @@ -189,9 +215,7 @@ struct effect_container auto& outputs() noexcept { return dummy_instance; } auto& outputs() const noexcept { return dummy_instance; } - member_iterator effects() { - return member_iterator_one_effect{*this}; - } + auto effects() { return member_iterator_one_effect{*this}; } struct ref { @@ -287,13 +311,10 @@ struct effect_container [[no_unique_address]] avnd::dummy outputs; }; - member_iterator full_state() + ref full_state(int i) { return {effect[i], this->inputs_storage, dummy_instance}; } + full_state_iterator full_state() { - for(T& e : effect) - { - ref r{e, this->inputs_storage, dummy_instance}; - co_yield r; - } + return full_state_iterator{*this}; } auto effects() @@ -334,13 +355,14 @@ struct effect_container typename T::outputs& outputs; }; - member_iterator full_state() + ref full_state(int i) { - for(state& e : effect) - { - ref r{e.effect, this->inputs_storage, e.outputs_storage}; - co_yield r; - } + return {effect[i].effect, this->inputs_storage, effect[i].outputs_storage}; + } + + full_state_iterator full_state() + { + return full_state_iterator{*this}; } auto effects() @@ -384,13 +406,15 @@ struct effect_container typename T::inputs& inputs; decltype(T::outputs)& outputs; }; - member_iterator full_state() + + ref full_state(int i) { - for(T& e : effect) - { - ref r{e.effect, this->inputs_storage, e.effect.outputs}; - co_yield r; - } + return {effect[i].effect, this->inputs_storage, effect[i].effect.outputs}; + } + + full_state_iterator full_state() + { + return full_state_iterator{*this}; } auto effects() @@ -438,20 +462,19 @@ struct effect_container decltype(T::inputs)& inputs; decltype(T::outputs)& outputs; }; - member_iterator full_state() + + ref full_state(int i) { - for(T& e : effect) - { - ref r{e, e.inputs, e.outputs}; - co_yield r; - } + return {effect[i].effect, effect[i].inputs, effect[i].outputs}; } - auto effects() + full_state_iterator full_state() { - return member_iterator_poly_effect{*this}; + return full_state_iterator{*this}; } + auto effects() { return member_iterator_poly_effect{*this}; } + member_iterator inputs() { for(auto& e : effect) @@ -497,13 +520,15 @@ struct effect_container [[no_unique_address]] avnd::dummy outputs; }; - member_iterator full_state() + + ref full_state(int i) { - for(T& e : effect) - { - ref r{e.effect, e.effect.inputs, avnd::dummy_instance}; - co_yield r; - } + return {effect[i].effect, effect[i].inputs, avnd::dummy_instance}; + } + + full_state_iterator full_state() + { + return full_state_iterator{*this}; } auto effects() diff --git a/include/avnd/wrappers/process/per_sample_arg.hpp b/include/avnd/wrappers/process/per_sample_arg.hpp index 0a776d67..75897272 100644 --- a/include/avnd/wrappers/process/per_sample_arg.hpp +++ b/include/avnd/wrappers/process/per_sample_arg.hpp @@ -94,7 +94,8 @@ struct process_adapter for(int c = 0; c < channels && effects_it != effects_range.end(); ++c, ++effects_it) { - auto& [impl, ins, outs] = *effects_it; + auto [impl, ins, outs] = *effects_it; + static_assert(std::is_reference_v); if constexpr(avnd::has_tick) { diff --git a/include/avnd/wrappers/process/per_sample_port.hpp b/include/avnd/wrappers/process/per_sample_port.hpp index ab08ac8c..8a9f5994 100644 --- a/include/avnd/wrappers/process/per_sample_port.hpp +++ b/include/avnd/wrappers/process/per_sample_port.hpp @@ -23,7 +23,7 @@ struct process_adapter // Here we know that we at least have one in and one out template - FP process_0(avnd::effect_container& implementation, FP in, auto& ref, auto&& tick) + FP process_0(avnd::effect_container& implementation, FP in, auto ref, auto&& tick) { auto& [fx, ins, outs] = ref; // Copy the input @@ -44,7 +44,7 @@ struct process_adapter } template - FP process_0(avnd::effect_container& implementation, FP in, auto& ref) + FP process_0(avnd::effect_container& implementation, FP in, auto ref) { auto& [fx, ins, outs] = ref; // Copy the input diff --git a/include/halp/audio.hpp b/include/halp/audio.hpp index bdb8781c..d0c8f731 100644 --- a/include/halp/audio.hpp +++ b/include/halp/audio.hpp @@ -53,6 +53,7 @@ struct fixed_audio_bus FP** samples{}; HALP_INLINE_FLATTEN operator FP**() const noexcept { return samples; } + HALP_INLINE_FLATTEN auto get() const noexcept { return *this; } HALP_INLINE_FLATTEN FP* operator[](int i) const noexcept { return samples[i]; } HALP_INLINE_FLATTEN avnd::span channel(std::size_t i, std::size_t frames) const noexcept @@ -71,6 +72,7 @@ struct dynamic_audio_bus_base int channels{}; HALP_INLINE_FLATTEN operator FP**() const noexcept { return samples; } + HALP_INLINE_FLATTEN auto get() const noexcept { return *this; } HALP_INLINE_FLATTEN FP* operator[](int i) const noexcept { return samples[i]; } HALP_INLINE_FLATTEN avnd::span channel(std::size_t i, std::size_t frames) const noexcept @@ -80,6 +82,15 @@ struct dynamic_audio_bus_base else return {}; } + + FP** begin() noexcept { return samples; } + FP** end() noexcept { return samples + channels; } + FP* const* begin() const noexcept { return samples; } + FP* const* end() const noexcept { return samples + channels; } + FP* const* cbegin() noexcept { return samples; } + FP* const* cend() noexcept { return samples + channels; } + FP* const* cbegin() const noexcept { return samples; } + FP* const* cend() const noexcept { return samples + channels; } }; template @@ -163,6 +174,7 @@ struct dynamic_audio_spectrum_bus int channels{}; HALP_INLINE_FLATTEN operator FP**() const noexcept { return samples; } + HALP_INLINE_FLATTEN auto get() const noexcept { return *this; } HALP_INLINE_FLATTEN FP* operator[](std::size_t i) const noexcept { return samples[i]; } HALP_INLINE_FLATTEN avnd::span channel(std::size_t i, std::size_t frames) const noexcept diff --git a/include/halp/controls_fmt.hpp b/include/halp/controls_fmt.hpp index 5530a996..4bf096f5 100644 --- a/include/halp/controls_fmt.hpp +++ b/include/halp/controls_fmt.hpp @@ -90,5 +90,20 @@ struct formatter> } }; +template +struct formatter> +{ + template + constexpr auto parse(ParseContext& ctx) const noexcept + { + return ctx.begin(); + } + + template + auto format(const halp::impulse_button_t&, FormatContext& ctx) const noexcept + { + return fmt::format_to(ctx.out(), "impulse: {}", T.value); + } +}; } #endif