Skip to content

Commit

Permalink
Fixes around spectrum analysis, added dot
Browse files Browse the repository at this point in the history
  • Loading branch information
sadko4u committed Dec 8, 2024
1 parent 257ba57 commit 69b9508
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 48 deletions.
15 changes: 12 additions & 3 deletions include/private/ui/referencer.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,13 @@ namespace lsp

size_t nBtnState;

lltl::parray<tk::GraphText> vVerText;
tk::GraphText *wHorText;
tk::Graph *wGraph;
tk::GraphAxis *wAxis;
tk::GraphText *wHorText;
tk::GraphAxis *wXAxis;
tk::GraphAxis *wYAxis;
tk::GraphDot *wMouseDot;
tk::GraphText *wMouseText;
lltl::parray<tk::GraphText> vVerText;
} fft_meters_t;

protected:
Expand All @@ -121,6 +124,10 @@ namespace lsp
protected:
static bool waveform_transform_func(float *dst, const float *src, size_t count, tk::GraphMesh::coord_t coord, void *data);
static float calc_zoom(waveform_t *wf, ssize_t x, ssize_t y, float accel);
static void sync_spectrum_freq_selector(fft_meters_t *fm, const ws::event_t *ev);
static void sync_spectrum_mouse_dot(fft_meters_t *fm, const ws::event_t *ev);
static bool fmt_note_name(tk::Widget *w, expr::Parameters *params, float freq);
static float log_relation(float v, float min, float max);

protected:
static status_t slot_matrix_change(tk::Widget *sender, void *ptr, void *data);
Expand All @@ -135,6 +142,8 @@ namespace lsp
static status_t slot_waveform_key_up(tk::Widget *sender, void *ptr, void *data);
static status_t slot_waveform_key_change(tk::Widget *sender, void *ptr, void *data, bool down);

