Added Math Class
Added Rainbow Line Visual Added Delta-Timing to Visuals Cleanup Code Structure
This commit is contained in:
parent
238e22caf6
commit
dd06aa3e35
19 changed files with 244 additions and 34 deletions
|
@ -22,9 +22,11 @@ set(SOURCE_FILES
|
|||
src/VulcanoLE/Audio/FFT.cpp
|
||||
src/VulcanoLE/Audio/VisAudioRunner.cpp
|
||||
src/VulcanoLE/Visual/VisPlugins.cpp
|
||||
src/VulcanoLE/Colors/ColorHelper.cpp
|
||||
src/VulcanoLE/Scripts/Loudness.cpp
|
||||
src/VulcanoLE/Scripts/Spectrum.cpp
|
||||
src/VulcanoLE/Scripts/WeirdSpec.cpp
|
||||
src/VulcanoLE/Scripts/PoliceLike.cpp
|
||||
src/VulcanoLE/Scripts/RainbowLine.cpp
|
||||
)
|
||||
set(UTILS_FILES
|
||||
src/VUtils/Logging.cpp
|
||||
|
@ -32,6 +34,7 @@ set(UTILS_FILES
|
|||
src/VUtils/Pool.cpp
|
||||
src/VUtils/Environment.cpp
|
||||
src/VUtils/StringUtils.cpp
|
||||
src/VUtils/Math.cpp
|
||||
)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/headers/)
|
||||
add_executable(
|
||||
|
|
10
headers/VUtils/Math.h
Normal file
10
headers/VUtils/Math.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
namespace VUtils {
|
||||
struct Math {
|
||||
static double clamp (double value, double min, double max);
|
||||
static double lerp(double a, double b, double f);
|
||||
static double bezierBlend(double t);
|
||||
static double easeIn(double ratio);
|
||||
};
|
||||
}
|
8
headers/VulcanoLE/Colors/ColorHelper.h
Normal file
8
headers/VulcanoLE/Colors/ColorHelper.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
#include <VulcanoLE/Colors/Type.h>
|
||||
|
||||
namespace Color {
|
||||
struct Generator {
|
||||
static rgba rgbFromRatio(double ratio, int16_t alpha);
|
||||
};
|
||||
}
|
10
headers/VulcanoLE/Colors/Type.h
Normal file
10
headers/VulcanoLE/Colors/Type.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
typedef struct rgba_type {
|
||||
int16_t r{};
|
||||
int16_t g{};
|
||||
int16_t b{};
|
||||
int16_t a = 255;
|
||||
} rgba;
|
|
@ -1,18 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <VulcanoLE/API/HIDHelper.h>
|
||||
#include <VulcanoLE/Colors/Type.h>
|
||||
|
||||
#define NUM_KEYS 144
|
||||
#define NUM_ROWS 6
|
||||
#define NUM_COLS 21
|
||||
|
||||
typedef struct rgba_type {
|
||||
int16_t r{};
|
||||
int16_t g{};
|
||||
int16_t b{};
|
||||
int16_t a = 255;
|
||||
} rgba;
|
||||
|
||||
typedef struct subArray {
|
||||
int count = 0;
|
||||
int *index = nullptr; // will init in code! and returned
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace VIZ {
|
|||
Loudness(AudioGrabber *pGrabber, Vulcan121 *pVulcan121);
|
||||
~Loudness() override = default;
|
||||
void on_setup() override;
|
||||
void on_tick() override;
|
||||
void on_tick(float delta) override;
|
||||
float lastVal = 0;
|
||||
const char *name() override;
|
||||
std::string m_name = "Loudness Meter";
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
#include <VulcanoLE/Visual/VIZ.h>
|
||||
|
||||
namespace VIZ {
|
||||
class WeirdSpec : public VIZ {
|
||||
class PoliceLike : public VIZ {
|
||||
protected:
|
||||
int decayRate = 10;
|
||||
double lastPeak = -1;
|
||||
double threshold = 15;
|
||||
public:
|
||||
WeirdSpec(AudioGrabber *pGrabber, Vulcan121 *pVulcan121);
|
||||
~WeirdSpec() override = default;
|
||||
PoliceLike(AudioGrabber *pGrabber, Vulcan121 *pVulcan121);
|
||||
~PoliceLike() override = default;
|
||||
void on_setup() override;
|
||||
void on_tick() override;
|
||||
void on_tick(float delta) override;
|
||||
void switchOnPeak(double);
|
||||
int tick = 0;
|
||||
bool left = true;
|
26
headers/VulcanoLE/Scripts/RainbowLine.h
Normal file
26
headers/VulcanoLE/Scripts/RainbowLine.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include <VulcanoLE/Visual/VIZ.h>
|
||||
|
||||
namespace VIZ {
|
||||
class RainbowLine : public VIZ {
|
||||
int currentColumn = 0;
|
||||
double deltaNeeded = 100000.0;
|
||||
double deltaElapsed = 0;
|
||||
rgba *colours = nullptr;
|
||||
double lastValue = 0;
|
||||
double decayValue = 0;
|
||||
double ratios[4] = {1.3,1.2,1.3,1.4};
|
||||
public:
|
||||
RainbowLine(AudioGrabber *pGrabber, Vulcan121 *vulcan);
|
||||
~RainbowLine() override;
|
||||
void on_setup() override;
|
||||
void on_tick(float delta) override;
|
||||
void calcNextDelta(double ratio);
|
||||
void updateMap(double factor);
|
||||
const char *name() override;
|
||||
std::string m_name = "Rainbow Line";
|
||||
led_map *data = Vulcan121::createEmptyLEDMap();
|
||||
bool firstUnder = true;
|
||||
};
|
||||
}
|
|
@ -8,7 +8,7 @@ namespace VIZ {
|
|||
Spectrum(AudioGrabber *pGrabber, Vulcan121 *pVulcan121);
|
||||
~Spectrum() override = default;
|
||||
void on_setup() override;
|
||||
void on_tick() override;
|
||||
void on_tick(float delta) override;
|
||||
double lastVal = 0;
|
||||
const char *name() override;
|
||||
std::string m_name = "Spectrum One";
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace VIZ {
|
|||
VIZ(AudioGrabber *pGrabber, Vulcan121 *pVulcan121) : grabber(pGrabber), keyboard(pVulcan121) {}
|
||||
virtual ~VIZ() = default;
|
||||
virtual void on_setup() = 0;
|
||||
virtual void on_tick() = 0;
|
||||
virtual void on_tick(float delta) = 0;
|
||||
Vulcan121 *keyboard{};
|
||||
Vulcan121::DATA keyboardData = Vulcan121::DATA{};
|
||||
AudioGrabber *grabber{};
|
||||
|
|
|
@ -3,23 +3,26 @@
|
|||
#include <vector>
|
||||
#include <VulcanoLE/Scripts/Spectrum.h>
|
||||
|
||||
#define VIZSIZE 3
|
||||
#define VIZSIZE 4
|
||||
|
||||
using micro = std::chrono::duration<double, std::micro>;
|
||||
|
||||
namespace VIZ {
|
||||
struct VisPlugins {
|
||||
int mode = 0;
|
||||
void init(HIDHelper *, AudioGrabber*);
|
||||
void init(HIDHelper *, AudioGrabber *);
|
||||
void on_startup();
|
||||
void on_tick();
|
||||
void on_shutdown();
|
||||
void setCurrentMode(int);
|
||||
~VisPlugins();
|
||||
VUtils::Environment *env;
|
||||
VUtils::Environment *env{};
|
||||
protected:
|
||||
VIZ *viz[VIZSIZE]{};
|
||||
VIZ *currentVis;
|
||||
Vulcan121 *keyboard;
|
||||
AudioGrabber *grabber;
|
||||
VIZ *currentVis{};
|
||||
Vulcan121 *keyboard{};
|
||||
AudioGrabber *grabber{};
|
||||
std::chrono::time_point<std::chrono::system_clock, micro> start;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
2
main.cpp
2
main.cpp
|
@ -44,7 +44,7 @@ int main(int argc, char **argv) {
|
|||
runner->plugins->setCurrentMode(config.getAsInt("visual_mode", 1));
|
||||
while (shouldRun) {
|
||||
int mode;
|
||||
LOGWN("Enter Visual Mode: %d-%d < 0 = EXIT:\t", 0, 1)
|
||||
LOGWN("Enter Visual Mode: %d-%d < 0 = EXIT:\t", 1, VIZSIZE)
|
||||
std::cin >> mode;
|
||||
if (std::cin.fail()) {
|
||||
ERR("ERROR -- You did not enter an integer")
|
||||
|
|
17
src/VUtils/Math.cpp
Normal file
17
src/VUtils/Math.cpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <VUtils/Math.h>
|
||||
|
||||
namespace VUtils {
|
||||
double Math::clamp(double value, double min, double max) {
|
||||
return value > max ? max : value < min ? min : value;
|
||||
}
|
||||
|
||||
double Math::lerp(double a, double b, double f) {
|
||||
return (a + (b - a) * f);
|
||||
}
|
||||
double Math::bezierBlend(double t) {
|
||||
return t * t * (3.0 - 2.0 * t);
|
||||
}
|
||||
double Math::easeIn(double ratio) {
|
||||
return ratio * ratio * ratio;
|
||||
}
|
||||
}
|
44
src/VulcanoLE/Colors/ColorHelper.cpp
Normal file
44
src/VulcanoLE/Colors/ColorHelper.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include <VulcanoLE/Colors/ColorHelper.h>
|
||||
|
||||
namespace Color {
|
||||
rgba Generator::rgbFromRatio(double ratio, int16_t alpha = 255) {
|
||||
int normalized = int(ratio * 256 * 6);
|
||||
int x = normalized % 256;
|
||||
|
||||
int16_t red = 0, green = 0, blue = 0;
|
||||
switch (normalized / 256) {
|
||||
case 0:
|
||||
red = 255;
|
||||
green = x;
|
||||
blue = 0;
|
||||
break;
|
||||
case 1:
|
||||
red = 255 - x;
|
||||
green = 255;
|
||||
blue = 0;
|
||||
break;
|
||||
case 2:
|
||||
red = 0;
|
||||
green = 255;
|
||||
blue = x;
|
||||
break;
|
||||
case 3:
|
||||
red = 0;
|
||||
green = 255 - x;
|
||||
blue = 255;
|
||||
break;
|
||||
case 4:
|
||||
red = x;
|
||||
green = 0;
|
||||
blue = 255;
|
||||
break;
|
||||
case 5:
|
||||
red = 255;
|
||||
green = 0;
|
||||
blue = 255 - x;
|
||||
break;
|
||||
}
|
||||
|
||||
return { red, green, blue, alpha };
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ namespace VIZ {
|
|||
usleep(100000);
|
||||
}
|
||||
|
||||
void Loudness::on_tick() {
|
||||
void Loudness::on_tick(float delta) {
|
||||
auto data = Vulcan121::createEmptyLEDMap();
|
||||
float val = grabber->getLoudness();
|
||||
val = val > 1.0f ? 1.0f : val;
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
#include <VulcanoLE/Scripts/WeirdSpec.h>
|
||||
#include <VulcanoLE/Scripts/PoliceLike.h>
|
||||
|
||||
namespace VIZ {
|
||||
WeirdSpec::WeirdSpec(AudioGrabber *pGrabber, Vulcan121 *pVulcan121) : VIZ(pGrabber, pVulcan121) {
|
||||
PoliceLike::PoliceLike(AudioGrabber *pGrabber, Vulcan121 *pVulcan121) : VIZ(pGrabber, pVulcan121) {
|
||||
|
||||
}
|
||||
|
||||
void WeirdSpec::on_setup() {
|
||||
void PoliceLike::on_setup() {
|
||||
keyboard->send_led_to({ 0, 0, 0, 0 });
|
||||
grabber->requestMode = AudioGrabber::ReqMode::FFT;
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
void WeirdSpec::on_tick() {
|
||||
void PoliceLike::on_tick(float delta) {
|
||||
auto map = Vulcan121::createEmptyLEDMap();
|
||||
auto data = grabber->fft.getData()->leftChannel;
|
||||
auto val = 0.0;
|
||||
|
@ -35,7 +35,7 @@ namespace VIZ {
|
|||
keyboard->send_led_map(map, true);
|
||||
}
|
||||
|
||||
void WeirdSpec::switchOnPeak(double peak) {
|
||||
void PoliceLike::switchOnPeak(double peak) {
|
||||
if (tick < 3) {
|
||||
return;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ namespace VIZ {
|
|||
}
|
||||
}
|
||||
|
||||
const char *WeirdSpec::name() {
|
||||
const char *PoliceLike::name() {
|
||||
return m_name.c_str();
|
||||
}
|
||||
}
|
89
src/VulcanoLE/Scripts/RainbowLine.cpp
Normal file
89
src/VulcanoLE/Scripts/RainbowLine.cpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include <VulcanoLE/Scripts/RainbowLine.h>
|
||||
#include <VulcanoLE/Colors/ColorHelper.h>
|
||||
#include <VUtils/Logging.h>
|
||||
#include <VUtils/Math.h>
|
||||
|
||||
#define MAX_DELTA 1212000
|
||||
#define MAX_PEAK 180
|
||||
|
||||
namespace VIZ {
|
||||
RainbowLine::RainbowLine(AudioGrabber *pGrabber, Vulcan121 *vulcan) : VIZ(pGrabber, vulcan) {
|
||||
colours = new rgba[keyboardData.num_cols];
|
||||
for (int i = 0; i < keyboardData.num_cols; ++i) {
|
||||
double ratio = (double) i / keyboardData.num_cols;
|
||||
colours[i] = Color::Generator::rgbFromRatio(ratio, 255);
|
||||
}
|
||||
}
|
||||
RainbowLine::~RainbowLine() {
|
||||
delete[] colours;
|
||||
delete data;
|
||||
}
|
||||
void RainbowLine::on_setup() {
|
||||
currentColumn = 0;
|
||||
updateMap(0);
|
||||
keyboard->send_led_to({ 0, 0, 0, 0 });
|
||||
grabber->requestMode = AudioGrabber::ReqMode::FFT;
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
void RainbowLine::on_tick(float delta) {
|
||||
updateMap(0.3);
|
||||
deltaElapsed += delta;
|
||||
auto fftData = grabber->fft.getData()->leftChannel;
|
||||
auto val = 0.0;
|
||||
for (int i = 1; i < 4; ++i) {
|
||||
auto avg = fftData[i] * ratios[i];
|
||||
if (avg > val)
|
||||
val = avg;
|
||||
}
|
||||
val = VUtils::Math::clamp(val, 0, 255);
|
||||
auto avg = (lastValue + val) * 0.5;
|
||||
if (avg > MAX_PEAK || avg > decayValue) {
|
||||
calcNextDelta(val < MAX_PEAK && firstUnder ? 160 : val);
|
||||
firstUnder = val > MAX_PEAK;
|
||||
decayValue = val;
|
||||
}
|
||||
if (val > MAX_PEAK) {
|
||||
firstUnder = true;
|
||||
}
|
||||
if (avg < 10) {
|
||||
deltaNeeded = 1000000000;
|
||||
}
|
||||
if (deltaElapsed >= deltaNeeded) {
|
||||
deltaElapsed = 0;
|
||||
currentColumn++;
|
||||
if (currentColumn >= keyboardData.num_cols) {
|
||||
currentColumn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (decayValue >= 0)
|
||||
decayValue -= 10;
|
||||
colours[currentColumn].a = val;
|
||||
auto column = keyboard->getColumn(currentColumn);
|
||||
for (int i = 0; i < column->count; ++i) {
|
||||
auto index = column->index[i];
|
||||
data[0].key[index] = colours[currentColumn];
|
||||
}
|
||||
lastValue = avg;
|
||||
// we clean up the map self later! :)
|
||||
keyboard->send_led_map(data, false);
|
||||
}
|
||||
|
||||
const char *RainbowLine::name() {
|
||||
return m_name.c_str();
|
||||
}
|
||||
|
||||
void RainbowLine::calcNextDelta(double ratio) {
|
||||
double rRatio = ratio / MAX_PEAK;
|
||||
rRatio = VUtils::Math::clamp(rRatio, 0.05, 1.0);
|
||||
rRatio = (VUtils::Math::easeIn(rRatio) - 1.0) * -1;
|
||||
deltaNeeded = rRatio * MAX_DELTA;
|
||||
}
|
||||
|
||||
void RainbowLine::updateMap(double factor) {
|
||||
for (int i = 0; i < keyboardData.num_keys; ++i) {
|
||||
data->key[i].a *= factor;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ namespace VIZ {
|
|||
grabber->requestMode = AudioGrabber::ReqMode::FFT;
|
||||
usleep(100000);
|
||||
}
|
||||
void Spectrum::on_tick() {
|
||||
void Spectrum::on_tick(float delta) {
|
||||
auto map = Vulcan121::createEmptyLEDMap();
|
||||
auto data = grabber->fft.getData()->leftChannel;
|
||||
// find largest bass ~43hz (44100 / FFT_SIZE) range
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#include <VulcanoLE/Visual/VisPlugins.h>
|
||||
#include <VulcanoLE/Scripts/Spectrum.h>
|
||||
#include <VulcanoLE/Scripts/Loudness.h>
|
||||
#include <VulcanoLE/Scripts/WeirdSpec.h>
|
||||
#include <VulcanoLE/Scripts/PoliceLike.h>
|
||||
#include <VUtils/Logging.h>
|
||||
#include <VulcanoLE/Scripts/RainbowLine.h>
|
||||
|
||||
namespace VIZ {
|
||||
void VisPlugins::init(HIDHelper *hidHelper, AudioGrabber *audioGrabber) {
|
||||
|
@ -10,7 +11,8 @@ namespace VIZ {
|
|||
keyboard = new Vulcan121(hidHelper);
|
||||
viz[0] = new Spectrum(grabber, keyboard);
|
||||
viz[1] = new Loudness(grabber, keyboard);
|
||||
viz[2] = new WeirdSpec(grabber, keyboard);
|
||||
viz[2] = new PoliceLike(grabber, keyboard);
|
||||
viz[3] = new RainbowLine(grabber, keyboard);
|
||||
currentVis = viz[mode];
|
||||
}
|
||||
|
||||
|
@ -20,11 +22,15 @@ namespace VIZ {
|
|||
exit(1);
|
||||
}
|
||||
currentVis->on_setup();
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
void VisPlugins::on_tick() {
|
||||
currentVis->on_tick();
|
||||
auto stop = std::chrono::high_resolution_clock::now();
|
||||
auto delta = std::chrono::duration_cast<micro>(stop - start).count();
|
||||
currentVis->on_tick(delta);
|
||||
usleep(1000);
|
||||
start = stop;
|
||||
}
|
||||
|
||||
void VisPlugins::on_shutdown() {
|
||||
|
@ -44,7 +50,7 @@ namespace VIZ {
|
|||
}
|
||||
|
||||
void VisPlugins::setCurrentMode(int m) {
|
||||
if (m == 0 || m > VIZSIZE) {
|
||||
if (m < 1 || m > VIZSIZE) {
|
||||
ERR("Mode Setting Failed >> Mode is not in the available range 1 - %d", VIZSIZE)
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue