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_blue=141
shutdown_brightness=50
rainbow_tail_factor=30
```
# TODO
- Support for custom Scripts without writing C++
- VWeb Interface to control Configs without restarting
- Less CPU Usage
- Keyboard Mapping
- Macro Support
- Execute of Script on Hotkeys
- [ ] Support for custom Scripts without writing C++
- [ ] LUA (sol2)
- [ ] Helper Functions
- [ ] Keyboard Mapper
- [ ] Web Interface to control Configs without restarting
- [ ] 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();
FFT fft;
ReqMode requestMode = ReqMode::FFT;
double loudness = 0.0;
float getLoudness();
stereoSampleFrame loudness = {0.0, 0.0};
stereoSampleFrame getLoudness();
bool work();
VUtils::Environment *env = nullptr;
private:

View File

@ -39,6 +39,7 @@ public:
int getIndex(int row, int col);
// PLEASE MAKE SURE YOU KNOW THE LIMITS!
int getIndexNoCheck(int row, int col);
static void fadeOutMap(led_map* map, double factor);
protected:
void setupMap();
// 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
#include <VulcanoLE/Visual/VIZ.h>
#include <VulcanoLE/Audio/AudioGrabber.h>
#include <VulcanoLE/Keyboards/Vulcan121.h>
@ -10,9 +11,18 @@ namespace VIZ {
~Loudness() override = default;
void onSetup() override;
void onTick(float delta) override;
float lastVal = 0;
void setForChannel(float value, int channel);
void drawFrame(int toRow);
const char *name() override;
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;
double lastValue = 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;
public:
RainbowLine(AudioGrabber *pGrabber, Vulcan121 *vulcan);
@ -18,7 +18,6 @@ namespace VIZ {
void onSetup() override;
void onTick(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();

View File

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

View File

@ -134,45 +134,49 @@ void AudioGrabber::init() {
if (env != nullptr)
m_scale = env->getAsDouble("audio_scale", 1.0);
DBG("SET Audio Scale: %.3f", m_scale)
loudness = 0.0;
loudness = { 0.0, 0.0 };
}
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++) {
float left = pFrame[0].l;
square += std::pow(left, 2);
squareL += std::pow(pFrame[0].l, 2);
squareR += std::pow(pFrame[0].r, 2);
}
mean = (square / (float) (BUFFER_SIZE));
loudness = std::sqrt(mean);
meanL = (squareL / (float) (BUFFER_SIZE));
meanR = (squareR / (float) (BUFFER_SIZE));
loudness = { std::sqrt(meanL), std::sqrt(meanR) };
}
void AudioGrabber::calculatePEAK(stereoSample *pFrame) {
float max = 0;
stereoSampleFrame max = { 0, 0 };
for (int i = 0; i < BUFFER_SIZE; i++) {
float left = std::abs(pFrame[0].l);
if (left > max) {
max = left;
}
float right = std::abs(pFrame[0].r);
if (left > max.l)
max.l = left;
if (right > max.r)
max.r = right;
}
loudness = max;
}
float AudioGrabber::getLoudness() {
stereoSampleFrame AudioGrabber::getLoudness() {
std::unique_lock<std::mutex> lck(m_mtx);
return (float) loudness;
return loudness;
}
bool AudioGrabber::work() {
std::unique_lock<std::mutex> lck(m_mtx);
if (this->read(m_buffer, BUFFER_SIZE)) {
for (int i = 0; i < BUFFER_SIZE; ++i) {
// my system is fucking quite
m_buffer[i].l *= m_scale;
m_buffer[i].r *= m_scale;
}
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) {
m_buffer[i].l *= m_scale;
m_buffer[i].r *= m_scale;
}
fft.process(m_buffer);
break;
case ReqMode::RMS:

View File

@ -233,8 +233,8 @@ bool Vulcan121::waitForCtrlDev() {
}
int Vulcan121::getColumnsForRow(int row) {
if (row > NUM_ROWS-1) {
WARN("Try to Access out of Bound %d max %d", row, NUM_ROWS-1)
if (row > NUM_ROWS - 1) {
WARN("Try to Access out of Bound %d max %d", row, NUM_ROWS - 1)
return 0;
}
return keyMapRow[row]->count;
@ -242,16 +242,16 @@ int Vulcan121::getColumnsForRow(int row) {
int Vulcan121::getRowsForColumns(int col) {
if (col > NUM_COLS-1) {
WARN("Try to Access out of Bound %d max %d", col, NUM_COLS-1)
if (col > NUM_COLS - 1) {
WARN("Try to Access out of Bound %d max %d", col, NUM_COLS - 1)
return 0;
}
return keyMapCol[col]->count;
}
int Vulcan121::getIndex(int row, int col) {
if (row > NUM_ROWS-1) {
WARN("Try to Access out of Bound %d max %d", row, NUM_ROWS-1)
if (row > NUM_ROWS - 1) {
WARN("Try to Access out of Bound %d max %d", row, NUM_ROWS - 1)
return 0;
}
if (col > keyMapRow[row]->count) {
@ -274,8 +274,8 @@ void Vulcan121::setupMap() {
79, 87, 100, 104, 109, 113, 119, 124, 129 };
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[3]->count = 17;
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]->count = 18;
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]->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;
@ -288,11 +288,11 @@ void Vulcan121::setupMap() {
keyMapCol[2]->count = 6;
keyMapCol[2]->index = new int[6]{ 11, 12, 13, 14, 15, 16 };
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]->index = new int[5]{ 23, 24, 25, 26, 32 };
keyMapCol[5]->count = 6;
keyMapCol[5]->index = new int[6]{ 28, 29, 30, 31, 36, 37 };
keyMapCol[4]->index = new int[5]{ 23, 24, 25, 26, 27 };
keyMapCol[5]->count = 7;
keyMapCol[5]->index = new int[7]{ 28, 29, 30, 31, 36, 32, 37 };
keyMapCol[6]->count = 5;
keyMapCol[6]->index = new int[5]{ 48, 33, 34, 35, 52 };
keyMapCol[7]->count = 5;
@ -329,9 +329,15 @@ int Vulcan121::getIndexNoCheck(int row, int col) {
return keyMapRow[row]->index[col];
}
const keys * Vulcan121::getColumn(int col) {
const keys *Vulcan121::getColumn(int col) {
return keyMapCol[col];
}
const keys * Vulcan121::getRow(int row) {
const keys *Vulcan121::getRow(int 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) {
auto data = Vulcan121::createEmptyLEDMap();
float val = grabber->getLoudness();
val = val > 1.0f ? 1.0f : val;
double newVal = (val + lastVal) * 0.5;
int maxCol = newVal * keyboardData.num_cols;
for (int col = 0; col < maxCol; ++col) {
auto column = keyboard->getColumn(col);
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);
Vulcan121::fadeOutMap(data, tailFactor);
stereoSample val = grabber->getLoudness();
val.l = val.l > 1.0f ? 1.0f : val.l;
val.r = val.r > 1.0f ? 1.0f : val.r;
setForChannel(val.l, 0);
setForChannel(val.r, 1);
keyboard->sendLedMap(data, false);
}
const char *Loudness::name() {
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>
#define MAX_DELTA 1212000
#define MAX_PEAK 180
#define MAX_PEAK 170
namespace VIZ {
RainbowLine::RainbowLine(AudioGrabber *pGrabber, Vulcan121 *vulcan) : VIZ(pGrabber, vulcan) {
@ -20,7 +20,7 @@ namespace VIZ {
}
void RainbowLine::onSetup() {
currentColumn = 0;
updateMap(0);
Vulcan121::fadeOutMap(data, 0);
tailFactor = VUtils::Math::clamp(grabber->env->getAsDouble("rainbow_tail_factor", 0.3), 0.0, 0.9);
keyboard->sendToLEDs({ 0, 0, 0, 0 });
grabber->requestMode = AudioGrabber::ReqMode::FFT;
@ -28,7 +28,7 @@ namespace VIZ {
}
void RainbowLine::onTick(float delta) {
updateMap(tailFactor);
Vulcan121::fadeOutMap(data, tailFactor);
deltaElapsed += delta;
auto fftData = grabber->fft.getData()->leftChannel;
auto val = 0.0;
@ -85,10 +85,4 @@ namespace VIZ {
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;
}
}
}