static status_t slot_spectrum_mouse_in(tk::Widget *sender, void *ptr, void *data);
static status_t slot_spectrum_mouse_out(tk::Widget *sender, void *ptr, void *data);
static status_t slot_spectrum_mouse_down(tk::Widget *sender, void *ptr, void *data);
static status_t slot_spectrum_mouse_up(tk::Widget *sender, void *ptr, void *data);
static status_t slot_spectrum_mouse_move(tk::Widget *sender, void *ptr, void *data);
Expand Down
2 changes: 2 additions & 0 deletions res/main/i18n/default/lists.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"referencer": {
"display" : {
"dot_full": "{@frequency} Hz\n{@note}{@octave}{@cents}\n{@level_db%+.2f} dB",
"dot_unknown": "{@fft_frequency} Hz\n{@level_db%+.2f} dB",
"full" : "{@channel}\n{@frequency} Hz\n{@note}{@octave}{@cents}\n{@level_db%+.2f} dB",
"unknown" : "{@channel}\n{@fft_frequency} Hz\n{@level_db%+.2f} dB"
},
Expand Down
2 changes: 2 additions & 0 deletions res/main/i18n/ru/lists.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"referencer": {
"display" : {
"dot_full": "{@frequency} Hz\n{@note}{@octave}{@cents}\n{@level_db%+.2f} дБ",
"dot_unknown": "{@fft_frequency} Hz\n{@level_db%+.2f} дБ",
"full" : "{@channel}\n{@frequency} Гц\n{@note}{@octave}{@cents}\n{@level_db%+.2f} дБ",
"unknown" : "{@channel}\n{@fft_frequency} Гц\n{@level_db%+.2f} дБ"
},
Expand Down
2 changes: 2 additions & 0 deletions res/main/i18n/us/lists.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"referencer": {
"display" : {
"dot_full": "{@frequency} Hz\n{@note}{@octave}{@cents}\n{@level_db%+.2f} dB",
"dot_unknown": "{@fft_frequency} Hz\n{@level_db%+.2f} dB",
"full" : "{@channel}\n{@frequency} Hz\n{@note}{@octave}{@cents}\n{@level_db%+.2f} dB",
"unknown" : "{@channel}\n{@fft_frequency} Hz\n{@level_db%+.2f} dB"
},
Expand Down
13 changes: 9 additions & 4 deletions res/main/ui/utils/referencer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
<hbox spacing="4" expand="true">
<!-- Spectrum -->
<group ui:inject="GraphGroup" ipadding="0" text="lists.referencer.tab.spectrum" expand="true">
<graph ui:id="spectrum_graph" width.min="200" height.min="200" expand="true" fill="true">
<graph width.min="200" height.min="200" expand="true" fill="true">
<origin hpos="-1" vpos="-1" visibility="false"/>

<!-- Secondary grid -->
Expand Down Expand Up @@ -193,7 +193,7 @@
</ui:if>

<!-- Axis -->
<axis ui:id="spectrum_graph_ox" angle="0.0" min="10" max="24000" color="graph_prim" log="true" visibility="false"/>
<axis angle="0.0" min="10" max="24000" color="graph_prim" log="true" visibility="false"/>
<axis angle="0.5" min="-72 db" max="24 db" color="graph_prim" log="true" visibility="false"/>
<axis angle="0.5" min="-1" max="1" visibility="false"/>

Expand Down Expand Up @@ -1608,8 +1608,8 @@
<marker id="famhor" ox="1" oy="0" width="2" hwidth="2" editable="true" color="graph_marker_line" hcolor="graph_marker_line_hover" pointer="vsize" visibility=":famhorv"/>

<!-- Axis -->
<axis ui:id="spectrum_graph_ox" angle="0.0" min="10" max="24000" color="graph_prim" log="true" visibility="false"/>
<axis angle="0.5" min="-72 db" max="24 db" color="graph_prim" log="true" visibility="false"/>
<axis ui:id="freq_analysis_ox" angle="0.0" min="10" max="24000" color="graph_prim" log="true" visibility="false"/>
<axis ui:id="freq_analysis_oy" angle="0.5" min="-72 db" max="24 db" color="graph_prim" log="true" visibility="false"/>
<axis angle="0.5" min="-1" max="1" visibility="false"/>

<!-- Text -->
Expand Down Expand Up @@ -1658,6 +1658,11 @@
<!-- Horizontal line -->
<text ui:id="freq_analysis_hor" x="24000" y=":famhor" ox="0" oy="1" text="" color="graph_marker_line" halign="-1" valign="(:famhor lt -24 db) ? 1 : -1" visibility=":famhorv"/>

<!-- Measure dot -->
<dot ui:id="freq_analysis_mouse_dot" color="graph_prim" bcolor="graph_prim" visibility="false" />
<text ui:id="freq_analysis_mouse_text" padding="6"
bg="true" bg.color="#000000" bg.color.a="0.5" color="graph_prim"
text="MMM" text.halign="-1" valign="1" visibility="false" />
</graph>

<!-- Bottom menu -->
Expand Down
210 changes: 169 additions & 41 deletions src/main/ui/referencer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,12 @@ namespace lsp

fm->nBtnState = 0;

fm->wHorText = NULL;
fm->wGraph = NULL;
fm->wAxis = NULL;
fm->wHorText = NULL;
fm->wXAxis = NULL;
fm->wYAxis = NULL;
fm->wMouseDot = NULL;
fm->wMouseText = NULL;

bStereo = (strcmp(meta->uid, meta::referencer_stereo.uid) == 0);
}
Expand Down Expand Up @@ -274,13 +277,18 @@ namespace lsp

fm->wGraph = pWrapper->controller()->widgets()->get<tk::Graph>("spectrum_graph");
fm->wHorText = pWrapper->controller()->widgets()->get<tk::GraphText>("freq_analysis_hor");
fm->wAxis = pWrapper->controller()->widgets()->get<tk::GraphAxis>("spectrum_graph_ox");
fm->wXAxis = pWrapper->controller()->widgets()->get<tk::GraphAxis>("freq_analysis_ox");
fm->wYAxis = pWrapper->controller()->widgets()->get<tk::GraphAxis>("freq_analysis_oy");
fm->wMouseDot = pWrapper->controller()->widgets()->get<tk::GraphDot>("freq_analysis_mouse_dot");
fm->wMouseText = pWrapper->controller()->widgets()->get<tk::GraphText>("freq_analysis_mouse_text");

for (const char * const * pm = (bStereo) ? ver_meters_stereo : ver_meters_mono; *pm != NULL; ++pm)
fm->vVerText.add(pWrapper->controller()->widgets()->get<tk::GraphText>(*pm));

if (fm->wGraph != NULL)
{
fm->wGraph->slots()->bind(tk::SLOT_MOUSE_IN, slot_spectrum_mouse_in, this);
fm->wGraph->slots()->bind(tk::SLOT_MOUSE_OUT, slot_spectrum_mouse_out, this);
fm->wGraph->slots()->bind(tk::SLOT_MOUSE_DOWN, slot_spectrum_mouse_down, this);
fm->wGraph->slots()->bind(tk::SLOT_MOUSE_UP, slot_spectrum_mouse_up, this);
fm->wGraph->slots()->bind(tk::SLOT_MOUSE_MOVE, slot_spectrum_mouse_move, this);
Expand Down Expand Up @@ -452,6 +460,41 @@ namespace lsp
return "mix_mid";
}

bool referencer_ui::fmt_note_name(tk::Widget *w, expr::Parameters *params, float freq)
{
float note_full = dspu::frequency_to_note(freq);
if (note_full == dspu::NOTE_OUT_OF_RANGE)
return false;

LSPString text;
tk::prop::String snote;
snote.bind(w->style(), w->display()->dictionary());

note_full += 0.5f;
ssize_t note_number = ssize_t(note_full);

// Note name
ssize_t note = note_number % 12;
text.fmt_ascii("lists.notes.names.%s", note_names[note]);
snote.set(&text);
snote.format(&text);
params->set_string("note", &text);

// Octave number
ssize_t octave = (note_number / 12) - 1;
params->set_int("octave", octave);

// Cents
ssize_t note_cents = (note_full - float(note_number)) * 100 - 50;
if (note_cents < 0)
text.fmt_ascii(" - %02d", -note_cents);
else
text.fmt_ascii(" + %02d", note_cents);
params->set_string("cents", &text);

return true;
}

void referencer_ui::sync_meter_state(ui::IPort *port)
{
fft_meters_t *fm = &sFftMeters;
Expand Down Expand Up @@ -481,15 +524,15 @@ namespace lsp
// Update the note name displayed in the text
// Fill the parameters
expr::Parameters params;
tk::prop::String snote;
tk::prop::String schannel;
LSPString text;
snote.bind(ver_text->style(), pDisplay->dictionary());
schannel.bind(ver_text->style(), pDisplay->dictionary());
SET_LOCALE_SCOPED(LC_NUMERIC, "C");

// Channels
text.fmt_ascii("lists.referencer.fft.%s", get_channel_key(channel));
snote.set(&text);
snote.format(&text);
schannel.set(&text);
schannel.format(&text);
params.set_string("channel", &text);

// Frequency
Expand All @@ -501,33 +544,8 @@ namespace lsp
params.set_float("level_db", dspu::gain_to_db(level));

// Note
float note_full = dspu::frequency_to_note(freq);
if (note_full != dspu::NOTE_OUT_OF_RANGE)
{
note_full += 0.5f;
ssize_t note_number = ssize_t(note_full);

// Note name
ssize_t note = note_number % 12;
text.fmt_ascii("lists.notes.names.%s", note_names[note]);
snote.set(&text);
snote.format(&text);
params.set_string("note", &text);

// Octave number
ssize_t octave = (note_number / 12) - 1;
params.set_int("octave", octave);

// Cents
ssize_t note_cents = (note_full - float(note_number)) * 100 - 50;
if (note_cents < 0)
text.fmt_ascii(" - %02d", -note_cents);
else
text.fmt_ascii(" + %02d", note_cents);
params.set_string("cents", &text);

if (fmt_note_name(ver_text, &params, freq))
ver_text->text()->set("lists.referencer.display.full", &params);
}
else
ver_text->text()->set("lists.referencer.display.unknown", &params);
}
Expand Down Expand Up @@ -881,6 +899,41 @@ namespace lsp
return STATUS_OK;
}

status_t referencer_ui::slot_spectrum_mouse_in(tk::Widget *sender, void *ptr, void *data)
{
referencer_ui *self = static_cast<referencer_ui *>(ptr);
if (self == NULL)
return STATUS_OK;

const ws::event_t *ev = static_cast<ws::event_t *>(data);
if (data == NULL)
return STATUS_OK;

fft_meters_t *fm = &self->sFftMeters;
if (fm->wMouseDot != NULL)
fm->wMouseDot->visibility()->set(true);
if (fm->wMouseText != NULL)
fm->wMouseText->visibility()->set(true);
sync_spectrum_mouse_dot(fm, ev);

return STATUS_OK;
}

status_t referencer_ui::slot_spectrum_mouse_out(tk::Widget *sender, void *ptr, void *data)
{
referencer_ui *self = static_cast<referencer_ui *>(ptr);
if (self == NULL)
return STATUS_OK;

fft_meters_t *fm = &self->sFftMeters;
if (fm->wMouseDot != NULL)
fm->wMouseDot->visibility()->set(false);
if (fm->wMouseText != NULL)
fm->wMouseText->visibility()->set(false);

return STATUS_OK;
}

status_t referencer_ui::slot_spectrum_mouse_down(tk::Widget *sender, void *ptr, void *data)
{
referencer_ui *self = static_cast<referencer_ui *>(ptr);
Expand All @@ -892,7 +945,8 @@ namespace lsp

fft_meters_t *fm = &self->sFftMeters;
fm->nBtnState |= (size_t(1) << ev->nCode);
slot_spectrum_mouse_move(sender, ptr, data);

sync_spectrum_freq_selector(fm, ev);

return STATUS_OK;
}
Expand Down Expand Up @@ -922,26 +976,100 @@ namespace lsp
return STATUS_OK;

fft_meters_t *fm = &self->sFftMeters;

sync_spectrum_freq_selector(fm, ev);
sync_spectrum_mouse_dot(fm, ev);

return STATUS_OK;
}

