version 2.0
This commit is contained in:
parent
0879a90112
commit
27948a134b
12 changed files with 436 additions and 295 deletions
|
@ -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];
|
||||||
|
|
||||||
|
|
46
LED_Panel_arduino_fastled/LED_Panel_arduino_fastled.ino
Normal file
46
LED_Panel_arduino_fastled/LED_Panel_arduino_fastled.ino
Normal 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();
|
||||||
|
|
||||||
|
}
|
44
LED_Panel_arduino_neopixel/LED_Panel_arduino_neopixel.ino
Normal file
44
LED_Panel_arduino_neopixel/LED_Panel_arduino_neopixel.ino
Normal 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();
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ public class EffectManager {
|
||||||
|
|
||||||
|
|
||||||
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() {
|
||||||
|
@ -69,14 +69,20 @@ public class EffectManager {
|
||||||
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)" : ""));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()) {
|
||||||
|
@ -52,6 +54,7 @@ public class LEDControl {
|
||||||
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();
|
||||||
|
|
167
src/main/java/de/zuim/ledcontrol/effects/AudioEffect.java
Normal file
167
src/main/java/de/zuim/ledcontrol/effects/AudioEffect.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,6 +18,7 @@ public class ClockEffect implements LEDEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
int iteration = 0;
|
int iteration = 0;
|
||||||
|
|
||||||
public void fontSwitcher() {
|
public void fontSwitcher() {
|
||||||
if (++iteration % 100 == 0) {
|
if (++iteration % 100 == 0) {
|
||||||
Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
|
Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
|
||||||
|
@ -27,7 +28,7 @@ public class ClockEffect implements LEDEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
|
@ -37,10 +38,10 @@ public class ClockEffect implements LEDEffect {
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -29,11 +29,11 @@ public class NetworkSpeedEffect implements LEDEffect {
|
||||||
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<>();
|
||||||
|
@ -90,8 +90,7 @@ public class NetworkSpeedEffect implements LEDEffect {
|
||||||
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));
|
||||||
|
|
|
@ -10,8 +10,8 @@ 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() {
|
||||||
|
@ -23,6 +23,7 @@ public class SineEffect implements LEDEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
double steps = 0;
|
double steps = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(long timeDelta, Graphics g) {
|
public void render(long timeDelta, Graphics g) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue