Skip to content

Commit

Permalink
Reset roundtrip measurement when scip capture, some UI refines
Browse files Browse the repository at this point in the history
  • Loading branch information
brummer10 committed Sep 4, 2023
1 parent 005f875 commit b9f6de5
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 79 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ A Neural Recorder plug to make the process of cloning external soft/hardware a b

![NeuralRecord](https://github.com/brummer10/neuralrecord/blob/main/NeuralRecord.png?raw=true)

Features a round trip measurement routine.
This allows to load the plug, connect the output to the system output,
loop over external gear (soft or hardware) and back to the Recorder input.

Simply press "Capture" to play the "input.wav" file to the output and record the returning input
delayed by the measured round trip latency.

Resulting recorded "target.wav" file will be perfectly in sync with the used "input.wav" file.
Currently, both files would be saved under "$(HOME)/profiles/".
The "target.wav" file will be overwritten on each Capture run, so there will be always only one target file.
You need to upload it from the device in order to use it with the AIDA-X or NAM trainer.

The "input.wav" file comes as resource with the plug (hence the big size of the binary packages) and get copied over to that folder,
when no input.wav file was found there.
This allows advanced users to use their own input.wav file by simply replace the one in that folder.

The target.wav file get checked during record and run to a normalisation function when needed.
(Only when the max peek in target is above the max peek in input).

The record will be saved in the PCM24 wav format (same as the input.wav file).

## Formats

Expand Down
92 changes: 42 additions & 50 deletions plugins/NeuralRecord/CairoWidgets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define CAIROWIDGETS_H

#include <functional>
#include <atomic>
#include "Cairo.hpp"
#include "extra/Runner.hpp"

Expand Down Expand Up @@ -109,24 +110,28 @@ class CairoShadows

};

// -----------------------------------------------------------------------

class CairoButton : public CairoSubWidget, public CairoShadows
{
public:
explicit CairoButton(SubWidget* const parent, const char* lab, std::function<void(const uint32_t , float) > setParameterValue_)
explicit CairoButton(SubWidget* const parent, const char* lab, const uint32_t index,
std::function<void(const uint32_t , float) > setParameterValue_)
: CairoSubWidget(parent),
setParameterValue(setParameterValue_) {
label = lab;
setParameterValue(setParameterValue_),
label(lab), port(index) {
value = 0.0f;
state = 0;
}
}

explicit CairoButton(TopLevelWidget* const parent, const char* lab, std::function<void(const uint32_t, float) > setParameterValue_)
explicit CairoButton(TopLevelWidget* const parent, const char* lab, const uint32_t index,
std::function<void(const uint32_t, float) > setParameterValue_)
: CairoSubWidget(parent),
setParameterValue(setParameterValue_) {
label = lab;
setParameterValue(setParameterValue_),
label(lab), port(index) {
value = 0.0f;
state = 0;
}
}

void setValue(float v)
{
Expand All @@ -136,7 +141,6 @@ class CairoButton : public CairoSubWidget, public CairoShadows
}

protected:

void onCairoDisplay(const CairoGraphicsContext& context) override
{
cairo_t* const cr = context.handle;
Expand All @@ -156,7 +160,7 @@ class CairoButton : public CairoSubWidget, public CairoShadows
if (!state)
boxShadowOutset(cr, w, h);
else
boxShadowInset(cr, w, h);
boxShadowInset(cr, w, h);

float offset = 0.0;
cairo_text_extents_t extents;
Expand All @@ -182,17 +186,11 @@ class CairoButton : public CairoSubWidget, public CairoShadows
{
if (!event.press)
{
const int w = getWidth();
const int h = getHeight();
const int mx = event.pos.getX();
const int my = event.pos.getY();

// inside
if (mx >= 0 && my >= 0 && mx < w && my < h)
if (contains(event.pos))
{
value = value ? 0.0f : 1.0f;
state = !state;
setParameterValue(0, value);
setParameterValue(port, value);
repaint();
}
}
Expand All @@ -201,11 +199,11 @@ class CairoButton : public CairoSubWidget, public CairoShadows
}

private:

std::function<void(const uint32_t, float) > setParameterValue;
float value;
uint state;
const char* label;
const uint32_t port;
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CairoButton)
};

Expand All @@ -217,12 +215,12 @@ class CairoProgressBar : public CairoSubWidget, public CairoShadows
explicit CairoProgressBar(SubWidget* const parent)
: CairoSubWidget(parent) {
value = 0.0f;
}
}

explicit CairoProgressBar(TopLevelWidget* const parent)
: CairoSubWidget(parent) {
value = 0.0f;
}
}