void referencer_ui::sync_spectrum_freq_selector(fft_meters_t *fm, const ws::event_t *ev)
{
if (fm->nBtnState != (size_t(1) << ws::MCB_LEFT))
return STATUS_OK;
if ((fm->wGraph == NULL) || (fm->wAxis == NULL) || (fm->pVerFreq == NULL))
return STATUS_OK;
return;
if ((fm->wGraph == NULL) || (fm->wXAxis == NULL) || (fm->pVerFreq == NULL))
return;

// Translate coordinates
const ssize_t index = fm->wGraph->indexof_axis(fm->wAxis);
const ssize_t index = fm->wGraph->indexof_axis(fm->wXAxis);
if (index < 0)
return STATUS_OK;
return;

float freq = 0.0f;
if (fm->wGraph->xy_to_axis(index, &freq, ev->nLeft, ev->nTop) != STATUS_OK)
return STATUS_OK;;
return;

lsp_trace("Spectrum Graph apply: x=%d, y=%d, freq=%.2f", ev->nLeft, ev->nTop, freq);

fm->pVerFreq->set_value(freq);
fm->pVerFreq->notify_all(ui::PORT_USER_EDIT);
}

return STATUS_OK;
float referencer_ui::log_relation(float v, float min, float max)
{
v = (min < max) ? lsp_limit(v, min, max) : lsp_limit(v, max, min);
return logf(v/min) / logf(max/min);
}

