version 2.0

This commit is contained in:
Felix Klenner 2021-03-14 12:18:00 +01:00
parent 0879a90112
commit 27948a134b
12 changed files with 436 additions and 295 deletions

View file

@ -2,7 +2,7 @@
#define PIN 3 #define PIN 3
PololuLedStrip<PIN> leds; PololuLedStrip<PIN> leds;
#define LED_COUNT 256 #define LED_COUNT 512
#define BAUD 1000000 #define BAUD 1000000
rgb_color colors[LED_COUNT]; rgb_color colors[LED_COUNT];

View file

@ -0,0 +1,46 @@
#include <FastLED.h>
#define PIN 3
#define LED_COUNT 512
#define BAUD 1000000
CRGB leds[LED_COUNT];
void setup() {
FastLED.addLeds<NEOPIXEL, PIN>(leds, LED_COUNT);
Serial.begin(BAUD);
Serial.setTimeout(500);
}
// main program
void loop() {
byte buf[1];
unsigned int c=0;
while(Serial.read() != 255){
if(c > 100000){
for (uint16_t i = 0; i < LED_COUNT; i++){
leds[i] = CRGB(0,0,0);
}
FastLED.show();
}
c++;
}
if(c>1){
}
for (uint16_t i = 0; i < LED_COUNT; i++)
{
char col[3];
Serial.readBytes(col, 3);
leds[i] = CRGB(col[0], col[1], col[2]);
}
FastLED.show();
}

View file

@ -0,0 +1,44 @@
#include <Adafruit_NeoPixel.h>
#define PIN 3
#define LED_COUNT 512
#define BAUD 1000000
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_COUNT, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin();
strip.show();
Serial.begin(BAUD);
Serial.setTimeout(500);
}
// main program
void loop() {
byte buf[1];
unsigned int c=0;
while(Serial.read() != 255){
if(c > 100000){
for (uint16_t i = 0; i < LED_COUNT; i++){
strip.setPixelColor(i, strip.Color(0,0,0));
}
strip.show();
}
c++;
}
if(c>1){
}
for (uint16_t i = 0; i < LED_COUNT; i++)
{
char col[3];
Serial.readBytes(col, 3);
strip.setPixelColor(i, strip.Color(col[0], col[1], col[2]));
}
strip.show();
}

View file