void setValue(float v)
{
Expand All @@ -231,7 +229,6 @@ class CairoProgressBar : public CairoSubWidget, public CairoShadows
}

protected:

void onCairoDisplay(const CairoGraphicsContext& context) override
{
cairo_t* const cr = context.handle;
Expand All @@ -255,7 +252,7 @@ class CairoProgressBar : public CairoSubWidget, public CairoShadows
char s[64];
snprintf(s, 63,"%d%%", (int) (value * 100.0));
cairo_text_extents(cr,s , &extents);
cairo_move_to (cr, width * 0.5-extents.width * 0.5, height * 0.5 + extents.height * 0.5 );
cairo_move_to (cr, width * 0.5 - extents.width * 0.5, height * 0.5 + extents.height * 0.5 );
cairo_set_source_rgba(cr, 0.63, 0.63, 0.63, 1.0);
cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
cairo_show_text(cr, s);
Expand All @@ -276,25 +273,21 @@ class CairoProgressBar : public CairoSubWidget, public CairoShadows
class CairoPeekMeter : public CairoSubWidget, public CairoShadows
{
public:
explicit CairoPeekMeter(SubWidget* const parent, int w, int h)
explicit CairoPeekMeter(SubWidget* const parent)
: CairoSubWidget(parent),
image(nullptr) {
old_value = -70.0f;
std_value = -70.0f;
value = -70.0f;
setSize(w, h);
drawMeterImage(w, h * 0.5);
}
}

explicit CairoPeekMeter(TopLevelWidget* const parent, int w, int h)
explicit CairoPeekMeter(TopLevelWidget* const parent)
: CairoSubWidget(parent),
image(nullptr) {
old_value = -70.0f;
std_value = -70.0f;
value = -70.0f;
setSize(w, h);
drawMeterImage(w, h * 0.5);
}
}

void setValue(float v)
{
Expand All @@ -307,7 +300,6 @@ class CairoPeekMeter : public CairoSubWidget, public CairoShadows
}

protected:

float power2db(float power)
{
const float falloff = 27 * 60 * 0.0005;
Expand Down Expand Up @@ -499,38 +491,38 @@ class CairoToolTip : public CairoSubWidget, public Runner
public:
explicit CairoToolTip(SubWidget* const parent_, const char* lab)
: CairoSubWidget(parent_),
parent(parent_) {
label = lab;
parent(parent_), label(lab) {
hide();
state = 0;
}
state.store(false, std::memory_order_release);
}

explicit CairoToolTip(TopLevelWidget* const parent_, const char* lab)
: CairoSubWidget(parent_),
parent(parent_) {
label = lab;
parent(parent_), label(lab) {
hide();
state = 0;
}
state.store(false, std::memory_order_release);
}

~CairoToolTip() {if (isRunnerActive()) stopRunner();}

void setLabel(const char* lab)
{
label = lab;
show();
state.store(false, std::memory_order_release);
if (!isRunnerActive()) {
if (!isVisible()) show();
startRunner(2500);
}
repaint();
if (!isRunnerActive()) startRunner(2500);
}

void unset()
{
hide();
if (isVisible()) hide();
parent->repaint();
}

protected:

void onCairoDisplay(const CairoGraphicsContext& context) override
{
cairo_t* const cr = context.handle;
Expand All @@ -547,7 +539,7 @@ class CairoToolTip : public CairoSubWidget, public Runner
cairo_stroke(cr);
cairo_text_extents_t extents;
cairo_set_source_rgba(cr, 0.63, 0.63, 0.63, 1.0);
cairo_set_font_size (cr, h * 0.26);
cairo_set_font_size (cr, h * 0.24);
cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_BOLD);
cairo_text_extents(cr, label , &extents);
Expand All @@ -561,20 +553,20 @@ class CairoToolTip : public CairoSubWidget, public Runner

bool run() override
{
if (state) {
state = 0;
if (state.load(std::memory_order_acquire)) {
state.store(false, std::memory_order_release);
unset();
return false;
} else {
state = 1;
state.store(true, std::memory_order_release);
return true;
}
}

private:
Widget* parent;
Widget * const parent;
const char* label;
uint state;
std::atomic<bool> state;
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CairoToolTip)
};

Expand Down
2 changes: 1 addition & 1 deletion plugins/NeuralRecord/PluginNeuralCapture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class PluginNeuralCapture : public Plugin {
}

uint32_t getVersion() const noexcept override {
return d_version(0, 1, 0);
return d_version(0, 1, 3);
}