void referencer_ui::sync_spectrum_mouse_dot(fft_meters_t *fm, const ws::event_t *ev)
{
if ((fm->wGraph == NULL) || (fm->wXAxis == NULL) || (fm->wYAxis == NULL))
return;

// Translate coordinates
const ssize_t xindex = fm->wGraph->indexof_axis(fm->wXAxis);
if (xindex < 0)
return;

const ssize_t yindex = fm->wGraph->indexof_axis(fm->wYAxis);
if (yindex < 0)
return;

float freq = 0.0f;
if (fm->wGraph->xy_to_axis(xindex, &freq, ev->nLeft, ev->nTop) != STATUS_OK)
return;

float level = 0.0f;
if (fm->wGraph->xy_to_axis(yindex, &level, ev->nLeft, ev->nTop) != STATUS_OK)
return;

lsp_trace("freq = %f, level = %f", freq, level);

// Set dot coordinates
if (fm->wMouseDot != NULL)
{
fm->wMouseDot->hvalue()->set_all(freq, SPEC_FREQ_MIN, SPEC_FREQ_MAX);
fm->wMouseDot->vvalue()->set_all(level, GAIN_AMP_M_INF_DB, GAIN_AMP_P_24_DB);
}

// Set text coordinates, value and alignment
if (fm->wMouseText != NULL)
{
fm->wMouseText->hvalue()->set(freq);
fm->wMouseText->vvalue()->set(level);
fm->wMouseText->layout()->set_halign(
(freq > 10000.0f) ? 1.0f - 2.0f * log_relation(freq, 10000.0f, SPEC_FREQ_MAX) : 1.0f);
fm->wMouseText->layout()->set_valign(
(level > GAIN_AMP_P_12_DB) ? 1.0f - 2.0f * log_relation(level, GAIN_AMP_P_12_DB, GAIN_AMP_P_24_DB) : 1.0f);
fm->wMouseText->text_layout()->set_halign(
(freq > 10000.0f) ? 2.0f * log_relation(freq, 10000.0f, SPEC_FREQ_MAX) - 1.0f : -1.0f);

// Frequency
expr::Parameters params;
LSPString text;
text.fmt_ascii("%.2f", freq);
params.set_string("frequency", &text);

// Gain Level
params.set_float("level", level);
params.set_float("level_db", dspu::gain_to_db(level));

// Note
if (fmt_note_name(fm->wMouseText, &params, freq))
fm->wMouseText->text()->set("lists.referencer.display.dot_full", &params);
else
fm->wMouseText->text()->set("lists.referencer.display.dot_unknown", &params);
}
}

} /* namespace plugins */
Expand Down

0 comments on commit 69b9508

Please sign in to comment.