Audio: Added Stereo Support

RainbowLine: Moved FadeOut effect to Keyboard
Loudness: Changed to use Stereo
Keyboard: Fixed Wrong Column Mapping
This commit is contained in:
Maurice Grönwoldt 2021-02-24 18:52:01 +01:00
parent 9b791f0765
commit 2e266fe038
10 changed files with 105 additions and 69 deletions

View file

@ -49,13 +49,18 @@ shutdown_color_red=235
shutdown_color_green=0 shutdown_color_green=0
shutdown_color_blue=141 shutdown_color_blue=141
shutdown_brightness=50 shutdown_brightness=50
rainbow_tail_factor=30
``` ```
# TODO # TODO
- Support for custom Scripts without writing C++ - [ ] Support for custom Scripts without writing C++
- VWeb Interface to control Configs without restarting - [ ] LUA (sol2)
- Less CPU Usage - [ ] Helper Functions
- Keyboard Mapping - [ ] Keyboard Mapper
- Macro Support - [ ] Web Interface to control Configs without restarting
- Execute of Script on Hotkeys - [ ] VWeb Implementing
- [x] Keyboard Mapping
- [ ] Keyboard Input Event-Handler
- [ ] Macro Support
- [ ] Execute of Script on Hotkeys (LUA)

View file

@ -35,8 +35,8 @@ public:
void init(); void init();
FFT fft; FFT fft;
ReqMode requestMode = ReqMode::FFT; ReqMode requestMode = ReqMode::FFT;
double loudness = 0.0; stereoSampleFrame loudness = {0.0, 0.0};
float getLoudness(); stereoSampleFrame getLoudness();
bool work(); bool work();
VUtils::Environment *env = nullptr; VUtils::Environment *env = nullptr;
private: private:

View file

@ -39,6 +39,7 @@ public:
int getIndex(int row, int col); int getIndex(int row, int col);
// PLEASE MAKE SURE YOU KNOW THE LIMITS! // PLEASE MAKE SURE YOU KNOW THE LIMITS!
int getIndexNoCheck(int row, int col); int getIndexNoCheck(int row, int col);
static void fadeOutMap(led_map* map, double factor);
protected: protected:
void setupMap(); void setupMap();
// we need some mapping feature! rows and cols dont have the same amount of keys. so the struct needs // we need some mapping feature! rows and cols dont have the same amount of keys. so the struct needs

View file

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <VulcanoLE/Visual/VIZ.h> #include <VulcanoLE/Visual/VIZ.h>
#include <VulcanoLE/Audio/AudioGrabber.h> #include <VulcanoLE/Audio/AudioGrabber.h>
#include <VulcanoLE/Keyboards/Vulcan121.h> #include <VulcanoLE/Keyboards/Vulcan121.h>
@ -10,9 +11,18 @@ namespace VIZ {
~Loudness() override = default; ~Loudness() override = default;
void onSetup() override; void onSetup() override;
void onTick(float delta) override; void onTick(float delta) override;
float lastVal = 0; void setForChannel(float value, int channel);
void drawFrame(int toRow);
const char *name() override; const char *name() override;
std::string m_name = "Loudness Meter"; std::string m_name = "Loudness Meter";
protected:
rgba colours[3] = {
{ 0, 0, 255, 80 },
{ 0, 255, 0, 80 },
{ 255, 0, 0, 40 }
};
double tailFactor = 0;
led_map *data = Vulcan121::createEmptyLEDMap();
}; };
} }

View file

