Skip to content
Snippets Groups Projects
Commit 63ad7912 authored by David Huss's avatar David Huss :speech_balloon:
Browse files

Make LED level indicator moar better

parent c46a2456
Branches
Tags
No related merge requests found
%% Cell type:code id:52c8bec3-db2d-4522-b692-b035a71410de tags:
``` python
from matplotlib import pyplot as plt
%matplotlib inline
import math
!{sys.executable} -m pip install clipboard
%matplotlib inline
import clipboard
def draw(r, g, b):
x = [x for x in range(256)]
fig = plt.figure(figsize=(8, 4))
ax = fig.add_axes([0, 0, 1, 1])
ax.axhline(y=0.5, color='black', linestyle='--')
ax.set_xticks(range(0, 256, 64))
ax.set_yticks(range(-256*2, 256*2+1, 128))
ax.grid()
ax.plot(x, r, 'r')
ax.plot(x, g, 'g')
ax.plot(x, b, 'b')
def r():
start = 100
start2 = 220
last_a = 0
for i in range(256):
if i < start:
yield 0
elif i < start2:
span = 255-start
d = (i-start)/span
last_a = int(d*30.0)
yield min(255, last_a)
else:
span = 255-start2
d = (i-start2)/span
d = d*d*d
yield min(255, last_a + int(d*350.0))
def g():
start = 0
end = 180-80
scale = 0.25
for i in range(256):
if i < start:
yield 0
elif i > end:
d = 1.0 - ((i-end)/(295-end))
# d = (d*d)/4 + d/2
yield max(0, min(255, int(d*175*scale)))
else:
d = ((i-start)/(255-start))
d = (d*d*d)
yield min(255, int(d*2800*scale))
def b():
start = 4
end = 40
scale = 0.2
for i in range(256):
if i < start:
yield 0
elif i > end:
d = (i-end)/(60)
d = d*d
d = 1.0 - d
# d = math.sqrt(d)
yield max(0, min(255, int(d*32*scale)))
else:
d = (i-start)/(255-start)
d = math.sqrt(d)/2 + d/2
yield max(0, min(255, int(d*107*scale)))
r, g, b = list(r()), list(g()), list(b())
draw(r, g, b)
text = ""
text += "// Lookup Table for Red LED Channel\n"
text += f"int red_lookup[] = {{{', '.join(str(v) for v in r)}}};\n\n"
text += "// Lookup Table for Green LED Channel\n"
text += f"int green_lookup[] = {{{', '.join(str(v) for v in g)}}};\n\n"
text += "// Lookup Table for Blue LED Channel\n"
text += f"int blue_lookup[] = {{{', '.join(str(v) for v in b)}}};\n\n"
import ipywidgets as widgets
from IPython.display import display, HTML, Javascript
mybtn = widgets.Button(description='copy C++ to clipboard', button_style='success')
def mybtn_event_handler(b):
print("copied")
clipboard.copy(text)
mybtn.on_click(mybtn_event_handler)
display(mybtn)
```
%% Output
zsh:1: parse error near `-m'
%% Cell type:code id:41562cc6-9911-4fb1-87ec-f2b3c8bfb3c2 tags:
``` python
from matplotlib import pyplot as plt
%matplotlib inline
import math
def draw(r):
l = len(r)
x = [x for x in range(l)]
fig = plt.figure(figsize=(8, 4))
ax = fig.add_axes([0, 0, 1, 1])
ax.axhline(y=0.5, color='black', linestyle='--')
ax.axvline(x=l/2, color='black', linestyle='--')
ax.set_xticks(range(0, l, 64))
ax.set_yticks(range(-l*2, l*2+1, 128))
ax.grid()
ax.plot(x, r)
def deadband(length, deadband=0.04):
readings = []
for i in range(length):
current_reading = i/(length-1)
scaler = (1.0) / (1.0 - deadband)
scaler += 0.1
if current_reading < 0.5:
current_reading += deadband
current_reading = min(0.5, current_reading)
current_reading = 0.5 - current_reading
current_reading *= scaler
current_reading = 0.5 - current_reading
# current_reading =
else:
current_reading -= deadband
current_reading = max(0.5, current_reading)
current_reading = 0.5 - current_reading
current_reading *= scaler
current_reading = 0.5 - current_reading
val = min(length, max(0, current_reading))
readings.append(val)
return readings
bip = deadband(16, deadband = 0.08)
draw(bip)
text = ""
text += "// Lookup Table for Bipolar Curve with deadband\n"
text += f"float bip_lookup[] = {{{', '.join(str(v) for v in bip)}}};\n\n"
import ipywidgets as widgets
from IPython.display import display, HTML, Javascript
mybtn = widgets.Button(description='copy C++ to clipboard', button_style='success')
def mybtn_event_handler(b):
print("copied")
clipboard.copy(text)
mybtn.on_click(mybtn_event_handler)
display(mybtn)
len(bip)
```
%% Output
16
%% Cell type:code id:ecc666b0-8195-4276-a576-39d41753b540 tags:
``` python
from matplotlib import pyplot as plt
%matplotlib inline
import math
import sys
def draw(r):
l = len(r)
x = [x for x in range(l)]
fig = plt.figure(figsize=(8, 4))
ax = fig.add_axes([0, 0, 1, 1])
ax.axhline(y=0.5, color='black', linestyle='--')
ax.set_xticks(range(0, l, 64))
ax.set_yticks(range(-l*2, l*2+1, 128))
ax.grid()
ax.plot(x, r)
def lin_to_log(length, strength=1.0):
# Limit to range 0.0 and 1.0
strength = min(1.0, max(0.0, strength))
readings = []
linear_readings = []
for i in range(length):
current_reading = i/length
linear_readings.append(current_reading)
# Log of 0 is error, so handle it explicitly
if i == 0:
current_reading = 0.0
else:
current_reading = math.log10(i)
readings.append(current_reading)
# Normalize to scale 0.1 to one
maxima = max(readings)
scaler = 1.0 / maxima
readings = [r*scaler for r in readings]
output = []
for i, r in enumerate(readings):
val = r*strength + linear_readings[i] * (1.0 - strength)
output.append(val)
# Convert to integer value range
output = [o for o in output]
return output
# lilo = lin_to_log(4096, strength=1.0)
lilo = lin_to_log(32, strength=1.0)
# lilo = [l/256.0 for l in lilo]
draw(lilo)
text = ""
text += "// Lookup Table for Logarithmic Curve\n"
text += f"float log_lookup[] = {{{', '.join(str(v) for v in lilo)}}};\n\n"
# print(text)
import ipywidgets as widgets
from IPython.display import display, HTML, Javascript
mybtn = widgets.Button(description='copy C++ to clipboard', button_style='success')
def mybtn_event_handler(b):
print("copied")
clipboard.copy(text)
mybtn.on_click(mybtn_event_handler)
display(mybtn)
min(lilo)
```
%% Output
0.0
%% Cell type:code id:2ecfda42-4a3c-489a-bc90-8576648c339c tags:
``` python
from matplotlib import pyplot as plt
%matplotlib inline
import math
import sys
def draw(r):
l = len(r)
x = [x for x in range(l)]
fig = plt.figure(figsize=(8, 4))
ax = fig.add_axes([0, 0, 1, 1])
ax.axhline(y=0.5, color='black', linestyle='--')
ax.set_xticks(range(0, l, 64))
ax.set_yticks(range(-l*2, l*2+1, 128))
ax.grid()
ax.plot(x, r)
def exp_lookup(length, strength=1.0):
# Limit to range 0.0 and 1.0
strength = min(1.0, max(0.0, strength))
readings = []
linear_readings = []
for i in range(length):
current_reading = i/length
linear_readings.append(current_reading)
# Log of 0 is error, so handle it explicitly
if i == 0:
current_reading = 0.0
else:
current_reading = i*i
readings.append(current_reading)
# Normalize to scale 0.1 to one
maxima = max(readings)
scaler = 1.0 / maxima
readings = [r*scaler for r in readings]
output = []
for i, r in enumerate(readings):
val = r*strength + linear_readings[i] * (1.0 - strength)
output.append(val)
# Convert to integer value range
output = [o for o in output]
return output
# lilo = lin_to_log(4096, strength=1.0)
lilo = exp_lookup(8, strength=1.0)
draw(lilo)
text = ""
text += "// Lookup Table for Exponential Curve\n"
text += f"float exp_lookup[] = {{{', '.join(str(v) for v in lilo)}}};\n\n"
# print(text)
import ipywidgets as widgets
from IPython.display import display, HTML, Javascript
mybtn = widgets.Button(description='copy C++ to clipboard', button_style='success')
def mybtn_event_handler(b):
print("copied")
clipboard.copy(text)
mybtn.on_click(mybtn_event_handler)
display(mybtn)
max(lilo)
```
%% Output
0.9999999999999999
%% Cell type:code id:e51416f3-f34d-4513-9f0c-fa52c468274e tags:
``` python
from matplotlib import pyplot as plt
%matplotlib inline
from ipywidgets import interact, FloatSlider
import matplotlib.transforms as transforms
import math
import clipboard
def draw(f):
fig = plt.figure(figsize=(8, 4))
ax = fig.add_axes([0, 0, 1, 1])
b = scan2d(x, y, f)
ax.axhline(y=b, color='red', linestyle='--')
ax.axvline(x=f, color='red', linestyle='--')
trans = transforms.blended_transform_factory(
ax.get_yticklabels()[0].get_transform(), ax.transData)
ax.text(0.95, b, "{:.02f}".format(b), color="red", transform=trans, ha="right", va="bottom")
ax.grid()
ax.plot(x, y)
def lerp(a, b, f=0.5) -> float:
f = min(1.0, max(0.0, f))
if f == 0.0:
return a
elif f == 1.0:
return b
else:
return a * (1.0-f) + b * f
def lerp2d(x1, y1, x2, y2, f=0.5):
if f == 0.0:
return [x1, x2]
elif f == 1.0:
return [x1, x2]
else:
x = lerp(x1, x2, f)
y = lerp(y1, y2, f)
return [x, y]
# A function that scans through two lists representing x/y values using a
# third value called f and returns the linear interpolation between those points
def scan2d(x, y, f):
# f = min(1.0, max(0.0, f))
assert len(x) == len(y)
# Find ax and bx for given factor
xa = None
last_value = None
idx = None
for i, v in enumerate(x):
# this = abs(f-v)
this = f-v
if xa is None or this > 0:
xa = this
idx = i
idx2 = min(idx+1, len(x)-1)
if idx == idx2:
return y[idx]
xa = x[idx]
xb = x[idx2]
ya = y[idx]
yb = y[idx2]
xspan = xb-xa
xscaler = 1/xspan
new_f = (f-xa)*xscaler
return lerp(ya, yb, new_f)
lines_orig = [
[0.0, 0.0, -0.5],
[0.45, 0.5, 0.0],
[0.55, 0.5, 1.0],
[1.0, 1.0, 0.0],
]
half_deadband = 0.005
lines_orig = [
[0.0, -1.0, 0.0],
[0.0+half_deadband, -1.0, 0.0],
]
steps = list(range(-9, 11))
for i in steps:
f = float(i)
print(f/10)
lines_orig.append([0.5+f/20-half_deadband, f/10, 0.0])
lines_orig.append([0.5+f/20+half_deadband, f/10, 0.0])
# Calculate curves for points of curvature
lines = []
for i, l in enumerate(lines_orig):
i2 = min(len(lines_orig)-1, i+1)
if l[2] == 0.0:
lines.append(l)
else:
xa = lines_orig[i][0]
xb = lines_orig[i2][0]
ya = lines_orig[i][1]
yb = lines_orig[i2][1]
x_span = xb-xa
y_span = yb-ya
x_step = 1/20
y_step = 1/20
for j in range(20):
x = x_step * j
y = y_step * j
y_curve = 0
if l[2] > 0.0:
y_curve = y*y*y
else:
y_curve = y*y
y = (1.0-l[2]) * y + l[2] * y_curve
lines.append([xa+x*x_span, ya+y*y_span, 0.0])
def make_lines(lines_orig, resolution=20):
lines = []
for i, l in enumerate(lines_orig):
i2 = min(len(lines_orig)-1, i+1)
if l[2] == 0.0:
lines.append(l)
else:
xa = lines_orig[i][0]
xb = lines_orig[i2][0]
ya = lines_orig[i][1]
yb = lines_orig[i2][1]
x_span = xb-xa
y_span = yb-ya
x_step = 1/20
y_step = 1/20
for j in range(resolution):
x = x_step * j
y = y_step * j
y_curve = 0
if l[2] > 0.0:
y_curve = y*y*y
else:
y_curve = y*y
y = (1.0-l[2]) * y + l[2] * y_curve
lines.append([xa+x*x_span, ya+y*y_span, 0.0])
return lines
lines = make_lines(lines_orig, 20)
x = [a[0] for a in lines]
y = [a[1] for a in lines]
c = [a[2] for a in lines]
# draw(x, y, 0.45/2)
interact(draw, f=FloatSlider(min=min(x), max=max(x), step=0.001, value=0.2))
length = len(x)
text = ""
text += "// Lookup Table for Pitch Knob\n"
text += f"float pitch_knob_lookup_x[] = {{{', '.join(str(xv) for xv in x)}}};\n"
text += f"float pitch_knob_lookup_y[] = {{{', '.join(str(yv) for yv in y)}}};\n"
text += f"size_t pitch_knob_lookup_length = {length};\n"
import ipywidgets as widgets
from IPython.display import display, HTML, Javascript
mybtn = widgets.Button(description='copy C++ to clipboard', button_style='success')
def mybtn_event_handler(b):
print("copied")
clipboard.copy(text)
mybtn.on_click(mybtn_event_handler)
display(mybtn)
```
%% Output
-0.9
-0.8
-0.7
-0.6
-0.5
-0.4
-0.3
-0.2
-0.1
0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0
%% Cell type:code id:f35f1609-3a10-4dce-b7dd-201d79f2c39c tags:
``` python
# Saturation curve
# X / Y / Curvature
lines_orig = [
[-1.5, -1.0, 1.0],
[-0.7, -0.7, 0.0],
[0.0, 0.0, 0.0],
[0.7, 0.7, -1.4],
[1.5, 1.0, 0.0],
]
lines = []
for i, l in enumerate(lines_orig):
i2 = min(len(lines_orig)-1, i+1)
if l[2] == 0.0:
lines.append(l)
else:
xa = lines_orig[i][0]
xb = lines_orig[i2][0]
ya = lines_orig[i][1]
yb = lines_orig[i2][1]
x_span = xb-xa
y_span = yb-ya
x_step = 1/20
y_step = 1/20
for j in range(8):
x = x_step * j
y = y_step * j
y_curve = 0
if l[2] > 0.0:
y_curve = y*y*y
else:
y_curve = y*y
y = (1.0-l[2]) * y + l[2] * y_curve
lines.append([xa+x*x_span, ya+y*y_span, 0.0])
lines = make_lines(lines_orig, 20)
x = [a[0] for a in lines]
y = [a[1]*0.5 for a in lines]
c = [a[2] for a in lines]
# draw(x, y, 0.45/2)
interact(draw, f=FloatSlider(min=min(x), max=max(x), step=0.001, value=0.2))
length = len(x)
text = ""
text += "// Lookup Curves for Saturation b\n"
text += f"float saturation_lookup_x[] = {{{', '.join(str(xv) for xv in x)}}};\n"
text += f"float saturation_lookup_y[] = {{{', '.join(str(yv) for yv in y)}}};\n"
text += f"size_t saturation_lookup_length = {length};\n"
import ipywidgets as widgets
from IPython.display import display, HTML, Javascript
mybtn = widgets.Button(description='copy C++ to clipboard', button_style='success')
def mybtn_event_handler(b):
print("copied")
clipboard.copy(text)
mybtn.on_click(mybtn_event_handler)
display(mybtn)
```
%% Output
%% Cell type:code id:f0cd9d06-a15a-46b4-a3ef-4aee3d4f7cd0 tags:
``` python
# Midi to pitch
# X / Y / Curvature
def draw_rgb(xr, yr, xg, yg, xb, yb):
fig = plt.figure(figsize=(8, 4))
ax = fig.add_axes([0, 0, 1, 1])
ax.grid()
ax.plot(xr, yr, 'r')
ax.plot(xg, yg, 'g')
ax.plot(xb, yb, 'b')
notes = [36, 48, 60]
for note in notes:
print((note-36)/12.0)
# BLUE
lines_b = [
[0, 0, 0.8],
[40, 10, -1.0],
[170, 0, 1.0],
]
lines_b = make_lines(lines_b, 16)
xb = [a[0] for a in lines_b]
yb = [a[1] for a in lines_b]
# Green
lines_g = [
[10, 0, 1.0],
[180, 60, -0.2],
[250, 0, 0.0],
]
lines_g = make_lines(lines_g, 16)
xg = [a[0] for a in lines_g]
yg = [a[1] for a in lines_g]
# RED
lines_r = [
[170, 0, 1.0],
[240, 30, 0.9],
[255, 255, 0.0],
]
lines_r = make_lines(lines_r, 16)
xr = [a[0] for a in lines_r]
yr = [a[1] for a in lines_r]
draw_rgb(xr, yr, xg, yg, xb, yb)
length = len(xr)
text = ""
text += "// Lookup Curves LED Red b\n"
text += f"float red_lut_x[] = {{{', '.join(str(xv) for xv in xr)}}};\n"
text += f"float red_lut_y[] = {{{', '.join(str(yv) for yv in yr)}}};\n"
text += f"size_t red_lut_len = {length};\n\n"
length = len(xg)
text += "// Lookup Curves LED Green b\n"
text += f"float green_lut_x[] = {{{', '.join(str(xv) for xv in xg)}}};\n"
text += f"float green_lut_y[] = {{{', '.join(str(yv) for yv in yg)}}};\n"
text += f"size_t green_lut_len = {length};\n\n"
length = len(xb)
text += "// Lookup Curves LED Blue b\n"
text += f"float blue_lut_x[] = {{{', '.join(str(xv) for xv in xb)}}};\n"
text += f"float blue_lut_y[] = {{{', '.join(str(yv) for yv in yb)}}};\n"
text += f"size_t blue_lut_len = {length};\n\n"
import ipywidgets as widgets
from IPython.display import display, HTML, Javascript
mybtn = widgets.Button(description='copy C++ to clipboard', button_style='success')
def mybtn_event_handler(b):
print("copied")
clipboard.copy(text)
mybtn.on_click(mybtn_event_handler)
display(mybtn)
```
%% Output
0.0
1.0
2.0
%% Cell type:code id:59b56dbc-6852-4989-bc19-3525ee7caf8b tags:
``` python
v = 1.0
math.log10(v * 10.0)
```
%% Output
1.0
%% Cell type:code id:5a511d24-cc91-450f-83e4-8295647d9391 tags:
``` python
```
......
......@@ -17,6 +17,7 @@
#include "looper.h"
#include "env_follower.h"
#include "helpers.h"
#include "luts.h"
#include "ui.h"
MIDI_CREATE_DEFAULT_INSTANCE();
......@@ -40,6 +41,7 @@ Oscillator lfo;
static SampleHold sample_and_hold;
static WhiteNoise noise;
static Metro tick;
static Easer easer;
// Initialize Buttons
Button button_1 = Button(D7);
......@@ -95,11 +97,17 @@ void AudioCallback(float **in, float **out, size_t size) {
// set the delay
delayline.SetDelay(delaytime);
// Iterate through the samples in the buffer
for (size_t i = 0; i < size; i++) {
uint8_t trig = tick.Process();
float lfo_value = lfo.Process();
float noise_value = noise.Process();
float rand = sample_and_hold.Process(trig, noise_value * 5.0f, sample_and_hold.MODE_SAMPLE_HOLD);
float rand = easer.Process(
sample_and_hold.Process(
trig,
noise_value * 5.0f,
sample_and_hold.MODE_SAMPLE_HOLD
));
if (ui.rec_source == REC_SOURCE_NOISE) {
ui.activeLooper()->Record(noise_value * 0.7f);
}
......@@ -113,6 +121,8 @@ void AudioCallback(float **in, float **out, size_t size) {
ui.activeLooper()->setPlaybackSpeed(pitch_val + midi_pitch_offset);
}
}
// Add the LFO to the
if (lfo_amount > 0.5f) {
ui.activeLooper()->setPlaybackSpeed(pitch_val + midi_pitch_offset);
} else {
......@@ -127,6 +137,7 @@ void AudioCallback(float **in, float **out, size_t size) {
ui.activeLooper()->Record(in[1][i]);
}
// Process the input envelope
input_envelope_follower.Process(in[1][i]);
// Process the Looper
......@@ -258,6 +269,9 @@ void setup() {
delayline.Init();
delayline.SetDelay(sample_rate);
// Easer for the random jumps
easer.setFactor(0.001);
// Start serial communications
Serial.begin(250000);
......@@ -343,7 +357,7 @@ void loop() {
ui.Render();
// Set the Color and brightness of the RGB LED in 8 bits
rgb_led.setAudioLevelIndicator(int(input_envelope_follower.getValue() * 255));
rgb_led.setAudioLevelIndicator(input_envelope_follower.getValue());
// MIDI
MIDI.read();
......
......@@ -5,6 +5,8 @@
#include "Adafruit_GFX.h"
extern Adafruit_SH1106G display;
int centeredText(const char *buf, int x, int y, int color, int lineheight=8) {
int16_t x1, y1;
uint16_t w, h;
......
#ifndef Leds_h
#define Leds_h
#include "Arduino.h"
#include "luts.h"
// Lookup Curves LED Red b
float red_lut_x[] = {170.0, 173.5, 177.0, 180.5, 184.0, 187.5, 191.0, 194.5, 198.0, 201.5, 205.0, 208.5, 212.0, 215.5, 219.0, 222.5, 240.0, 240.75, 241.5, 242.25, 243.0, 243.75, 244.5, 245.25, 246.0, 246.75, 247.5, 248.25, 249.0, 249.75, 250.5, 251.25, 255};
float red_lut_y[] = {0.0, 0.0037500000000000007, 0.030000000000000006, 0.10125000000000003, 0.24000000000000005, 0.46875, 0.8100000000000003, 1.2862500000000003, 1.9200000000000004, 2.7337500000000006, 3.75, 4.991250000000002, 6.480000000000002, 8.238750000000001, 10.290000000000003, 12.65625, 30.0, 31.1503125, 32.4525, 34.0584375, 36.12, 38.7890625, 42.2175, 46.5571875, 51.96, 58.5778125, 66.5625, 76.06593750000002, 87.24000000000001, 100.23656250000002, 115.20750000000002, 132.3046875, 255};
size_t red_lut_len = 33;
// Lookup Curves LED Green b
float green_lut_x[] = {10.0, 18.5, 27.0, 35.5, 44.0, 52.5, 61.00000000000001, 69.5, 78.0, 86.5, 95.0, 103.50000000000001, 112.00000000000001, 120.5, 129.0, 137.5, 180.0, 183.5, 187.0, 190.5, 194.0, 197.5, 201.0, 204.5, 208.0, 211.5, 215.0, 218.5, 222.0, 225.5, 229.0, 232.5, 250};
float green_lut_y[] = {0.0, 0.0075000000000000015, 0.06000000000000001, 0.20250000000000007, 0.4800000000000001, 0.9375, 1.6200000000000006, 2.5725000000000007, 3.8400000000000007, 5.467500000000001, 7.5, 9.982500000000003, 12.960000000000004, 16.477500000000003, 20.580000000000005, 25.3125, 60.0, 56.43, 52.92, 49.47, 46.08, 42.75, 39.48, 36.269999999999996, 33.120000000000005, 30.029999999999998, 27.000000000000007, 24.03, 21.119999999999997, 18.269999999999996, 15.480000000000004, 12.750000000000007, 0};
size_t green_lut_len = 33;
// Lookup Curves LED Blue b
float blue_lut_x[] = {0.0, 2.0, 4.0, 6.000000000000001, 8.0, 10.0, 12.000000000000002, 14.000000000000002, 16.0, 18.0, 20.0, 22.0, 24.000000000000004, 26.0, 28.000000000000004, 30.0, 40.0, 46.5, 53.0, 59.5, 66.0, 72.5, 79.0, 85.5, 92.0, 98.5, 105.0, 111.5, 118.00000000000001, 124.5, 131.0, 137.5, 170.0, 170.0, 170.0, 170.0, 170.0, 170.0, 170.0, 170.0, 170.0, 170.0, 170.0, 170.0, 170.0, 170.0, 170.0, 170.0};
float blue_lut_y[] = {0.0, 0.10099999999999998, 0.20799999999999996, 0.327, 0.46399999999999997, 0.6249999999999999, 0.8160000000000001, 1.0430000000000001, 1.312, 1.629, 1.9999999999999998, 2.4310000000000005, 2.928000000000001, 3.497, 4.144000000000001, 4.875, 10.0, 9.025, 8.1, 7.225, 6.4, 5.625, 4.9, 4.225, 3.5999999999999996, 3.0250000000000004, 2.5, 2.0249999999999986, 1.5999999999999996, 1.2250000000000014, 0.9000000000000004, 0.625, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
size_t blue_lut_len = 48;
// Lookup Table for Red LED Channel
int red_lookup[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 24, 24, 25, 27, 28, 31, 33, 37, 40, 45, 50, 56, 63, 70, 78, 88, 98, 109, 122, 135, 150, 166, 183, 202, 222, 243, 255, 255, 255, 255, 255};
// Lookup Table for Green LED Channel
int green_lookup[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 23, 24, 25, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40, 42, 43, 43, 43, 42, 42, 42, 42, 41, 41, 41, 41, 41, 40, 40, 40, 40, 39, 39, 39, 39, 39, 38, 38, 38, 38, 37, 37, 37, 37, 37, 36, 36, 36, 36, 35, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, 32, 32, 32, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 28, 28, 28, 27, 27, 27, 27, 26, 26, 26, 26, 26, 25, 25, 25, 25, 24, 24, 24, 24, 24, 23, 23, 23, 23, 22, 22, 22, 22, 21, 21, 21, 21, 21, 20, 20, 20, 20, 19, 19, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10, 9, 9, 9, 9, 8};
// Lookup Table for Blue LED Channel
int blue_lookup[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
class RGBLed {
int pin_red;
int pin_green;
int pin_blue;
float level = 0.0f;
Easer easer;
public:
RGBLed(int pin_red, int pin_green, int pin_blue);
void init();
void off();
void setColor(int r, int g, int b);
void setAudioLevelIndicator(int level);
void setAudioLevelIndicator(float envelope_value);
};
RGBLed::RGBLed(int pin_red, int pin_green, int pin_blue) {
this->pin_red = pin_red;
this->pin_green = pin_green;
this->pin_blue = pin_blue;
this->easer.setFactor(0.7);
}
void RGBLed::init() {
......@@ -52,9 +66,13 @@ void RGBLed::setColor(int r, int g, int b) {
analogWrite(this->pin_blue, b);
}
void RGBLed::setAudioLevelIndicator(int level) {
level = min(255, max(0, level));
this->setColor(red_lookup[level], green_lookup[level], blue_lookup[level]);
void RGBLed::setAudioLevelIndicator(float envelope_value) {
level = easer.Process(envelope_value);
int brightness = int(min(255.0f, max(0.0f, level * 255)));
int red = get_from_xy_table(red_lut_x, red_lut_y, brightness, red_lut_len);
int green = get_from_xy_table(green_lut_x, green_lut_y, brightness, green_lut_len);
int blue = get_from_xy_table(blue_lut_x, blue_lut_y, brightness, blue_lut_len);
this->setColor(red, green, blue);
}
#endif
\ No newline at end of file
......@@ -18,9 +18,27 @@ float saturation_lookup_y[] = {-0.5, -0.49998125, -0.49985, -0.49949375, -0.4988
size_t saturation_lookup_length = 19;
class Easer {
float output = 0.0f;
float delta = 0.0f;
float easing = 0.1f;
public:
Easer();
float Process(float input) {
delta = input - output;
output += delta * easing;
return output;
}
void setFactor(float factor) {
easing = min(max(0.00001f, factor), 1.0f);
}
};
Easer::Easer() {
};
float lerp(float a, float b, float f) {
......
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment