Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Define input and output level calibration functionality for DSP #121

Merged
merged 3 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ jobs:
- name: Run tests
working-directory: ${{github.workspace}}
run: |
./build/tools/run_tests
./build/tools/benchmodel ./example_models/wavenet.nam
./build/tools/benchmodel ./example_models/lstm.nam
20 changes: 20 additions & 0 deletions NAM/dsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,21 @@ class DSP
// Expected sample rate, in Hz.
// TODO throw if it doesn't know.
double GetExpectedSampleRate() const { return mExpectedSampleRate; };
// Input Level, in dBu, corresponding to 0 dBFS for a sine wave
// You should call HasInputLevel() first to be safe.
double GetInputLevel() {return mInputLevel.level;};
// Get how loud this model is, in dB.
// Throws a std::runtime_error if the model doesn't know how loud it is.
double GetLoudness() const;
// Output Level, in dBu, corresponding to 0 dBFS for a sine wave
// You should call HasOutputLevel() first to be safe.
double GetOutputLevel() {return mOutputLevel.level;};
// Does this model know its output level?
bool HasInputLevel() {return mInputLevel.haveLevel;};
// Get whether the model knows how loud it is.
bool HasLoudness() const { return mHasLoudness; };
// Does this model know its output level?
bool HasOutputLevel() {return mOutputLevel.haveLevel;};
// General function for resetting the DSP unit.
// This doesn't call prewarm(). If you want to do that, then you might want to use ResetAndPrewarm().
// See https://github.com/sdatkinson/NeuralAmpModelerCore/issues/96 for the reasoning.
Expand All @@ -73,10 +83,12 @@ class DSP
Reset(sampleRate, maxBufferSize);
prewarm();
}
void SetInputLevel(const double inputLevel) {mInputLevel.haveLevel = true; mInputLevel.level = inputLevel;};
// Set the loudness, in dB.
// This is usually defined to be the loudness to a standardized input. The trainer has its own, but you can always
// use this to define it a different way if you like yours better.
void SetLoudness(const double loudness);
void SetOutputLevel(const double outputLevel) {mOutputLevel.haveLevel = true; mOutputLevel.level = outputLevel;};

protected:
bool mHasLoudness = false;
Expand All @@ -92,6 +104,14 @@ class DSP

// How many samples should be processed for me to be considered "warmed up"?
virtual int PrewarmSamples() { return 0; };

private:
struct Level {
bool haveLevel=false;
float level = 0.0;
};
Level mInputLevel;
Level mOutputLevel;
};

// Class where an input buffer is kept so that long-time effects can be
Expand Down
1 change: 1 addition & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ include_directories(tools ${NAM_DEPS_PATH}/nlohmann)

add_executable(loadmodel loadmodel.cpp ${NAM_SOURCES})
add_executable(benchmodel benchmodel.cpp ${NAM_SOURCES})
add_executable(run_tests run_tests.cpp ${NAM_SOURCES})

source_group(NAM ${CMAKE_CURRENT_SOURCE_DIR} FILES ${NAM_SOURCES})

Expand Down
19 changes: 19 additions & 0 deletions tools/run_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Entry point for tests

#include <iostream>
#include "test/test_dsp.cpp"

int main() {
std::cout << "Running tests..." << std::endl;
// TODO Automatically loop, catch exceptions, log results
test_dsp::test_construct();
test_dsp::test_get_input_level();
test_dsp::test_get_output_level();
test_dsp::test_has_input_level();
test_dsp::test_has_output_level();
test_dsp::test_set_input_level();
test_dsp::test_set_output_level();

std::cout << "Success!" << std::endl;
return 0;
}
59 changes: 59 additions & 0 deletions tools/test/test_dsp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Tests for dsp

#include "NAM/dsp.h"

namespace test_dsp {
// Simplest test: can I construct something!
void test_construct() {
nam::DSP myDsp(48000.0);
}

void test_get_input_level() {
nam::DSP myDsp(48000.0);
const double expected = 19.3;
myDsp.SetInputLevel(expected);
assert(myDsp.HasInputLevel());
const double actual = myDsp.GetInputLevel();

assert(actual == expected);
}

void test_get_output_level() {
nam::DSP myDsp(48000.0);
const double expected = 12.3;
myDsp.SetOutputLevel(expected);
assert(myDsp.HasOutputLevel());
const double actual = myDsp.GetOutputLevel();

assert(actual == expected);
}

// Test correct function of DSP::HasInputLevel()
void test_has_input_level() {
nam::DSP myDsp(48000.0);
assert(!myDsp.HasInputLevel());

myDsp.SetInputLevel(19.3);
assert(myDsp.HasInputLevel());
}

void test_has_output_level() {
nam::DSP myDsp(48000.0);
assert(!myDsp.HasOutputLevel());

myDsp.SetOutputLevel(12.3);
assert(myDsp.HasOutputLevel());
}

// Test correct function of DSP::HasInputLevel()
void test_set_input_level() {
nam::DSP myDsp(48000.0);
myDsp.SetInputLevel(19.3);
}

void test_set_output_level() {
nam::DSP myDsp(48000.0);
myDsp.SetOutputLevel(19.3);
}
};

Loading