[ui] draw base spiral
This commit is contained in:
parent
705b5d9404
commit
bf657b668b
5 changed files with 65 additions and 17 deletions
|
@ -24,6 +24,15 @@ public:
|
||||||
halp::hslider_i32<"Max", halp::range{.min = 0, .max = 127, .init = 72}> max;
|
halp::hslider_i32<"Max", halp::range{.min = 0, .max = 127, .init = 72}> max;
|
||||||
} inputs;
|
} inputs;
|
||||||
|
|
||||||
|
// This one will be memcpy'd as it is a trivial type
|
||||||
|
struct processor_to_ui
|
||||||
|
{
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::function<void(processor_to_ui)> send_message;
|
||||||
|
|
||||||
struct outs
|
struct outs
|
||||||
{
|
{
|
||||||
halp::midi_bus<"Output"> midi;
|
halp::midi_bus<"Output"> midi;
|
||||||
|
|
|
@ -26,10 +26,19 @@ struct Analyser::ui
|
||||||
{
|
{
|
||||||
halp_meta(layout, halp::layouts::vbox)
|
halp_meta(layout, halp::layouts::vbox)
|
||||||
halp_meta(background, halp::colors::mid)
|
halp_meta(background, halp::colors::mid)
|
||||||
halp_meta(width, 400)
|
halp_meta(width, 500)
|
||||||
halp_meta(height, 400)
|
halp_meta(height, 500)
|
||||||
|
|
||||||
halp::custom_actions_item<SpiralDisplay> widget{.x = 0, .y = 0};
|
halp::custom_actions_item<SpiralDisplay> widget{.x = 0, .y = 0};
|
||||||
} spiral;
|
} 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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,9 @@ Amuencha::SpiralDisplay::SpiralDisplay()
|
||||||
: min_midi_note{24}
|
: min_midi_note{24}
|
||||||
, max_midi_note{72}
|
, 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()
|
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);
|
display_bins[b] = exp2(log2_fmin + (log2_fmax - log2_fmin) * bratio);
|
||||||
spiral_r_a[b].r = rmin + (rmax - rmin) * bratio;
|
spiral_r_a[b].r = rmin + (rmax - rmin) * bratio;
|
||||||
spiral_r_a[b].a = theta_min + (theta_max - theta_min) * 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
|
// 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);
|
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].r = rmin + (rmax - rmin) * bratio;
|
||||||
spiral_r_a[num_bins].a = theta_min + (theta_max - theta_min) * 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)
|
for (int b{0}; b < num_bins; ++b)
|
||||||
bin_sizes[b] = display_bins[b + 1] - display_bins[b];
|
bin_sizes[b] = display_bins[b + 1] - display_bins[b];
|
||||||
|
|
|
@ -10,26 +10,29 @@
|
||||||
namespace Amuencha
|
namespace Amuencha
|
||||||
{
|
{
|
||||||
using namespace boost::math::float_constants;
|
using namespace boost::math::float_constants;
|
||||||
using namespace std;
|
using namespace avnd;
|
||||||
|
|
||||||
struct SpiralDisplay
|
struct SpiralDisplay
|
||||||
{
|
{
|
||||||
SpiralDisplay();
|
SpiralDisplay();
|
||||||
|
|
||||||
static consteval int width() { return 400; }
|
static consteval int width() { return 500; }
|
||||||
static consteval int height() { return 400; }
|
static consteval int height() { return 500; }
|
||||||
|
|
||||||
void paint(avnd::painter auto ctx)
|
void paint(avnd::painter auto ctx)
|
||||||
{
|
{
|
||||||
half = height() * .5f;
|
half = height() * .5f;
|
||||||
|
|
||||||
|
if (display_bins.empty())
|
||||||
|
compute_frequencies();
|
||||||
|
|
||||||
for (int i{0}; i < 12; i++)
|
for (int i{0}; i < 12; i++)
|
||||||
{
|
{
|
||||||
ctx.move_to(half, half);
|
ctx.move_to(half, half);
|
||||||
ctx.line_to(x(note_positions[i].real()),
|
ctx.line_to(x(note_positions[i].real()),
|
||||||
y(note_positions[i].imag()));
|
y(note_positions[i].imag()));
|
||||||
ctx.draw_text(x(note_positions[i].real() * 1.1 - .02),
|
ctx.draw_text(x(note_positions[i].real() * 1.05 - .02),
|
||||||
y(note_positions[i].imag() * 1.1 - .01),
|
y(note_positions[i].imag() * 1.05 - .01),
|
||||||
note_names[i]);
|
note_names[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,24 +46,34 @@ struct SpiralDisplay
|
||||||
|
|
||||||
for (int b{0}; b < display_spectrum[id].size(); ++b)
|
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;
|
//if (display_spectrum[id][b]>0) cout << display_spectrum[id][b] << endl;
|
||||||
// power normalised between 0 and 1 => 0.1 = spiral branch
|
// power normalised between 0 and 1 => 0.1 = spiral branch
|
||||||
float r = spiral_r_a[b].r + amplitude;
|
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()));
|
ctx.line_to(x(p.real()), y(p.imag()));
|
||||||
r = spiral_r_a[b + 1].r + amplitude;
|
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()));
|
ctx.line_to(x(p.real()), y(p.imag()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int b{static_cast<int>(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()));
|
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:
|
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"};
|
{"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
|
||||||
|
|
||||||
static const int num_ID = 2;
|
static const int num_ID = 2;
|
||||||
|
@ -76,7 +89,7 @@ private:
|
||||||
|
|
||||||
// static const constexpr array<complex<float>, 12> note_positions{inti_pos()};
|
// static const constexpr array<complex<float>, 12> note_positions{inti_pos()};
|
||||||
|
|
||||||
array<complex<float>, 12> note_positions{};
|
std::array<std::complex<float>, 12> note_positions{};
|
||||||
|
|
||||||
// central frequencies (log space)
|
// central frequencies (log space)
|
||||||
std::vector<float> frequencies;
|
std::vector<float> frequencies;
|
||||||
|
|
17
README.md
17
README.md
|
@ -1,2 +1,17 @@
|
||||||
# Amuencha
|
# 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
|
||||||
|
|
Loading…
Add table
Reference in a new issue