// Go to:
Expand Down
67 changes: 41 additions & 26 deletions plugins/NeuralRecord/UINeuralCapture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ START_NAMESPACE_DISTRHO
// Init / Deinit

UINeuralCapture::UINeuralCapture()
: UI(350, 250) {
: UI(350, 250, true) {
kInitialHeight = 250;
kInitialWidth = 350;
fButton = new CairoButton(this, "Capture",
sizeGroup = new UiSizeGroup(kInitialWidth, kInitialHeight);
getPathInfo(pathInfo);

fButton = new CairoButton(this, "Capture", PluginNeuralCapture::paramButton,
[this] (const uint32_t index, float value) {this->setParameterValue(index, value);});
fButton->setSize(200, 50);
fButton->setAbsolutePos(75, 30);
sizeGroup->addToSizeGroup(fButton, 75, 30, 200, 50);

fProgressBar = new CairoProgressBar(this);
fProgressBar->setSize(200, 30);
fProgressBar->setAbsolutePos(75, 105);
sizeGroup->addToSizeGroup(fProgressBar, 75, 105, 200, 30);

fPeekMeter = new CairoPeekMeter(this, 200, 50);
fPeekMeter->setAbsolutePos(75, 160);
fPeekMeter = new CairoPeekMeter(this);
sizeGroup->addToSizeGroup(fPeekMeter, 75, 160, 200, 50);

fToolTip = new CairoToolTip(this, "This is a Error Message");
fToolTip->setSize(350, 50);
fToolTip->setAbsolutePos(0, 105);
fToolTip = new CairoToolTip(this, "This is a Message");
sizeGroup->addToSizeGroup(fToolTip, 0, 95, 350, 50);

setGeometryConstraints(kInitialWidth, kInitialHeight, true);
}
Expand All @@ -58,6 +58,8 @@ void UINeuralCapture::parameterChanged(uint32_t index, float value) {
if (value >=1.0) {
fButton->setValue(0.0f);
setParameterValue(PluginNeuralCapture::paramButton, 0.0f);
} else if (value > 0.9969) {
fToolTip->setLabel(pathInfo.c_str());
}
break;
case PluginNeuralCapture::paramMeter:
Expand Down Expand Up @@ -101,6 +103,33 @@ void UINeuralCapture::sampleRateChanged(double newSampleRate) {
// -----------------------------------------------------------------------
// Optional UI callbacks

/**
Get the path were recording been saved
*/

void UINeuralCapture::getPathInfo(std::string &pInfo)
{
pInfo = "Saved to: ";
#ifndef __MOD_DEVICES__
#if defined(WIN32) || defined(_WIN32)
pInfo += getenv("USERPROFILE");
if (pInfo.empty()) {
pInfo += getenv("HOMEDRIVE");
pInfo += getenv("HOMEPATH");
}
#else
pInfo += getenv("HOME");
#endif
pInfo +=PATH_SEPARATOR;
pInfo +="profiles";
pInfo +=PATH_SEPARATOR;
#else
pInfo += "/data/user-files/Audio Recordings/profiles/";
#endif
pInfo += "target.wav";
}


/**
Idle callback.
This function is called at regular intervals.
Expand Down Expand Up @@ -139,21 +168,7 @@ void UINeuralCapture::onCairoDisplay(const CairoGraphicsContext& context) {
void UINeuralCapture::onResize(const ResizeEvent& ev)
{
UI::onResize(ev);
const float scaleHFactor = static_cast<float>(ev.size.getHeight())/static_cast<float>(kInitialHeight);
const float scaleWFactor = static_cast<float>(ev.size.getWidth())/static_cast<float>(kInitialWidth);
const float scaleFactor = scaleHFactor < scaleWFactor ? scaleHFactor : scaleWFactor;

fButton->setSize(200*scaleFactor, 50*scaleFactor);
fButton->setAbsolutePos(75*scaleWFactor, 30*scaleHFactor);

fProgressBar->setSize(200*scaleFactor, 30*scaleFactor);
fProgressBar->setAbsolutePos(75*scaleWFactor, 105*scaleHFactor);

fPeekMeter->setSize( 200*scaleFactor, 50*scaleFactor);
fPeekMeter->setAbsolutePos(75*scaleWFactor, 160*scaleHFactor);

fToolTip->setSize(350*scaleFactor, 50*scaleFactor);
fToolTip->setAbsolutePos(0*scaleFactor, 105*scaleFactor);
sizeGroup->resizeAspectSizeGroup(ev.size.getWidth(), ev.size.getHeight());
}

// -----------------------------------------------------------------------
Expand Down
Loading

0 comments on commit b9f6de5

Please sign in to comment.