From a89c030dbaa060bff9805e64c059a5c98d311cec Mon Sep 17 00:00:00 2001 From: pfrison Date: Tue, 12 Mar 2019 00:05:46 +0100 Subject: [PATCH] VRGNYMusicLights visualizer Ok --- VRGNYMusicLights/Sources/AnimationPlayer.java | 55 ++++++++++++++++++++++++++++++++++++++++++++++++------- VRGNYMusicLights/Sources/Interface.java | 22 ++++++++++++++++------ VRGNYMusicLights/Sources/LightCanvasJPanel.java | 38 +++++++++++++++++++++++++------------- VRGNYMusicLights/Sources/Main.java | 15 +++++++++++---- VRGNYMusicLights/Sources/Music.java | 21 ++++++++++++--------- VRGNYMusicLights/Sources/MusicList.java | 20 ++++++++++++++++++++ VRGNYMusicLights/Sources/MusicPath.java | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- VRGNYMusicLights/Sources/MusicPattern.java | 27 ++++++++++++++++++++++++++- 8 files changed, 277 insertions(+), 51 deletions(-) diff --git a/VRGNYMusicLights/Sources/AnimationPlayer.java b/VRGNYMusicLights/Sources/AnimationPlayer.java index 74dca73..6569fce 100644 --- a/VRGNYMusicLights/Sources/AnimationPlayer.java +++ b/VRGNYMusicLights/Sources/AnimationPlayer.java @@ -10,14 +10,50 @@ import javax.swing.JPanel; public class AnimationPlayer extends JPanel implements ActionListener { private static final long serialVersionUID = 1L; + private LightCanvasJPanel lightCanvas; + private MusicList musicList; + private JButton backward; private JButton stop; private JButton play; private JButton pause; private JButton forward; + + private long tick = 0; + private boolean go = false; + private boolean stopClock = false; + private static final int TICK_JUMP = 20; + private Thread tickClock = new Thread(new Runnable() { + @Override + public void run() { + while(!stopClock) { + if(!go) { // pause + try { Thread.sleep(100); } + catch (InterruptedException ignored) {} + continue; + } + + long before = System.currentTimeMillis(); + lightCanvas.paintLights(musicList.render(tick)); + tick += TICK_JUMP; + long after = System.currentTimeMillis(); + + if(after - before < TICK_JUMP) { + try { Thread.sleep(10 - after + before);} + catch (InterruptedException ignored) {} + } else if(after - before > TICK_JUMP) { + System.err.println("Animation were slowed down by " + String.valueOf(after - before - 10) + " ticks !"); + } + } + } + }); + public void stopTickClock() {stopClock = true;} - public AnimationPlayer() { this(BoxLayout.LINE_AXIS); } - public AnimationPlayer(int direction) { + public AnimationPlayer(LightCanvasJPanel lightCanvas, MusicList musicList) { this(lightCanvas, musicList, BoxLayout.LINE_AXIS); } + public AnimationPlayer(LightCanvasJPanel lightCanvas, MusicList musicList, int direction) { + this.lightCanvas = lightCanvas; + this.musicList = musicList; + setLayout(new BoxLayout(this, direction)); add(Box.createHorizontalGlue()); @@ -48,21 +84,26 @@ public class AnimationPlayer extends JPanel implements ActionListener { add(forward); add(Box.createHorizontalGlue()); + + tickClock.start(); } @Override public void actionPerformed(ActionEvent e) { // TODO player actions if(e.getSource() == backward) { - + tick -= 500; + if(tick < 0) + tick = 0; }else if(e.getSource() == stop) { - + go = false; + tick = 0; }else if(e.getSource() == play) { - + go = true; }else if(e.getSource() == pause) { - + go = false; }else if(e.getSource() == forward) { - + tick += 500; } } } diff --git a/VRGNYMusicLights/Sources/Interface.java b/VRGNYMusicLights/Sources/Interface.java index ca80079..faafb37 100644 --- a/VRGNYMusicLights/Sources/Interface.java +++ b/VRGNYMusicLights/Sources/Interface.java @@ -3,7 +3,6 @@ import java.awt.Font; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; -import javax.swing.BoxLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; @@ -12,10 +11,13 @@ public class Interface extends JFrame{ private static final long serialVersionUID = 1L; private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14); private static final Font defaultFont = new Font(new JLabel().getFont().getName(), Font.PLAIN, new JLabel().getFont().getSize()); + + private MusicList musicList; + private AnimationPlayer animPlayer; - public Interface(final Runnable executeOnClose) { + public Interface(MusicList musicList, final Runnable executeOnClose) { super("VRGNYMusicLights"); - //this.actionList = actionList; + this.musicList = musicList; setResizable(false); populateWindow(); pack(); @@ -24,6 +26,8 @@ public class Interface extends JFrame{ addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { + if(animPlayer != null) + animPlayer.stopTickClock(); if(executeOnClose != null) executeOnClose.run(); dispose(); @@ -34,6 +38,7 @@ public class Interface extends JFrame{ private void populateWindow() { JPanel mainPanel = new JPanel(new BorderLayout()); addPlayPanel(mainPanel); + addTimeLine(mainPanel); add(mainPanel); } @@ -41,18 +46,23 @@ public class Interface extends JFrame{ JPanel playPanel = new JPanel(new BorderLayout()); // title - JLabel title = new JLabel("Player :"); + JLabel title = new JLabel("Visualizer :"); title.setFont(titleFont); playPanel.add(title, BorderLayout.NORTH); // lights - playPanel.add(new LightCanvasJPanel(), BorderLayout.CENTER); + LightCanvasJPanel lightCanvas = new LightCanvasJPanel(); + playPanel.add(lightCanvas, BorderLayout.CENTER); // controls - AnimationPlayer animPlayer = new AnimationPlayer(); + animPlayer = new AnimationPlayer(lightCanvas, musicList); animPlayer.setAlignmentX(CENTER_ALIGNMENT); playPanel.add(animPlayer, BorderLayout.SOUTH); parent.add(playPanel, BorderLayout.SOUTH); } + + private void addTimeLine(JPanel parent) { + JPanel timeLine = new JPanel(); + } } diff --git a/VRGNYMusicLights/Sources/LightCanvasJPanel.java b/VRGNYMusicLights/Sources/LightCanvasJPanel.java index 56a58fe..3debfbb 100644 --- a/VRGNYMusicLights/Sources/LightCanvasJPanel.java +++ b/VRGNYMusicLights/Sources/LightCanvasJPanel.java @@ -5,33 +5,29 @@ import java.awt.Graphics; import javax.swing.JPanel; public class LightCanvasJPanel extends JPanel { - public static final double[][] DEFAULT_LIGHT_COORDS = new double[][] { - {0, 0} , {0.2, 0} , {0.4, 0} , {0.6 , 0}, {0.8, 0} , {1, 0} , - {0, 0.2}, {0.2, 0.2}, {0.4, 0.2}, {0.6, 0.2}, {0.8, 0.2}, {1, 0.2}, - {0, 0.4}, {0.2, 0.4}, {0.4, 0.4}, {0.6, 0.4}, {0.8, 0.4}, {1, 0.4}, - {0, 0.6}, {0.2, 0.6}, {0.4, 0.6}, {0.6, 0.6}, {0.8, 0.6}, {1, 0.6}, - {0, 0.8}, {0.2, 0.8}, {0.4, 0.8}, {0.6, 0.8}, {0.8, 0.8}, {1, 0.8}, - {0, 1} , {0.2, 1} , {0.4, 1} , {0.6, 1} , {0.8, 1} , {1, 1} , - }; - private static final long serialVersionUID = 1L; private static final int WIDTH = 320; // = 300 + padding * 2 private static final int HEIGHT = 220; // = 200 + padding * 2 private static final int LIGHT_RADIUS = 4; private static final int PADDING = 10; private double[][] lightsCoords; + private double[] lights = null; - /** - * @param lightCoords : double[LightID][X = 0, Y = 1] = coordinates as a percentage [0, 1] - */ - public LightCanvasJPanel() {this(DEFAULT_LIGHT_COORDS);} + public LightCanvasJPanel() { this(MusicPath.LIGHT_COORDS); } public LightCanvasJPanel(double[][] lightsCoords) { this.lightsCoords = lightsCoords; setPreferredSize(new Dimension(WIDTH, HEIGHT)); } + public void paintLights(double[] lights) { + this.lights = lights; + repaint(); + } + @Override protected void paintComponent(Graphics g) { + super.paintComponent(g); + // background g.setColor(Color.WHITE); g.fillRect(0, 0, WIDTH, HEIGHT); @@ -47,5 +43,21 @@ public class LightCanvasJPanel extends JPanel { g.fillOval(centerX - LIGHT_RADIUS, centerY - LIGHT_RADIUS, LIGHT_RADIUS * 2, LIGHT_RADIUS * 2); } + + // lights values + if(lights == null || lights.length != lightsCoords.length) + return; + g.setColor(Color.YELLOW); + for(int i=0; i(); } + + public void addMusic(Music music) { musics.add(music); } + public void deleteMusic(int index) { musics.remove(index); } + + public double[] render(long tick) { + if(musics.size() == 0) + return null; + double[] lights = musics.get(0).render(tick); + for(int i=1; i 1) + lights[j] = 1; + } + } + return lights; + } } diff --git a/VRGNYMusicLights/Sources/MusicPath.java b/VRGNYMusicLights/Sources/MusicPath.java index 8921d8a..4e2e3d1 100644 --- a/VRGNYMusicLights/Sources/MusicPath.java +++ b/VRGNYMusicLights/Sources/MusicPath.java @@ -1,20 +1,128 @@ public class MusicPath { - private static final int VERTICAL_DOWN = 0; - private static final int VERTICAL_UP = 1; - private static final int HORIZONTAL_DOWN = 2; - private static final int HORIZONTAL_UP = 3; - private static final int DIAGONAL_TOP_RIGHT_DOWN_LEFT = 4; - private static final int DIAGONAL_TOP_LEFT_DOWN_RIGHT = 5; - private static final int CENTER_OUT = 6; - private static final int CENTER_IN = 7; + public static final double[][] LIGHT_COORDS = new double[][] { + // Planche 1 + {0.0383, 0}, {0.0766, 0}, {0.115, 0}, {0.1533, 0}, {0.1916, 0}, {0.23, 0}, //M1L1 + {0.2683, 0}, {0.306, 0}, {0.345, 0}, {0.383, 0}, {0.4216, 0}, {0.46, 0}, {0.4983, 0}, //M1L2 + {0.0333, 0.25}, {0.0666, 0.25}, {0.0999, 0.25}, {0.1333, 0.25}, //P1-1 + {0.3016, 0.25}, {0.3366, 0.25}, {0.3733, 0.25}, {0.4099, 0.25}, {0.4466, 0.25}, {0.4833, 0.25}, {0.5199, 0.25}, //P1-2 + {0.3366, 0.3}, {0.3366, 0.35}, //P1-3 + {0, 0.3075}, {0, 0.365}, {0, 0.4225}, //M1l1 + + // Planche 2 + {0.5366, 0}, {0.575, 0}, {0.6133, 0}, {0.6516, 0}, {0.69, 0}, {0.7283, 0}, {0.7666, 0}, //M2L1 + {0.805, 0}, {0.8433, 0}, {0.8816, 0}, {0.92, 0}, {0.9583, 0}, //M2L2 + {0.5566, 0.25}, {0.5933, 0.25}, {0.6299, 0.25}, {0.6666, 0.25}, //P2-1 + {0.8366, 0.25}, {0.8699, 0.25}, {0.9032, 0.25}, {0.9366, 0.25}, {0.9699, 0.25}, //P2-2 + {1, 0.06}, {1, 0.115}, {1, 0.17}, {1, 0.225}, {1, 0.28}, {1, 0.335}, {1, 0.39}, //M2l1 + + // Planche 3 + {0.3366, 0.4}, {0.3366, 0.45}, {0.3366, 0.5}, //P3-1 + {0.3366, 0.75}, {0.3366, 0.8}, //P3-2 + {0, 0.48}, {0, 0.5375}, {0, 0.595}, {0, 0.6525}, {0, 0.71}, {0, 0.7675}, //M3l1 + + // Planche 4 + {1, 0.445}, {1, 0.5}, {1, 0.555}, {1, 0.61}, {1, 0.665}, {1, 0.72}, {1, 0.775}, //M4l1 + + // Planche 5 + {0.0383, 1}, {0.0766, 1}, {0.115, 1}, {0.1533, 1}, {0.1916, 1}, {0.23, 1}, //M5L1 + {0.2683, 1}, {0.306, 1}, {0.345, 1}, {0.383, 1}, {0.4216, 1}, {0.46, 1}, {0.4983, 1}, //M5L2 + {0.3366, 0.85}, {0.3366, 0.9}, {0.3366, 0.95}, //P5-1 + {0, 0.8255}, {0, 0.8835}, {0, 0.9415}, //M5l1 + + // Planche 6 + {0.5366, 1}, {0.575, 1}, {0.6133, 1}, {0.6516, 1}, {0.69, 1}, {0.7283, 1}, {0.7666, 1}, //M6L1 + {0.805, 1}, {0.8433, 1}, {0.8816, 1}, {0.92, 1}, {0.9583, 1}, //M6L2 + {1, 0.83}, {1, 0.885}, {1, 0.94} //M6l1 + }; + + public static final int VERTICAL_DOWN = 0; + public static final int VERTICAL_UP = 1; + public static final int HORIZONTAL_TO_LEFT = 2; + public static final int HORIZONTAL_TO_RIGHT = 3; + public static final int DIAGONAL_TOP_RIGHT_DOWN_LEFT = 4; + public static final int DIAGONAL_DOWN_LEFT_TOP_RIGHT = 5; + public static final int DIAGONAL_TOP_LEFT_DOWN_RIGHT = 6; + public static final int DIAGONAL_DOWN_RIGHT_TOP_LEFT = 7; + public static final int CENTER_OUT = 8; + public static final int CENTER_IN = 9; + public static final int ALL = 10; private int animation; + private int effectDuration; + private double[][] lightsCoords; - public MusicPath(int animation) { + public MusicPath(int animation, int effectDuration) { this(animation, effectDuration, LIGHT_COORDS); } + public MusicPath(int animation, int effectDuration, double[][] lightsCoords) { this.animation = animation; + this.effectDuration = effectDuration; + this.lightsCoords = lightsCoords; } - // TODO transform music according to animation - // what format ? int[nled][pattern] (ms) ? + public int[] calculateTickDelais() { // tick in ms + int[] ticksDelais = new int[lightsCoords.length]; + for(int i=0; i= stop) + return 0; + int tickMod = (int) (tick % totalLentgh); + if(tickMod < patternTiming[0]) + return 0; + if(tickMod < patternTiming[1]) + return (double) (tickMod - patternTiming[0]) / (double) (pattern[1]); + if(tickMod < patternTiming[2]) + return 1; + return 1 - ((double) (tickMod - patternTiming[2]) / (double) (pattern[3])); } } -- libgit2 0.21.2