diff --git a/Amuencha/AmuenchaModel.hpp b/Amuencha/AmuenchaModel.hpp index 417509f..a8034f9 100644 --- a/Amuencha/AmuenchaModel.hpp +++ b/Amuencha/AmuenchaModel.hpp @@ -24,6 +24,15 @@ public: halp::hslider_i32<"Max", halp::range{.min = 0, .max = 127, .init = 72}> max; } inputs; + // This one will be memcpy'd as it is a trivial type + struct processor_to_ui + { + int min; + int max; + }; + + std::function send_message; + struct outs { halp::midi_bus<"Output"> midi; diff --git a/Amuencha/AmuenchaUi.hpp b/Amuencha/AmuenchaUi.hpp index c970491..08ebc75 100644 --- a/Amuencha/AmuenchaUi.hpp +++ b/Amuencha/AmuenchaUi.hpp @@ -26,10 +26,19 @@ struct Analyser::ui { halp_meta(layout, halp::layouts::vbox) halp_meta(background, halp::colors::mid) - halp_meta(width, 400) - halp_meta(height, 400) + halp_meta(width, 500) + halp_meta(height, 500) halp::custom_actions_item widget{.x = 0, .y = 0}; } spiral; + + // Define the communication between UI and processor. + struct bus + { + // Receive a message on the UI thread from the processing thread + static void process_message(ui& self, processor_to_ui msg) + { + } + }; }; } diff --git a/Amuencha/SpiralDisplay.cpp b/Amuencha/SpiralDisplay.cpp index a216183..1e69579 100644 --- a/Amuencha/SpiralDisplay.cpp +++ b/Amuencha/SpiralDisplay.cpp @@ -4,7 +4,9 @@ Amuencha::SpiralDisplay::SpiralDisplay() : min_midi_note{24} , max_midi_note{72} { - for (int i{0}; i < 12; i++) note_positions[i] = polar(.80f, half_pi - i * two_pi / 12); + for (int i{0}; i < 12; i++) note_positions[i] = std::polar(.9f, half_pi - i * two_pi / 12); + + display_spectrum.resize(num_ID); } void Amuencha::SpiralDisplay::compute_frequencies() @@ -50,7 +52,7 @@ void Amuencha::SpiralDisplay::compute_frequencies() display_bins[b] = exp2(log2_fmin + (log2_fmax - log2_fmin) * bratio); spiral_r_a[b].r = rmin + (rmax - rmin) * bratio; spiral_r_a[b].a = theta_min + (theta_max - theta_min) * bratio; - spiral_positions[b] = polar(spiral_r_a[b].r, spiral_r_a[b].a); + spiral_positions[b] = std::polar(spiral_r_a[b].r, spiral_r_a[b].a); } // repeat one more time to avoid a second for loops @@ -58,7 +60,7 @@ void Amuencha::SpiralDisplay::compute_frequencies() display_bins[num_bins] = exp2(log2_fmin + (log2_fmax - log2_fmin) * bratio); spiral_r_a[num_bins].r = rmin + (rmax - rmin) * bratio; spiral_r_a[num_bins].a = theta_min + (theta_max - theta_min) * bratio; - spiral_positions[num_bins] = polar(spiral_r_a[num_bins].r, spiral_r_a[num_bins].a); + spiral_positions[num_bins] = std::polar(spiral_r_a[num_bins].r, spiral_r_a[num_bins].a); for (int b{0}; b < num_bins; ++b) bin_sizes[b] = display_bins[b + 1] - display_bins[b]; diff --git a/Amuencha/SpiralDisplay.hpp b/Amuencha/SpiralDisplay.hpp index 985cf4a..4639578 100644 --- a/Amuencha/SpiralDisplay.hpp +++ b/Amuencha/SpiralDisplay.hpp @@ -10,26 +10,29 @@ namespace Amuencha { using namespace boost::math::float_constants; -using namespace std; +using namespace avnd; struct SpiralDisplay { SpiralDisplay(); - static consteval int width() { return 400; } - static consteval int height() { return 400; } + static consteval int width() { return 500; } + static consteval int height() { return 500; } void paint(avnd::painter auto ctx) { half = height() * .5f; + if (display_bins.empty()) + compute_frequencies(); + for (int i{0}; i < 12; i++) { ctx.move_to(half, half); ctx.line_to(x(note_positions[i].real()), y(note_positions[i].imag())); - ctx.draw_text(x(note_positions[i].real() * 1.1 - .02), - y(note_positions[i].imag() * 1.1 - .01), + ctx.draw_text(x(note_positions[i].real() * 1.05 - .02), + y(note_positions[i].imag() * 1.05 - .01), note_names[i]); } @@ -43,24 +46,34 @@ struct SpiralDisplay for (int b{0}; b < display_spectrum[id].size(); ++b) { - float amplitude = 0.8 / num_octaves * min(1.f, display_spectrum[id][b] * gain); + float amplitude = 0.8 / num_octaves * std::min(1.f, display_spectrum[id][b] * gain); //if (display_spectrum[id][b]>0) cout << display_spectrum[id][b] << endl; // power normalised between 0 and 1 => 0.1 = spiral branch float r = spiral_r_a[b].r + amplitude; - auto p = polar(r, spiral_r_a[b].a); + auto p = std::polar(r, spiral_r_a[b].a); ctx.line_to(x(p.real()), y(p.imag())); r = spiral_r_a[b + 1].r + amplitude; - p = polar(r, spiral_r_a[b + 1].a); + p = std::polar(r, spiral_r_a[b + 1].a); ctx.line_to(x(p.real()), y(p.imag())); } - for (int b{static_cast(spiral_positions.size()) - 1}; b >= 0; --b) + for (int b = spiral_positions.size() - 1; b >= 0; --b) ctx.line_to(x(spiral_positions[b].real()), y(spiral_positions[b].imag())); } + + // Overlay the base spiral in black + // if (base_spiral.isEmpty()) { + ctx.move_to(x(spiral_positions.back().real()), y(spiral_positions.back().imag())); + for (int b = spiral_positions.size() - 1; b >= 0; --b) + ctx.line_to(x(spiral_positions[b].real()), y(spiral_positions[b].imag())); + //base_spiral = base_spiral.simplified(); + // } + + ctx.stroke(); } private: - static const constexpr string_view note_names[12] + static const constexpr std::string_view note_names[12] {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; static const int num_ID = 2; @@ -76,7 +89,7 @@ private: // static const constexpr array, 12> note_positions{inti_pos()}; - array, 12> note_positions{}; + std::array, 12> note_positions{}; // central frequencies (log space) std::vector frequencies; diff --git a/README.md b/README.md index cd5ec83..478bf3f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,17 @@ # Amuencha -A new and wonderful [ossia score](https://ossia.io) add-on +An [ossia score](https://ossia.io) add-on cloned from the [avendish template](https://github.com/ossia-templates/score-avnd-simple-template)\ +It aims at porting Nicolas Brodu's [frequency analyzer](https://nicolas.brodu.net/en/programmation/amuencha/index.html) to Avendish + +## Features + +* Draw background spiral and notes axis + +## TODO + +* Visualisation + - [ ] Redraw with min and max midi value + - [ ] Rimplement all draw function without storing painters +* Port Backend analyzer +* Additional features + - [ ] Midi output + - [ ] audio output per frequency band