@ -10,7 +10,7 @@ namespace VIZ {
rgba *colours = nullptr; rgba *colours = nullptr;
double lastValue = 0; double lastValue = 0;
double decayValue = 0; double decayValue = 0;
double ratios[4] = {1.3,1.2,1.3,1.4}; double ratios[4] = {1.3,1.3,1.3,1.2};
double tailFactor = 0.3; double tailFactor = 0.3;
public: public:
RainbowLine(AudioGrabber *pGrabber, Vulcan121 *vulcan); RainbowLine(AudioGrabber *pGrabber, Vulcan121 *vulcan);
@ -18,7 +18,6 @@ namespace VIZ {
void onSetup() override; void onSetup() override;
void onTick(float delta) override; void onTick(float delta) override;
void calcNextDelta(double ratio); void calcNextDelta(double ratio);
void updateMap(double factor);
const char *name() override; const char *name() override;
std::string m_name = "Rainbow Line"; std::string m_name = "Rainbow Line";
led_map *data = Vulcan121::createEmptyLEDMap(); led_map *data = Vulcan121::createEmptyLEDMap();

View file

@ -356,7 +356,7 @@ Key Count With LEDs: 105
| 18 | 3 | | 18 | 3 |
| 19 | E | | 19 | E |
| 20 | D | | 20 | D |
| 27 | C | | 21 | X |
### COL 4 ### COL 4
@ -367,7 +367,7 @@ Key Count With LEDs: 105
| 24 | 4 | | 24 | 4 |
| 25 | R | | 25 | R |
| 26 | F | | 26 | F |
| 32 | V | | 27 | C |
### COL 5 ### COL 5
@ -379,6 +379,7 @@ Key Count With LEDs: 105
| 30 | T | | 30 | T |
| 31 | G | | 31 | G |
| 36 | B | | 36 | B |
| 32 | V |
| 37 | SPACE | | 37 | SPACE |

View file

@ -134,45 +134,49 @@ void AudioGrabber::init() {
if (env != nullptr) if (env != nullptr)
m_scale = env->getAsDouble("audio_scale", 1.0); m_scale = env->getAsDouble("audio_scale", 1.0);
DBG("SET Audio Scale: %.3f", m_scale) DBG("SET Audio Scale: %.3f", m_scale)
loudness = 0.0; loudness = { 0.0, 0.0 };
} }
void AudioGrabber::calculateRMS(stereoSample *pFrame) { void AudioGrabber::calculateRMS(stereoSample *pFrame) {
float square = 0, mean; float squareL = 0, meanL;
float squareR = 0, meanR;
for (int i = 0; i < BUFFER_SIZE; i++) { for (int i = 0; i < BUFFER_SIZE; i++) {
float left = pFrame[0].l; squareL += std::pow(pFrame[0].l, 2);
square += std::pow(left, 2); squareR += std::pow(pFrame[0].r, 2);
} }
mean = (square / (float) (BUFFER_SIZE)); meanL = (squareL / (float) (BUFFER_SIZE));
loudness = std::sqrt(mean); meanR = (squareR / (float) (BUFFER_SIZE));
loudness = { std::sqrt(meanL), std::sqrt(meanR) };
} }
void AudioGrabber::calculatePEAK(stereoSample *pFrame) { void AudioGrabber::calculatePEAK(stereoSample *pFrame) {
float max = 0; stereoSampleFrame max = { 0, 0 };
for (int i = 0; i < BUFFER_SIZE; i++) { for (int i = 0; i < BUFFER_SIZE; i++) {
float left = std::abs(pFrame[0].l); float left = std::abs(pFrame[0].l);
if (left > max) { float right = std::abs(pFrame[0].r);
max = left; if (left > max.l)
} max.l = left;
if (right > max.r)
max.r = right;
} }
loudness = max; loudness = max;
} }
float AudioGrabber::getLoudness() { stereoSampleFrame AudioGrabber::getLoudness() {
std::unique_lock<std::mutex> lck(m_mtx); std::unique_lock<std::mutex> lck(m_mtx);
return (float) loudness; return loudness;
} }
bool AudioGrabber::work() { bool AudioGrabber::work() {
std::unique_lock<std::mutex> lck(m_mtx); std::unique_lock<std::mutex> lck(m_mtx);
if (this->read(m_buffer, BUFFER_SIZE)) { if (this->read(m_buffer, BUFFER_SIZE)) {
switch (requestMode) {
case ReqMode::FFT:
// FFT get's better results with maybe a bit scaling.. for RMS and PEAK this gets "worse"
for (int i = 0; i < BUFFER_SIZE; ++i) { for (int i = 0; i < BUFFER_SIZE; ++i) {
// my system is fucking quite
m_buffer[i].l *= m_scale; m_buffer[i].l *= m_scale;
m_buffer[i].r *= m_scale; m_buffer[i].r *= m_scale;
} }
switch (requestMode) {
case ReqMode::FFT:
fft.process(m_buffer); fft.process(m_buffer);
break; break;
case ReqMode::RMS: case ReqMode::RMS:

View file

@ -274,8 +274,8 @@ void Vulcan121::setupMap() {
79, 87, 100, 104, 109, 113, 119, 124, 129 }; 79, 87, 100, 104, 109, 113, 119, 124, 129 };
keyMapRow[2]->count = 19; keyMapRow[2]->count = 19;
keyMapRow[2]->index = new int[19]{ 2, 7, 13, 19, 25, 30, 34, 50, 55, 61, 67, 73, 80, 101, 105, 110, 114, 120, 125 }; keyMapRow[2]->index = new int[19]{ 2, 7, 13, 19, 25, 30, 34, 50, 55, 61, 67, 73, 80, 101, 105, 110, 114, 120, 125 };
keyMapRow[3]->count = 17; keyMapRow[3]->count = 18;
keyMapRow[3]->index = new int[17]{ 3, 8, 14, 20, 26, 31, 35, 51, 56, 62, 68, 74, 88, 115, 121, 126, 130 }; keyMapRow[3]->index = new int[18]{ 3, 8, 14, 20, 26, 31, 35, 51, 56, 62, 68, 74, 96, 88, 115, 121, 126, 130 };
keyMapRow[4]->count = 17; keyMapRow[4]->count = 17;
keyMapRow[4]->index = new int[17]{ 4, 9, 15, 21, 27, 32, 36, 52, 57, 63, 69, 75, 82, 106, 116, 122, 127 }; keyMapRow[4]->index = new int[17]{ 4, 9, 15, 21, 27, 32, 36, 52, 57, 63, 69, 75, 82, 106, 116, 122, 127 };
keyMapRow[5]->count = 14; keyMapRow[5]->count = 14;
@ -288,11 +288,11 @@ void Vulcan121::setupMap() {
keyMapCol[2]->count = 6; keyMapCol[2]->count = 6;
keyMapCol[2]->index = new int[6]{ 11, 12, 13, 14, 15, 16 }; keyMapCol[2]->index = new int[6]{ 11, 12, 13, 14, 15, 16 };
keyMapCol[3]->count = 5; keyMapCol[3]->count = 5;
keyMapCol[3]->index = new int[5]{ 17, 18, 19, 20, 27 }; keyMapCol[3]->index = new int[5]{ 17, 18, 19, 20, 21 };
keyMapCol[4]->count = 5; keyMapCol[4]->count = 5;
keyMapCol[4]->index = new int[5]{ 23, 24, 25, 26, 32 }; keyMapCol[4]->index = new int[5]{ 23, 24, 25, 26, 27 };
keyMapCol[5]->count = 6; keyMapCol[5]->count = 7;
keyMapCol[5]->index = new int[6]{ 28, 29, 30, 31, 36, 37 }; keyMapCol[5]->index = new int[7]{ 28, 29, 30, 31, 36, 32, 37 };
keyMapCol[6]->count = 5; keyMapCol[6]->count = 5;
keyMapCol[6]->index = new int[5]{ 48, 33, 34, 35, 52 }; keyMapCol[6]->index = new int[5]{ 48, 33, 34, 35, 52 };
keyMapCol[7]->count = 5; keyMapCol[7]->count = 5;
@ -335,3 +335,9 @@ const keys * Vulcan121::getColumn(int col) {
const keys *Vulcan121::getRow(int row) { const keys *Vulcan121::getRow(int row) {
return keyMapRow[row]; return keyMapRow[row];
} }
void Vulcan121::fadeOutMap(led_map *map, double factor = 0.3) {
for (auto &i : map->key) {
i.a *= factor;
}
}

View file

@ -10,25 +10,41 @@ namespace VIZ {
} }
void Loudness::onTick(float delta) { void Loudness::onTick(float delta) {
auto data = Vulcan121::createEmptyLEDMap(); Vulcan121::fadeOutMap(data, tailFactor);
float val = grabber->getLoudness(); stereoSample val = grabber->getLoudness();
val = val > 1.0f ? 1.0f : val; val.l = val.l > 1.0f ? 1.0f : val.l;
double newVal = (val + lastVal) * 0.5; val.r = val.r > 1.0f ? 1.0f : val.r;
int maxCol = newVal * keyboardData.num_cols; setForChannel(val.l, 0);
for (int col = 0; col < maxCol; ++col) { setForChannel(val.r, 1);
auto column = keyboard->getColumn(col); keyboard->sendLedMap(data, false);
for (int i = 0; i < column->count; ++i) {
auto index = column->index[i];
if (col >= maxCol - 1) data[ 0 ].key[ index ] = { 255, 0, 0, 100 };
else data[ 0 ].key[ index ] = { 0, 0, 255, 80 };
}
}
// delete map! ;)
lastVal = val;
keyboard->sendLedMap(data, true);
} }
const char *Loudness::name() { const char *Loudness::name() {
return m_name.c_str(); return m_name.c_str();
} }
void Loudness::setForChannel(float value, int channel) {
// because we have stereo we need to move on the rows
int offset = channel == 0 ? 1 : 3;
int until = channel == 0 ? 3 : 5;
colours[channel].a = value * 128.0;
for (int i = offset; i < until; ++i) {
auto row = keyboard->getRow(i);
int to = row->count * value;
for (int j = 0; j < to; ++j) {
auto index = row->index[j];
data[0].key[index] = colours[channel];
}
}
drawFrame(0);
drawFrame(5);
}
void Loudness::drawFrame(int toRow) {
auto row = keyboard->getRow(toRow);
for (int j = 0; j < row->count; ++j) {
auto index = row->index[j];
data[0].key[index] = colours[2];
}
}
} }

View file

@ -4,7 +4,7 @@
#include <VUtils/Math.h> #include <VUtils/Math.h>
#define MAX_DELTA 1212000 #define MAX_DELTA 1212000
#define MAX_PEAK 180 #define MAX_PEAK 170
namespace VIZ { namespace VIZ {
RainbowLine::RainbowLine(AudioGrabber *pGrabber, Vulcan121 *vulcan) : VIZ(pGrabber, vulcan) { RainbowLine::RainbowLine(AudioGrabber *pGrabber, Vulcan121 *vulcan) : VIZ(pGrabber, vulcan) {
@ -20,7 +20,7 @@ namespace VIZ {
} }
void RainbowLine::onSetup() { void RainbowLine::onSetup() {
currentColumn = 0; currentColumn = 0;
updateMap(0); Vulcan121::fadeOutMap(data, 0);
tailFactor = VUtils::Math::clamp(grabber->env->getAsDouble("rainbow_tail_factor", 0.3), 0.0, 0.9); tailFactor = VUtils::Math::clamp(grabber->env->getAsDouble("rainbow_tail_factor", 0.3), 0.0, 0.9);
keyboard->sendToLEDs({ 0, 0, 0, 0 }); keyboard->sendToLEDs({ 0, 0, 0, 0 });
grabber->requestMode = AudioGrabber::ReqMode::FFT; grabber->requestMode = AudioGrabber::ReqMode::FFT;
@ -28,7 +28,7 @@ namespace VIZ {
} }
void RainbowLine::onTick(float delta) { void RainbowLine::onTick(float delta) {
updateMap(tailFactor); Vulcan121::fadeOutMap(data, tailFactor);
deltaElapsed += delta; deltaElapsed += delta;
auto fftData = grabber->fft.getData()->leftChannel; auto fftData = grabber->fft.getData()->leftChannel;
auto val = 0.0; auto val = 0.0;
@ -85,10 +85,4 @@ namespace VIZ {
rRatio = (VUtils::Math::easeIn(rRatio) - 1.0) * -1; rRatio = (VUtils::Math::easeIn(rRatio) - 1.0) * -1;
deltaNeeded = rRatio * MAX_DELTA; deltaNeeded = rRatio * MAX_DELTA;
} }
void RainbowLine::updateMap(double factor) {
for (int i = 0; i < keyboardData.num_keys; ++i) {
data->key[i].a *= factor;
}
}
} }