@ -16,8 +16,8 @@ public class EffectManager {
private boolean sweep = false; private boolean sweep = false;
private final LEDEffect[] effects = new LEDEffect[]{new ClockEffect(),new AudioVolumeEffect(), new NetworkSpeedEffect(), new SineEffect(), new AudioFFTEffect(), new ColorSweepEffect()}; private final LEDEffect[] effects = new LEDEffect[]{new ClockEffect(), new AudioVolumeEffect(), new NetworkSpeedEffect(), new SineEffect(), new AudioFFTEffect(), new ColorSweepEffect()};
private int activeId = 0; private int activeId = 4;
private final TrayIcon trayIcon; private final TrayIcon trayIcon;
public EffectManager() { public EffectManager() {
@ -28,7 +28,7 @@ public class EffectManager {
trayIcon.addMouseListener(new MouseListener() { trayIcon.addMouseListener(new MouseListener() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
switch (e.getButton()){ switch (e.getButton()) {
case MouseEvent.BUTTON1: case MouseEvent.BUTTON1:
loadNext(); loadNext();
break; break;
@ -65,20 +65,26 @@ public class EffectManager {
} }
new Timer(30 * 1000, e -> { new Timer(30 * 1000, e -> {
if(sweep) if (sweep)
loadNext(); loadNext();
}).start(); }).start();
loadNext(); loadNext(true);
} }
private void loadNext() { private void loadNext() {
loadNext(false);
}
private void loadNext(boolean first) {
if (!first) {
getActiveEffect().unload(); getActiveEffect().unload();
activeId++; activeId++;
if (activeId == effects.length) if (activeId == effects.length)
activeId = 0; activeId = 0;
}
getActiveEffect().load(); getActiveEffect().load();
trayIcon.setToolTip("LEDEffects - " + getActiveEffect().getDescription()+ (sweep?" (autoswitch)":"")); trayIcon.setToolTip("LEDEffects - " + getActiveEffect().getDescription() + (sweep ? " (autoswitch)" : ""));
} }
public LEDEffect getActiveEffect() { public LEDEffect getActiveEffect() {

View file

@ -11,10 +11,11 @@ import java.awt.image.BufferedImage;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
public class LEDControl { public class LEDControl {
public static final int WIDTH = 16; public static final int WIDTH = 32;
public static final int HEIGHT = 16; public static final int HEIGHT = 16;
public static final int LED_NUM = WIDTH * HEIGHT; public static final int LED_NUM = WIDTH * HEIGHT;
public static final int BAUD = 1000000; public static final int BAUD = 1000000;
private static final int FRAME_MS = 40;
private SerialPort port; private SerialPort port;
@ -37,7 +38,8 @@ public class LEDControl {
long iteration = 0; long iteration = 0;
long minTimeDelta = Long.MAX_VALUE, long minTimeDelta = Long.MAX_VALUE,
maxTimeDelta = 0; maxTimeDelta = 0,
avgTimeDelta = 0;
while (true) { while (true) {
if (port == null || !port.isOpen()) { if (port == null || !port.isOpen()) {
@ -48,10 +50,11 @@ public class LEDControl {
} }
long timeDelta = System.nanoTime() - time; long timeDelta = System.nanoTime() - time;
if(timeDelta > maxTimeDelta) if (timeDelta > maxTimeDelta)
maxTimeDelta = timeDelta; maxTimeDelta = timeDelta;
if(timeDelta < minTimeDelta) if (timeDelta < minTimeDelta)
minTimeDelta = timeDelta; minTimeDelta = timeDelta;
avgTimeDelta += timeDelta;
time = System.nanoTime(); time = System.nanoTime();
renderFrame(timeDelta); renderFrame(timeDelta);
@ -68,12 +71,13 @@ public class LEDControl {
} }
} }
sleep(10); sleep(FRAME_MS);//(int) (FRAME_MS) - ((System.nanoTime()-time)/1000000)));
if (iteration % 1000 == 1) { if (iteration % 1000 == 0 && iteration > 0) {
System.out.println("Frametime: " + (Math.round(timeDelta) / 100000) / 10.0 + "ms ("+(Math.round(minTimeDelta) / 100000) / 10.0+"ms - "+(Math.round(maxTimeDelta) / 100000) / 10.0+"ms) " + iteration + " Frames"); System.out.println("Frametime: " + (Math.round(avgTimeDelta / 1000.0) / 100000) / 10.0 + "ms (" + (Math.round(minTimeDelta) / 100000) / 10.0 + "ms - " + (Math.round(maxTimeDelta) / 100000) / 10.0 + "ms) " + iteration + " Frames");
minTimeDelta = Long.MAX_VALUE; minTimeDelta = Long.MAX_VALUE;
maxTimeDelta = 0; maxTimeDelta = 0;
avgTimeDelta = 0;
} }
iteration++; iteration++;
} }
@ -113,7 +117,7 @@ public class LEDControl {
} }
private void renderFrame(long timeDelta) { private void renderFrame(long timeDelta) {
BufferedImage image = new BufferedImage(16 * eff.getActiveEffect().getScale(), 16 * eff.getActiveEffect().getScale(), BufferedImage.TYPE_INT_ARGB); BufferedImage image = new BufferedImage(WIDTH * eff.getActiveEffect().getScale(), HEIGHT * eff.getActiveEffect().getScale(), BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics(); Graphics g = image.getGraphics();
eff.getActiveEffect().render(timeDelta, g); eff.getActiveEffect().render(timeDelta, g);
g.dispose(); g.dispose();

View file

@ -0,0 +1,167 @@
package de.zuim.ledcontrol.effects;
import com.tagtraum.jipes.math.FFTFactory;
import com.tagtraum.jipes.math.Transform;
import de.zuim.ledcontrol.LEDEffect;
import javax.sound.sampled.*;
import java.util.ArrayList;
import java.util.List;
public abstract class AudioEffect implements LEDEffect {
private final List<AudioData> cachedAudioData = new ArrayList<>();
private final static int BUFFERSIZE = 4096;
private Thread audioThread = null;
@Override
public void load() {
Runnable audioRunnable = () -> {
Mixer.Info[] mixers = AudioSystem.getMixerInfo();
List<Line.Info> availableTargetLines = new ArrayList<>();
for (Mixer.Info mixerInfo : mixers) {
Mixer m = AudioSystem.getMixer(mixerInfo);
Line.Info[] lines = m.getTargetLineInfo();
System.out.println(mixerInfo);
for (Line.Info li : lines) {
try {
if (li instanceof DataLine.Info && mixerInfo.toString().contains("default")) {
m.open();
System.out.println("(" + availableTargetLines.size() + ") Found target line: " + li + " " + mixerInfo + "(" + li.getClass() + ")");
availableTargetLines.add(li);
m.close();
}
} catch (LineUnavailableException e) {
System.out.println("Line unavailable.");
}
}
}
DataLine.Info targetLineInfo = (DataLine.Info) availableTargetLines.get(0);
System.out.println("SUPPORTED TARGET FORMATS: ");
AudioFormat[] formats = (targetLineInfo).getFormats();
for (int i = 0; i < formats.length; i++) {
System.out.println("(" + i + ")" + formats[i]);
}
AudioFormat format = formats[64];
System.out.println("SELECTED: " + format);
final DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
final AudioInputStream audioStream;
//verbesserung: https://stackoverflow.com/a/51240462
try {
TargetDataLine targetLine = (TargetDataLine) AudioSystem.getLine(info);
targetLine.open();
targetLine.start();
audioStream = new AudioInputStream(targetLine);
final byte[] buf = new byte[BUFFERSIZE];
final int numberOfSamples = buf.length / format.getFrameSize();
final Transform fft = FFTFactory.getInstance().create(numberOfSamples);
while (audioThread != null) {
int read = audioStream.read(buf);
float[] fBuf = decode(buf, format);
final float[][] transformed = fft.transform(fBuf);
final float[] realPart = transformed[0];
final float[] imaginaryPart = transformed[1];
double[] magnitudes = toMagnitudes(realPart, imaginaryPart);
cachedAudioData.add(new AudioData(magnitudes, targetLine.getLevel()));
/*System.out.println("M"+ Arrays.toString(magnitudes));
float max = 0, avg = 0, min = 11111111;
for (float m : fBuf) {
avg += m;
if (m > max)
max = (int) m;
if (m < min)
min = (int) m;
}
System.out.println("M"+ max+" "+min+" "+avg/fBuf.length+ " "+read+" "+fBuf.length);*/
}
audioStream.close();
targetLine.close();
} catch (Exception e) {
e.printStackTrace();
}
};
audioThread = new Thread(audioRunnable);
audioThread.start();
}
@Override
public void unload() {
if (audioThread != null && audioThread.isAlive())
audioThread = null;
}
public List<AudioData> getData() {
return cachedAudioData;
}
public int getMagnitudeLength() {
return cachedAudioData.isEmpty() ? 0 : cachedAudioData.get(0).magnitudes.length;
}
private static float[] decode(final byte[] buf, final AudioFormat format) {
final float[] fbuf = new float[buf.length / format.getFrameSize()];
for (int pos = 0; pos < buf.length; pos += format.getFrameSize()) {
final int sample = format.isBigEndian()
? byteToIntBigEndian(buf, pos, format.getFrameSize())
: byteToIntLittleEndian(buf, pos, format.getFrameSize());
// normalize to [0,1]
fbuf[pos / format.getFrameSize()] = sample / (Short.MAX_VALUE + 1.0f);
}
return fbuf;
}
private static double[] toMagnitudes(final float[] realPart, final float[] imaginaryPart) {
final double[] powers = new double[realPart.length / 2];
for (int i = 0; i < powers.length; i++) {
powers[i] = Math.sqrt(realPart[i] * realPart[i] + imaginaryPart[i] * imaginaryPart[i]);
}
return powers;
}
private static int byteToIntLittleEndian(final byte[] buf, final int offset, final int bytesPerSample) {
int sample = 0;
for (int byteIndex = 0; byteIndex < bytesPerSample; byteIndex++) {
final int aByte = buf[offset + byteIndex] & 0xff;
sample += aByte << 8 * (byteIndex);
}
return sample;
}
private static int byteToIntBigEndian(final byte[] buf, final int offset, final int bytesPerSample) {
int sample = 0;
for (int byteIndex = 0; byteIndex < bytesPerSample; byteIndex++) {
final int aByte = buf[offset + byteIndex] & 0xff;
sample += aByte << (8 * (bytesPerSample - byteIndex - 1));
}
return sample;
}
static class AudioData {
public double[] magnitudes;
public float level;
public AudioData(double[] magnitudes, float level) {
this.magnitudes = magnitudes;
this.level = level;
}
}
}

View file

@ -1,193 +1,63 @@
package de.zuim.ledcontrol.effects; package de.zuim.ledcontrol.effects;
import com.tagtraum.jipes.math.FFTFactory;
import com.tagtraum.jipes.math.Transform;
import de.zuim.ledcontrol.LEDEffect;
import javax.sound.sampled.*;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.Arrays;
import java.util.List;
import static de.zuim.ledcontrol.LEDControl.HEIGHT; import static de.zuim.ledcontrol.LEDControl.HEIGHT;
import static de.zuim.ledcontrol.LEDControl.WIDTH; import static de.zuim.ledcontrol.LEDControl.WIDTH;
public class AudioFFTEffect implements LEDEffect { public class AudioFFTEffect extends AudioEffect {
@Override @Override
public String getDescription() { public String getDescription() {
return "Audio FFT"; return "Audio FFT";
} }
final static int BUFFERSIZE = 2048;
float[] fbuf = null;
double[] magnitudes = null;
Thread audioThread = null;
@Override
public void load() {
Runnable audioRunnable = () -> {
Mixer.Info[] mixers = AudioSystem.getMixerInfo();
List<Line.Info> availableTargetLines = new ArrayList<>();
for (Mixer.Info mixerInfo : mixers) {
Mixer m = AudioSystem.getMixer(mixerInfo);
Line.Info[] lines = m.getTargetLineInfo();
System.out.println(mixerInfo);
for (Line.Info li : lines) {
try {
if (li instanceof DataLine.Info && mixerInfo.toString().contains("mix")) {
m.open();
System.out.println("(" + availableTargetLines.size() + ") Found target line: " + li + " " + mixerInfo + "(" + li.getClass() + ")");
availableTargetLines.add(li);
m.close();
}
} catch (LineUnavailableException e) {
System.out.println("Line unavailable.");
}
}
}
DataLine.Info targetLineInfo = (DataLine.Info) availableTargetLines.get(0);
System.out.println("SUPPORTED TARGET FORMATS: ");
AudioFormat[] formats = (targetLineInfo).getFormats();
for (int i = 0; i < formats.length; i++) {
System.out.println("(" + i + ")" + formats[i]);
}
AudioFormat format = formats[2];
System.out.println("SELECTED: " + format);
final DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
final AudioInputStream audioStream;
//verbesserung: https://stackoverflow.com/a/51240462
try {
TargetDataLine targetLine = (TargetDataLine) AudioSystem.getLine(info);
targetLine.open();
targetLine.start();
audioStream = new AudioInputStream(targetLine);
final byte[] buf = new byte[BUFFERSIZE];
final int numberOfSamples = buf.length / format.getFrameSize();
final Transform fft = FFTFactory.getInstance().create(numberOfSamples);
while (audioThread != null) {
int read = audioStream.read(buf);
fbuf = decode(buf, format);
final float[][] transformed = fft.transform(fbuf);
final float[] realPart = transformed[0];
final float[] imaginaryPart = transformed[1];
magnitudes = toMagnitudes(realPart, imaginaryPart);
//System.out.println("M"+ Arrays.toString(magnitudes));
int max = 0, avg = 0, min = 11111111;
for (double m : magnitudes) {
avg += m;
if (m > max)
max = (int) m;
if (m < min)
min = (int) m;
}
//System.out.println("M"+ max+" "+min+" "+avg/magnitudes.length+ " "+read+" "+magnitudes.length);
}
audioStream.close();
targetLine.close();
} catch (Exception e) {
e.printStackTrace();
}
};
audioThread = new Thread(audioRunnable);
audioThread.start();
}
@Override
public void unload() {
if (audioThread != null && audioThread.isAlive())
audioThread = null;
}
@Override @Override
public void render(long timeDelta, Graphics g) { public void render(long timeDelta, Graphics g) {
double[] avg = null;
if (!getData().isEmpty()) {
avg = new double[getMagnitudeLength()];
for (int i = 0; i < getMagnitudeLength(); i++) {
for (int j = 0; j < getData().size(); j++) {
avg[i] += getData().get(j).magnitudes[i];
}
avg[i] = avg[i] / getData().size();
}
getData().clear();
getData().add(new AudioData(avg, -1));
for (int x = 0; x < WIDTH; x++) { for (int x = 0; x < WIDTH; x++) {
double val = 0; double val = 0;
int ignoreMagnitudes = 6;
double base = Math.exp(Math.log(avg.length ) / (WIDTH + ignoreMagnitudes));
if (magnitudes != null) { int intervalStart = (int) Math.pow(base, x + ignoreMagnitudes),
double base = Math.exp(Math.log(magnitudes.length/2)/(WIDTH+3)); intervalEnd = (int) Math.pow(base, x + ignoreMagnitudes + 1);
int intervalStart = (int) Math.pow(base,x+3),
intervalEnd = (int) Math.pow(base,x+4);
//System.out.println(x+" "+intervalStart+"-"+intervalEnd); //System.out.println(x+" "+intervalStart+"-"+intervalEnd);
for(int magPos = intervalStart; magPos < intervalEnd; magPos++){ for (int magPos = intervalStart; magPos < intervalEnd; magPos++) {
val += magnitudes[magPos]; val += avg[magPos];
} }
val /= intervalEnd-intervalStart; val /= intervalEnd - intervalStart;
/* /*
int magnitudesInPixel = (magnitudes.length / WIDTH) / 20; int magnitudesInPixel = (avg.length / WIDTH) / 2;
for (int sample = 0; sample < magnitudesInPixel; sample++) { for (int sample = 0; sample < magnitudesInPixel; sample++) {
val += magnitudes[x * magnitudesInPixel + sample]; val += avg[x * magnitudesInPixel + sample];
} }
val /= (double) magnitudes.length / WIDTH;*/ val /= (double) avg.length / WIDTH;*/
} val*=1+Math.pow(2, x/((double)WIDTH*.5));
int y = (int) Math.min(HEIGHT,Math.round(Math.max(1, val+10))/10);
int y = (int) Math.min(HEIGHT, Math.round(Math.max(1, val + 10)) / 30);
g.setColor(new Color(Math.abs(y) + 1, 2, 0)); g.setColor(new Color(Math.abs(y) + 1, 2, 0));
g.drawRect(x, HEIGHT - y, 0, HEIGHT); g.drawRect(x, HEIGHT - y, 0, HEIGHT);
g.setColor(new Color(Math.abs(y), 0, 0)); g.setColor(new Color(Math.abs(y), 0, 0));
g.drawRect(x, HEIGHT - y, 0, 0); g.drawRect(x, HEIGHT - y, 0, 0);
} }
} }
private static float[] decode(final byte[] buf, final AudioFormat format) {
final float[] fbuf = new float[buf.length / format.getFrameSize()];
for (int pos = 0; pos < buf.length; pos += format.getFrameSize()) {
final int sample = format.isBigEndian()
? byteToIntBigEndian(buf, pos, format.getFrameSize())
: byteToIntLittleEndian(buf, pos, format.getFrameSize());
// normalize to [0,1]
fbuf[pos / format.getFrameSize()] = sample / (Short.MAX_VALUE + 1.0f);
}
return fbuf;
} }
private static double[] toMagnitudes(final float[] realPart, final float[] imaginaryPart) {
final double[] powers = new double[realPart.length / 2];
for (int i = 0; i < powers.length; i++) {
powers[i] = Math.sqrt(realPart[i] * realPart[i] + imaginaryPart[i] * imaginaryPart[i]);
}
return powers;
}
private static int byteToIntLittleEndian(final byte[] buf, final int offset, final int bytesPerSample) {
int sample = 0;
for (int byteIndex = 0; byteIndex < bytesPerSample; byteIndex++) {
final int aByte = buf[offset + byteIndex] & 0xff;
sample += aByte << 8 * (byteIndex);
}
return sample;
}
private static int byteToIntBigEndian(final byte[] buf, final int offset, final int bytesPerSample) {
int sample = 0;
for (int byteIndex = 0; byteIndex < bytesPerSample; byteIndex++) {
final int aByte = buf[offset + byteIndex] & 0xff;
sample += aByte << (8 * (bytesPerSample - byteIndex - 1));
}
return sample;
}
} }

View file

@ -21,17 +21,19 @@ public class AudioVolumeEffect extends AudioFFTEffect {
public void render(long timeDelta, Graphics g) { public void render(long timeDelta, Graphics g) {
timeDeltaSum += timeDelta; timeDeltaSum += timeDelta;
if (fbuf != null) { if (!getData().isEmpty()) {
float avg = 0; /*float avg = 0;
float max = 0; float max = 0;
for (float v : fbuf) { for (double v : getData().get(0)) {
avg += Math.abs(v); avg += Math.abs(v);
if (v > max) { if (v > max) {
max = v; max = (float) v;
} }
} }
avg /= fbuf.length; avg /= cachedMagnitudes.get(0).length;*/
volHistory.add((int) (5 * avg)); System.out.println(getData().get(0).level);
volHistory.add((int) (getData().get(0).level * 100));
getData().clear();
} }
if (volHistory.size() > WIDTH) { if (volHistory.size() > WIDTH) {
@ -41,7 +43,7 @@ public class AudioVolumeEffect extends AudioFFTEffect {
for (int x = 0; x < volHistory.size(); x++) { for (int x = 0; x < volHistory.size(); x++) {
g.setColor(new Color((int) ((Math.abs(volHistory.get(x)) + 1) * ((WIDTH - x) / (float) WIDTH)), 2, 0)); g.setColor(new Color((int) ((Math.abs(volHistory.get(x)) + 1) * ((WIDTH - x) / (float) WIDTH)), 2, 0));
g.drawRect(WIDTH - x - 1, HEIGHT - volHistory.get(x), 0, HEIGHT); g.drawRect(x, HEIGHT - volHistory.get(x), 0, HEIGHT);
} }
} }

View file

@ -9,8 +9,8 @@ import java.util.Date;
import static de.zuim.ledcontrol.LEDControl.HEIGHT; import static de.zuim.ledcontrol.LEDControl.HEIGHT;
public class ClockEffect implements LEDEffect { public class ClockEffect implements LEDEffect {
private Font font = new Font("Calibri", Font.BOLD, 12*getScale()); private Font font = new Font("crosextra-carlito", Font.BOLD, 10 * getScale());
private double posOffset = 0; private double posOffset = 3;
@Override @Override
public String getDescription() { public String getDescription() {
@ -18,30 +18,31 @@ public class ClockEffect implements LEDEffect {
} }
int iteration = 0; int iteration = 0;
public void fontSwitcher(){
if(++iteration%100==0){ public void fontSwitcher() {
if (++iteration % 100 == 0) {
Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
font = new Font(allFonts[iteration/100].getFontName(), Font.PLAIN, 10*getScale()); font = new Font(allFonts[iteration / 100].getFontName(), Font.PLAIN, 10 * getScale());
System.out.println(allFonts[iteration/100].getFontName()); System.out.println(allFonts[iteration / 100].getFontName());
} }
} }
public void render(long timeDelta, Graphics g) { public void render(long timeDelta, Graphics g) {
//fontSwitcher(); fontSwitcher();
Date date = new Date(); Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat(" H:mm"); SimpleDateFormat formatter = new SimpleDateFormat("H:mm");
String text = formatter.format(date); String text = formatter.format(date);
SimpleDateFormat formatter2 = new SimpleDateFormat("ss"); SimpleDateFormat formatter2 = new SimpleDateFormat("ss");
String text2 = formatter2.format(date); String text2 = formatter2.format(date);
g.setFont(font); g.setFont(font);
g.setColor(new Color(0,10-date.getMinutes()/6,date.getMinutes()/6)); g.setColor(new Color(0, 10 - date.getMinutes() / 6, date.getMinutes() / 6));
posOffset-=(4*getScale()*timeDelta)/1000000000.0; //posOffset-=(4*getScale()*timeDelta)/1000000000.0;
g.drawString(text, (int) posOffset, HEIGHT/2*getScale()); g.drawString(text, (int) posOffset, HEIGHT / 2 * getScale());
g.setColor(new Color(10-date.getSeconds()/6,date.getSeconds()/6,0)); g.setColor(new Color(10 - date.getSeconds() / 6, date.getSeconds() / 6, 0));
g.drawString(text2, 2, HEIGHT*getScale()); g.drawString(text2, 5, HEIGHT * getScale());
if(posOffset<-g.getFontMetrics().stringWidth(text)) if (posOffset < -g.getFontMetrics().stringWidth(text))
posOffset=0; posOffset = 0;
} }
} }

View file

@ -14,13 +14,14 @@ public class ColorSweepEffect implements LEDEffect {
} }
float step = 0; float step = 0;
@Override @Override
public void render(long timeDelta, Graphics gr) { public void render(long timeDelta, Graphics gr) {
step += timeDelta*0.0000000001d; step += timeDelta * 0.0000000001d;
if(step > 1) if (step > 1)
step=0; step = 0;
gr.setColor(Color.getHSBColor(step,1f,15f/255f)); gr.setColor(Color.getHSBColor(step, 1f, 5f / 255f));
gr.fillRect(0,0,WIDTH,HEIGHT); gr.fillRect(0, 0, WIDTH, HEIGHT);
} }
} }

View file

@ -13,8 +13,8 @@ import static de.zuim.ledcontrol.LEDControl.WIDTH;
public class NetworkSpeedEffect implements LEDEffect { public class NetworkSpeedEffect implements LEDEffect {
private static final int MAX_UPLOAD_MBIT_S = 33; private static final int MAX_UPLOAD_MBIT_S = 290;
private static final int MAX_DOWNLOAD_MBIT_S = 330; private static final int MAX_DOWNLOAD_MBIT_S = 500;
private static final long NANOS_PER_PIXEL = 1000000000; private static final long NANOS_PER_PIXEL = 1000000000;
@Override @Override
@ -26,14 +26,14 @@ public class NetworkSpeedEffect implements LEDEffect {
@Override @Override
public void load() { public void load() {
if(network == null){ if (network == null) {
SystemInfo si = new SystemInfo(); SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware(); HardwareAbstractionLayer hal = si.getHardware();
network = hal.getNetworkIFs().get(0); network = hal.getNetworkIFs().get(2);
} }
} }
private final Font font = new Font("Calibri", Font.BOLD, 9*getScale()); private final Font font = new Font("crosextra-carlito", Font.BOLD, 7 * getScale());
long lastDownBytes = 0, lastUpBytes = 0; long lastDownBytes = 0, lastUpBytes = 0;
private final List<Measurement> history = new ArrayList<>(); private final List<Measurement> history = new ArrayList<>();
@ -42,39 +42,39 @@ public class NetworkSpeedEffect implements LEDEffect {
@Override @Override
public void render(long timeDelta, Graphics g) { public void render(long timeDelta, Graphics g) {
nanosElapsed+=timeDelta; nanosElapsed += timeDelta;
if(network != null && nanosElapsed > NANOS_PER_PIXEL){ if (network != null && nanosElapsed > NANOS_PER_PIXEL) {
network.updateAttributes(); network.updateAttributes();
double factor_MBit = (8*1000000000.0)/(1000*1000*nanosElapsed); double factor_MBit = (8 * 1000000000.0) / (1000 * 1000 * nanosElapsed);
double up_speed = ((network.getBytesSent() - lastUpBytes)*(factor_MBit)); double up_speed = ((network.getBytesSent() - lastUpBytes) * (factor_MBit));
double down_speed = ((network.getBytesRecv() - lastDownBytes)*(factor_MBit)); double down_speed = ((network.getBytesRecv() - lastDownBytes) * (factor_MBit));
lastUpBytes = network.getBytesSent(); lastUpBytes = network.getBytesSent();
lastDownBytes = network.getBytesRecv(); lastDownBytes = network.getBytesRecv();
history.add(new Measurement((int) (Math.round((HEIGHT*up_speed) / MAX_UPLOAD_MBIT_S)), (int) (Math.round((HEIGHT*down_speed) / MAX_DOWNLOAD_MBIT_S)))); history.add(new Measurement((int) (Math.round((HEIGHT * up_speed) / MAX_UPLOAD_MBIT_S)), (int) (Math.round((HEIGHT * down_speed) / MAX_DOWNLOAD_MBIT_S))));
if(history.size()>WIDTH){ if (history.size() > WIDTH) {
history.remove(0); history.remove(0);
} }
uploadText = Math.round(up_speed)+""; uploadText = Math.round(up_speed) + "";
downloadText = Math.round(down_speed)+""; downloadText = Math.round(down_speed) + "";
//System.out.println(up_speed+" "+down_speed); //System.out.println(up_speed+" "+down_speed);
nanosElapsed = 0; nanosElapsed = 0;
} }
if(history.size() > 1){ if (history.size() > 1) {
g.setFont(font); g.setFont(font);
g.setColor(new Color(1, 0, 0)); g.setColor(new Color(1, 0, 0));
g.drawString(downloadText, WIDTH-g.getFontMetrics().stringWidth(downloadText), HEIGHT*getScale()-3); g.drawString(downloadText, WIDTH - g.getFontMetrics().stringWidth(downloadText), HEIGHT * getScale() - 3);
g.setColor(new Color(0, 1, 0)); g.setColor(new Color(0, 1, 0));
g.drawString(uploadText, WIDTH-g.getFontMetrics().stringWidth(uploadText), HEIGHT/2*getScale()-2); g.drawString(uploadText, WIDTH - g.getFontMetrics().stringWidth(uploadText), HEIGHT / 2 * getScale() - 2);
for(int x = 0; x < WIDTH && x < history.size(); x++){ for (int x = 0; x < WIDTH && x < history.size(); x++) {
boolean firstUp = history.get(x).upY > history.get(x).downY; boolean firstUp = history.get(x).upY > history.get(x).downY;
drawMeasurement(g, x, firstUp); drawMeasurement(g, x, firstUp);
drawMeasurement(g, x, !firstUp); drawMeasurement(g, x, !firstUp);
@ -82,16 +82,15 @@ public class NetworkSpeedEffect implements LEDEffect {
} }
} }
private void drawMeasurement(Graphics g, int x, boolean up){ private void drawMeasurement(Graphics g, int x, boolean up) {
int offset = WIDTH - history.size(); int offset = WIDTH - history.size();
if(up){ if (up) {
g.setColor(new Color(0, 1, 0)); g.setColor(new Color(0, 1, 0));
g.drawLine(x + offset, HEIGHT - history.get(x).upY, x + offset, HEIGHT - 1); g.drawLine(x + offset, HEIGHT - history.get(x).upY, x + offset, HEIGHT - 1);
g.setColor(new Color(0, 7, 0)); g.setColor(new Color(0, 7, 0));
g.drawRect(x + offset, HEIGHT - 1 - history.get(x).upY, 0, 0); g.drawRect(x + offset, HEIGHT - 1 - history.get(x).upY, 0, 0);
//g.drawLine(x + offset, HEIGHT - 1 - history.get(x).upY, x + offset + 1, HEIGHT - 1 - history.get(x+1).upY); //g.drawLine(x + offset, HEIGHT - 1 - history.get(x).upY, x + offset + 1, HEIGHT - 1 - history.get(x+1).upY);
} } else {
else{
g.setColor(new Color(1, 0, 0)); g.setColor(new Color(1, 0, 0));
g.drawLine(x + offset, HEIGHT - history.get(x).downY, x + offset, HEIGHT - 1); g.drawLine(x + offset, HEIGHT - history.get(x).downY, x + offset, HEIGHT - 1);
g.setColor(new Color(7, 0, 0)); g.setColor(new Color(7, 0, 0));
@ -100,7 +99,7 @@ public class NetworkSpeedEffect implements LEDEffect {
} }
} }
static class Measurement{ static class Measurement {
public int upY; public int upY;
public int downY; public int downY;

View file

@ -10,34 +10,35 @@ import static de.zuim.ledcontrol.LEDControl.WIDTH;
public class SineEffect implements LEDEffect { public class SineEffect implements LEDEffect {
private Random r = new Random(); private final Random r = new Random();
private double[][] seeds = new double[10][7]; private final double[][] seeds = new double[10][7];
@Override @Override
public void load() { public void load() {
for(double[] seed : seeds){ for (double[] seed : seeds) {
for(int i = 0; i < seed.length; i++){ for (int i = 0; i < seed.length; i++) {
seed[i] = r.nextDouble(); seed[i] = r.nextDouble();
} }
} }
} }
double steps = 0; double steps = 0;
@Override @Override
public void render(long timeDelta, Graphics g) { public void render(long timeDelta, Graphics g) {
steps += timeDelta*0.000000001; steps += timeDelta * 0.000000001;
for(int i = 0; i < 6; i++){ for (int i = 0; i < 6; i++) {
g.setColor(new Color((int) (15*seeds[i][0]), (int) (10*seeds[i][3]),(int)(4*seeds[i][4]))); g.setColor(new Color((int) (15 * seeds[i][0]), (int) (10 * seeds[i][3]), (int) (4 * seeds[i][4])));
for (int x = 0; x < WIDTH*getScale(); x++){ for (int x = 0; x < WIDTH * getScale(); x++) {
g.drawLine(x, calc(i, x),x+1,calc(i, x+1)); g.drawLine(x, calc(i, x), x + 1, calc(i, x + 1));
} }
} }
} }
private int calc(int i, int x){ private int calc(int i, int x) {
return (int) (Math.sin(((x+2*seeds[i][2])*0.5*seeds[i][1])/getScale()+steps*seeds[i][6])*7*getScale()*(seeds[i][5]+0.2) + (getScale()*HEIGHT)/2); return (int) (Math.sin(((x + 2 * seeds[i][2]) * 0.5 * seeds[i][1]) / getScale() + steps * seeds[i][6]) * 7 * getScale() * (seeds[i][5] + 0.2) + (getScale() * HEIGHT) / 2);
} }
@Override @Override