106 lines
3.1 KiB
C++
106 lines
3.1 KiB
C++
#include <VulcanoLE/Scripts/RainbowMap.h>
|
|
#include <VulcanoLE/Colors/ColorHelper.h>
|
|
#include <VUtils/Logging.h>
|
|
#include <VUtils/Math.h>
|
|
|
|
#define MAX_DELTA 808000
|
|
#define MAX_PEAK 170
|
|
|
|
namespace VIZ {
|
|
RainbowMap::RainbowMap(AudioGrabber *pGrabber, Vulcan121 *vulcan) : VIZ(pGrabber, vulcan) {
|
|
maxCols = keyboardData.num_cols * keyboardData.num_rows;
|
|
colours = new rgba[maxCols];
|
|
for (int i = 0; i < maxCols; ++i) {
|
|
double ratio = (double) i / maxCols;
|
|
colours[i] = Color::Generator::rgbFromRatio(ratio, 128);
|
|
}
|
|
}
|
|
RainbowMap::~RainbowMap() {
|
|
delete[] colours;
|
|
}
|
|
void RainbowMap::onSetup() {
|
|
currentColumn = 0;
|
|
Vulcan121::fadeOutMap(data, 0);
|
|
keyboard->sendToLEDs({ 0, 0, 0, 0 });
|
|
grabber->requestMode = AudioGrabber::ReqMode::FFT;
|
|
usleep(100000);
|
|
}
|
|
|
|
void RainbowMap::onTick(float delta) {
|
|
deltaElapsed += delta;
|
|
auto fftData = grabber->fft.getData()->leftChannel;
|
|
auto val = 0.0;
|
|
for (int i = 0; i < 3; ++i) {
|
|
auto avg = fftData[i];
|
|
if (avg > val)
|
|
val = avg;
|
|
}
|
|
val = VUtils::Math::clamp(val, 0, 255);
|
|
double avg = deltaMove(val);
|
|
if (deltaElapsed >= deltaNeeded) {
|
|
currentColumn++;
|
|
if (currentColumn >= maxCols)
|
|
currentColumn = 0;
|
|
moveRainbow(avg);
|
|
deltaElapsed -= deltaNeeded;
|
|
}
|
|
moveRainbow(avg);
|
|
lastValue = avg;
|
|
// we clean up the map self later! :)
|
|
keyboard->sendLedMap(data);
|
|
}
|
|
|
|
double RainbowMap::deltaMove(double val) {
|
|
auto avg = VUtils::Math::clamp((lastValue + val) * 0.5, 0, 200);
|
|
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 (decayValue >= 0)
|
|
decayValue -= 10;
|
|
return avg;
|
|
}
|
|
|
|
const char *RainbowMap::name() {
|
|
return m_name.c_str();
|
|
}
|
|
|
|
void RainbowMap::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 RainbowMap::moveRainbow(double d) {
|
|
int i = 0;
|
|
int color = currentColumn;
|
|
while (i < keyboardData.num_cols) {
|
|
colours[color].a = (uint8_t) d;
|
|
updateColumn(i, color);
|
|
color++;
|
|
i++;
|
|
if (color > maxCols - 1)
|
|
color = 0;
|
|
}
|
|
}
|
|
|
|
void RainbowMap::updateColumn(int col, int colIndex) {
|
|
auto column = keyboard->getColumn(col);
|
|
if (!column) {
|
|
ERR("Column: %d not found", col);
|
|
return;
|
|
}
|
|
for (int i = 0; i < column->count; ++i) {
|
|
auto index = column->index[i];
|
|
data.key[index] = colours[colIndex];
|
|
}
|
|
}
|
|
} |