Commit a89c030dbaa060bff9805e64c059a5c98d311cec
1 parent
b191d7e7
VRGNYMusicLights visualizer Ok
Showing
8 changed files
with
277 additions
and
51 deletions
Show diff stats
VRGNYMusicLights/Sources/AnimationPlayer.java
@@ -10,14 +10,50 @@ import javax.swing.JPanel; | @@ -10,14 +10,50 @@ import javax.swing.JPanel; | ||
10 | public class AnimationPlayer extends JPanel implements ActionListener { | 10 | public class AnimationPlayer extends JPanel implements ActionListener { |
11 | private static final long serialVersionUID = 1L; | 11 | private static final long serialVersionUID = 1L; |
12 | 12 | ||
13 | + private LightCanvasJPanel lightCanvas; | ||
14 | + private MusicList musicList; | ||
15 | + | ||
13 | private JButton backward; | 16 | private JButton backward; |
14 | private JButton stop; | 17 | private JButton stop; |
15 | private JButton play; | 18 | private JButton play; |
16 | private JButton pause; | 19 | private JButton pause; |
17 | private JButton forward; | 20 | private JButton forward; |
21 | + | ||
22 | + private long tick = 0; | ||
23 | + private boolean go = false; | ||
24 | + private boolean stopClock = false; | ||
25 | + private static final int TICK_JUMP = 20; | ||
26 | + private Thread tickClock = new Thread(new Runnable() { | ||
27 | + @Override | ||
28 | + public void run() { | ||
29 | + while(!stopClock) { | ||
30 | + if(!go) { // pause | ||
31 | + try { Thread.sleep(100); } | ||
32 | + catch (InterruptedException ignored) {} | ||
33 | + continue; | ||
34 | + } | ||
35 | + | ||
36 | + long before = System.currentTimeMillis(); | ||
37 | + lightCanvas.paintLights(musicList.render(tick)); | ||
38 | + tick += TICK_JUMP; | ||
39 | + long after = System.currentTimeMillis(); | ||
40 | + | ||
41 | + if(after - before < TICK_JUMP) { | ||
42 | + try { Thread.sleep(10 - after + before);} | ||
43 | + catch (InterruptedException ignored) {} | ||
44 | + } else if(after - before > TICK_JUMP) { | ||
45 | + System.err.println("Animation were slowed down by " + String.valueOf(after - before - 10) + " ticks !"); | ||
46 | + } | ||
47 | + } | ||
48 | + } | ||
49 | + }); | ||
50 | + public void stopTickClock() {stopClock = true;} | ||
18 | 51 | ||
19 | - public AnimationPlayer() { this(BoxLayout.LINE_AXIS); } | ||
20 | - public AnimationPlayer(int direction) { | 52 | + public AnimationPlayer(LightCanvasJPanel lightCanvas, MusicList musicList) { this(lightCanvas, musicList, BoxLayout.LINE_AXIS); } |
53 | + public AnimationPlayer(LightCanvasJPanel lightCanvas, MusicList musicList, int direction) { | ||
54 | + this.lightCanvas = lightCanvas; | ||
55 | + this.musicList = musicList; | ||
56 | + | ||
21 | setLayout(new BoxLayout(this, direction)); | 57 | setLayout(new BoxLayout(this, direction)); |
22 | 58 | ||
23 | add(Box.createHorizontalGlue()); | 59 | add(Box.createHorizontalGlue()); |
@@ -48,21 +84,26 @@ public class AnimationPlayer extends JPanel implements ActionListener { | @@ -48,21 +84,26 @@ public class AnimationPlayer extends JPanel implements ActionListener { | ||
48 | add(forward); | 84 | add(forward); |
49 | 85 | ||
50 | add(Box.createHorizontalGlue()); | 86 | add(Box.createHorizontalGlue()); |
87 | + | ||
88 | + tickClock.start(); | ||
51 | } | 89 | } |
52 | 90 | ||
53 | @Override | 91 | @Override |
54 | public void actionPerformed(ActionEvent e) { | 92 | public void actionPerformed(ActionEvent e) { |
55 | // TODO player actions | 93 | // TODO player actions |
56 | if(e.getSource() == backward) { | 94 | if(e.getSource() == backward) { |
57 | - | 95 | + tick -= 500; |
96 | + if(tick < 0) | ||
97 | + tick = 0; | ||
58 | }else if(e.getSource() == stop) { | 98 | }else if(e.getSource() == stop) { |
59 | - | 99 | + go = false; |
100 | + tick = 0; | ||
60 | }else if(e.getSource() == play) { | 101 | }else if(e.getSource() == play) { |
61 | - | 102 | + go = true; |
62 | }else if(e.getSource() == pause) { | 103 | }else if(e.getSource() == pause) { |
63 | - | 104 | + go = false; |
64 | }else if(e.getSource() == forward) { | 105 | }else if(e.getSource() == forward) { |
65 | - | 106 | + tick += 500; |
66 | } | 107 | } |
67 | } | 108 | } |
68 | } | 109 | } |
VRGNYMusicLights/Sources/Interface.java
@@ -3,7 +3,6 @@ import java.awt.Font; | @@ -3,7 +3,6 @@ import java.awt.Font; | ||
3 | import java.awt.event.WindowAdapter; | 3 | import java.awt.event.WindowAdapter; |
4 | import java.awt.event.WindowEvent; | 4 | import java.awt.event.WindowEvent; |
5 | 5 | ||
6 | -import javax.swing.BoxLayout; | ||
7 | import javax.swing.JFrame; | 6 | import javax.swing.JFrame; |
8 | import javax.swing.JLabel; | 7 | import javax.swing.JLabel; |
9 | import javax.swing.JPanel; | 8 | import javax.swing.JPanel; |
@@ -12,10 +11,13 @@ public class Interface extends JFrame{ | @@ -12,10 +11,13 @@ public class Interface extends JFrame{ | ||
12 | private static final long serialVersionUID = 1L; | 11 | private static final long serialVersionUID = 1L; |
13 | private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14); | 12 | private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14); |
14 | private static final Font defaultFont = new Font(new JLabel().getFont().getName(), Font.PLAIN, new JLabel().getFont().getSize()); | 13 | private static final Font defaultFont = new Font(new JLabel().getFont().getName(), Font.PLAIN, new JLabel().getFont().getSize()); |
14 | + | ||
15 | + private MusicList musicList; | ||
16 | + private AnimationPlayer animPlayer; | ||
15 | 17 | ||
16 | - public Interface(final Runnable executeOnClose) { | 18 | + public Interface(MusicList musicList, final Runnable executeOnClose) { |
17 | super("VRGNYMusicLights"); | 19 | super("VRGNYMusicLights"); |
18 | - //this.actionList = actionList; | 20 | + this.musicList = musicList; |
19 | setResizable(false); | 21 | setResizable(false); |
20 | populateWindow(); | 22 | populateWindow(); |
21 | pack(); | 23 | pack(); |
@@ -24,6 +26,8 @@ public class Interface extends JFrame{ | @@ -24,6 +26,8 @@ public class Interface extends JFrame{ | ||
24 | addWindowListener(new WindowAdapter() { | 26 | addWindowListener(new WindowAdapter() { |
25 | @Override | 27 | @Override |
26 | public void windowClosing(WindowEvent e) { | 28 | public void windowClosing(WindowEvent e) { |
29 | + if(animPlayer != null) | ||
30 | + animPlayer.stopTickClock(); | ||
27 | if(executeOnClose != null) | 31 | if(executeOnClose != null) |
28 | executeOnClose.run(); | 32 | executeOnClose.run(); |
29 | dispose(); | 33 | dispose(); |
@@ -34,6 +38,7 @@ public class Interface extends JFrame{ | @@ -34,6 +38,7 @@ public class Interface extends JFrame{ | ||
34 | private void populateWindow() { | 38 | private void populateWindow() { |
35 | JPanel mainPanel = new JPanel(new BorderLayout()); | 39 | JPanel mainPanel = new JPanel(new BorderLayout()); |
36 | addPlayPanel(mainPanel); | 40 | addPlayPanel(mainPanel); |
41 | + addTimeLine(mainPanel); | ||
37 | add(mainPanel); | 42 | add(mainPanel); |
38 | } | 43 | } |
39 | 44 | ||
@@ -41,18 +46,23 @@ public class Interface extends JFrame{ | @@ -41,18 +46,23 @@ public class Interface extends JFrame{ | ||
41 | JPanel playPanel = new JPanel(new BorderLayout()); | 46 | JPanel playPanel = new JPanel(new BorderLayout()); |
42 | 47 | ||
43 | // title | 48 | // title |
44 | - JLabel title = new JLabel("Player :"); | 49 | + JLabel title = new JLabel("Visualizer :"); |
45 | title.setFont(titleFont); | 50 | title.setFont(titleFont); |
46 | playPanel.add(title, BorderLayout.NORTH); | 51 | playPanel.add(title, BorderLayout.NORTH); |
47 | 52 | ||
48 | // lights | 53 | // lights |
49 | - playPanel.add(new LightCanvasJPanel(), BorderLayout.CENTER); | 54 | + LightCanvasJPanel lightCanvas = new LightCanvasJPanel(); |
55 | + playPanel.add(lightCanvas, BorderLayout.CENTER); | ||
50 | 56 | ||
51 | // controls | 57 | // controls |
52 | - AnimationPlayer animPlayer = new AnimationPlayer(); | 58 | + animPlayer = new AnimationPlayer(lightCanvas, musicList); |
53 | animPlayer.setAlignmentX(CENTER_ALIGNMENT); | 59 | animPlayer.setAlignmentX(CENTER_ALIGNMENT); |
54 | playPanel.add(animPlayer, BorderLayout.SOUTH); | 60 | playPanel.add(animPlayer, BorderLayout.SOUTH); |
55 | 61 | ||
56 | parent.add(playPanel, BorderLayout.SOUTH); | 62 | parent.add(playPanel, BorderLayout.SOUTH); |
57 | } | 63 | } |
64 | + | ||
65 | + private void addTimeLine(JPanel parent) { | ||
66 | + JPanel timeLine = new JPanel(); | ||
67 | + } | ||
58 | } | 68 | } |
VRGNYMusicLights/Sources/LightCanvasJPanel.java
@@ -5,33 +5,29 @@ import java.awt.Graphics; | @@ -5,33 +5,29 @@ import java.awt.Graphics; | ||
5 | import javax.swing.JPanel; | 5 | import javax.swing.JPanel; |
6 | 6 | ||
7 | public class LightCanvasJPanel extends JPanel { | 7 | public class LightCanvasJPanel extends JPanel { |
8 | - public static final double[][] DEFAULT_LIGHT_COORDS = new double[][] { | ||
9 | - {0, 0} , {0.2, 0} , {0.4, 0} , {0.6 , 0}, {0.8, 0} , {1, 0} , | ||
10 | - {0, 0.2}, {0.2, 0.2}, {0.4, 0.2}, {0.6, 0.2}, {0.8, 0.2}, {1, 0.2}, | ||
11 | - {0, 0.4}, {0.2, 0.4}, {0.4, 0.4}, {0.6, 0.4}, {0.8, 0.4}, {1, 0.4}, | ||
12 | - {0, 0.6}, {0.2, 0.6}, {0.4, 0.6}, {0.6, 0.6}, {0.8, 0.6}, {1, 0.6}, | ||
13 | - {0, 0.8}, {0.2, 0.8}, {0.4, 0.8}, {0.6, 0.8}, {0.8, 0.8}, {1, 0.8}, | ||
14 | - {0, 1} , {0.2, 1} , {0.4, 1} , {0.6, 1} , {0.8, 1} , {1, 1} , | ||
15 | - }; | ||
16 | - | ||
17 | private static final long serialVersionUID = 1L; | 8 | private static final long serialVersionUID = 1L; |
18 | private static final int WIDTH = 320; // = 300 + padding * 2 | 9 | private static final int WIDTH = 320; // = 300 + padding * 2 |
19 | private static final int HEIGHT = 220; // = 200 + padding * 2 | 10 | private static final int HEIGHT = 220; // = 200 + padding * 2 |
20 | private static final int LIGHT_RADIUS = 4; | 11 | private static final int LIGHT_RADIUS = 4; |
21 | private static final int PADDING = 10; | 12 | private static final int PADDING = 10; |
22 | private double[][] lightsCoords; | 13 | private double[][] lightsCoords; |
14 | + private double[] lights = null; | ||
23 | 15 | ||
24 | - /** | ||
25 | - * @param lightCoords : double[LightID][X = 0, Y = 1] = coordinates as a percentage [0, 1] | ||
26 | - */ | ||
27 | - public LightCanvasJPanel() {this(DEFAULT_LIGHT_COORDS);} | 16 | + public LightCanvasJPanel() { this(MusicPath.LIGHT_COORDS); } |
28 | public LightCanvasJPanel(double[][] lightsCoords) { | 17 | public LightCanvasJPanel(double[][] lightsCoords) { |
29 | this.lightsCoords = lightsCoords; | 18 | this.lightsCoords = lightsCoords; |
30 | setPreferredSize(new Dimension(WIDTH, HEIGHT)); | 19 | setPreferredSize(new Dimension(WIDTH, HEIGHT)); |
31 | } | 20 | } |
32 | 21 | ||
22 | + public void paintLights(double[] lights) { | ||
23 | + this.lights = lights; | ||
24 | + repaint(); | ||
25 | + } | ||
26 | + | ||
33 | @Override | 27 | @Override |
34 | protected void paintComponent(Graphics g) { | 28 | protected void paintComponent(Graphics g) { |
29 | + super.paintComponent(g); | ||
30 | + | ||
35 | // background | 31 | // background |
36 | g.setColor(Color.WHITE); | 32 | g.setColor(Color.WHITE); |
37 | g.fillRect(0, 0, WIDTH, HEIGHT); | 33 | g.fillRect(0, 0, WIDTH, HEIGHT); |
@@ -47,5 +43,21 @@ public class LightCanvasJPanel extends JPanel { | @@ -47,5 +43,21 @@ public class LightCanvasJPanel extends JPanel { | ||
47 | 43 | ||
48 | g.fillOval(centerX - LIGHT_RADIUS, centerY - LIGHT_RADIUS, LIGHT_RADIUS * 2, LIGHT_RADIUS * 2); | 44 | g.fillOval(centerX - LIGHT_RADIUS, centerY - LIGHT_RADIUS, LIGHT_RADIUS * 2, LIGHT_RADIUS * 2); |
49 | } | 45 | } |
46 | + | ||
47 | + // lights values | ||
48 | + if(lights == null || lights.length != lightsCoords.length) | ||
49 | + return; | ||
50 | + g.setColor(Color.YELLOW); | ||
51 | + for(int i=0; i<lights.length; i++) { | ||
52 | + if(lightsCoords[i].length != 2) | ||
53 | + throw new MalformedCoordinates(); | ||
54 | + int centerX = (int) (lightsCoords[i][0] * (WIDTH - PADDING * 2)) + PADDING; | ||
55 | + int centerY = (int) (lightsCoords[i][1] * (HEIGHT - PADDING * 2)) + PADDING; | ||
56 | + | ||
57 | + g.fillOval((int) (centerX - (LIGHT_RADIUS * lights[i])), | ||
58 | + (int) (centerY - (LIGHT_RADIUS * lights[i])), | ||
59 | + (int) (LIGHT_RADIUS * lights[i] * 2), | ||
60 | + (int) (LIGHT_RADIUS * lights[i] * 2)); | ||
61 | + } | ||
50 | } | 62 | } |
51 | } | 63 | } |
VRGNYMusicLights/Sources/Main.java
1 | +import javax.swing.JOptionPane; | ||
1 | 2 | ||
2 | /* TODO list : | 3 | /* TODO list : |
3 | * - keyboard listener for animation player (play / pause = space, forward = semicolon, backward = comma, stop = backspace) | 4 | * - keyboard listener for animation player (play / pause = space, forward = semicolon, backward = comma, stop = backspace) |
4 | */ | 5 | */ |
5 | public class Main { | 6 | public class Main { |
6 | public static void main(String[] args) throws InterruptedException { | 7 | public static void main(String[] args) throws InterruptedException { |
7 | - /* FIXME interface testing in progress | ||
8 | - | ||
9 | - String serialPort = null; | 8 | + // FIXME interface testing in progress |
9 | + /*String serialPort = null; | ||
10 | try { | 10 | try { |
11 | serialPort = SerialPortChooserDialog.showSerialPortChooserDialog(); | 11 | serialPort = SerialPortChooserDialog.showSerialPortChooserDialog(); |
12 | } catch (NoSerialPortException e) { | 12 | } catch (NoSerialPortException e) { |
@@ -19,7 +19,14 @@ public class Main { | @@ -19,7 +19,14 @@ public class Main { | ||
19 | // arduino need time before accepting serial data | 19 | // arduino need time before accepting serial data |
20 | Thread.sleep(1000);*/ | 20 | Thread.sleep(1000);*/ |
21 | 21 | ||
22 | - Interface i = new Interface(new Runnable() { | 22 | + MusicList musicList = new MusicList(null); |
23 | + musicList.addMusic( | ||
24 | + new Music( | ||
25 | + new MusicPattern(new int[] {1000, 0, 0, 1000}, 1000, 0), | ||
26 | + new MusicPath(MusicPath.CENTER_IN, 1000), | ||
27 | + 1)); | ||
28 | + | ||
29 | + Interface i = new Interface(musicList, new Runnable() { | ||
23 | @Override | 30 | @Override |
24 | public void run() { | 31 | public void run() { |
25 | //serialCom.close(); | 32 | //serialCom.close(); |
VRGNYMusicLights/Sources/Music.java
1 | 1 | ||
2 | public class Music { | 2 | public class Music { |
3 | private MusicPattern pattern; | 3 | private MusicPattern pattern; |
4 | - private MusicPath path; | ||
5 | - private long startDelai; // in ms | ||
6 | - private long length; // in ms | 4 | + private int[] lightTickDelais; |
5 | + private double volume; | ||
7 | 6 | ||
8 | - public Music(MusicPattern pattern, MusicPath path, long startDelai, long length) { | 7 | + public Music(MusicPattern pattern, MusicPath path, double volume) { |
9 | this.pattern = pattern; | 8 | this.pattern = pattern; |
10 | - this.path = path; | ||
11 | - this.startDelai = startDelai; | ||
12 | - this.length = length; | ||
13 | - | ||
14 | - //call MusicPath transform() | 9 | + this.lightTickDelais = path.calculateTickDelais(); |
10 | + this.volume = volume; | ||
11 | + } | ||
12 | + | ||
13 | + public double[] render(long tick) { | ||
14 | + double[] lights = new double[lightTickDelais.length]; | ||
15 | + for(int i=0; i<lights.length; i++) | ||
16 | + lights[i] = pattern.render(lightTickDelais[i] + tick) * volume; | ||
17 | + return lights; | ||
15 | } | 18 | } |
16 | } | 19 | } |
VRGNYMusicLights/Sources/MusicList.java
@@ -8,4 +8,24 @@ public class MusicList { | @@ -8,4 +8,24 @@ public class MusicList { | ||
8 | this.serialCom = serialCom; | 8 | this.serialCom = serialCom; |
9 | musics = new ArrayList<>(); | 9 | musics = new ArrayList<>(); |
10 | } | 10 | } |
11 | + | ||
12 | + public void addMusic(Music music) { musics.add(music); } | ||
13 | + public void deleteMusic(int index) { musics.remove(index); } | ||
14 | + | ||
15 | + public double[] render(long tick) { | ||
16 | + if(musics.size() == 0) | ||
17 | + return null; | ||
18 | + double[] lights = musics.get(0).render(tick); | ||
19 | + for(int i=1; i<musics.size(); i++) { | ||
20 | + double[] tmpRender = musics.get(i).render(tick); | ||
21 | + for(int j=0; j<lights.length; j++) { | ||
22 | + lights[j] += tmpRender[j]; | ||
23 | + if(lights[j] < 0) | ||
24 | + lights[j] = 0; | ||
25 | + if(lights[j] > 1) | ||
26 | + lights[j] = 1; | ||
27 | + } | ||
28 | + } | ||
29 | + return lights; | ||
30 | + } | ||
11 | } | 31 | } |
VRGNYMusicLights/Sources/MusicPath.java
1 | 1 | ||
2 | public class MusicPath { | 2 | public class MusicPath { |
3 | - private static final int VERTICAL_DOWN = 0; | ||
4 | - private static final int VERTICAL_UP = 1; | ||
5 | - private static final int HORIZONTAL_DOWN = 2; | ||
6 | - private static final int HORIZONTAL_UP = 3; | ||
7 | - private static final int DIAGONAL_TOP_RIGHT_DOWN_LEFT = 4; | ||
8 | - private static final int DIAGONAL_TOP_LEFT_DOWN_RIGHT = 5; | ||
9 | - private static final int CENTER_OUT = 6; | ||
10 | - private static final int CENTER_IN = 7; | 3 | + public static final double[][] LIGHT_COORDS = new double[][] { |
4 | + // Planche 1 | ||
5 | + {0.0383, 0}, {0.0766, 0}, {0.115, 0}, {0.1533, 0}, {0.1916, 0}, {0.23, 0}, //M1L1 | ||
6 | + {0.2683, 0}, {0.306, 0}, {0.345, 0}, {0.383, 0}, {0.4216, 0}, {0.46, 0}, {0.4983, 0}, //M1L2 | ||
7 | + {0.0333, 0.25}, {0.0666, 0.25}, {0.0999, 0.25}, {0.1333, 0.25}, //P1-1 | ||
8 | + {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 | ||
9 | + {0.3366, 0.3}, {0.3366, 0.35}, //P1-3 | ||
10 | + {0, 0.3075}, {0, 0.365}, {0, 0.4225}, //M1l1 | ||
11 | + | ||
12 | + // Planche 2 | ||
13 | + {0.5366, 0}, {0.575, 0}, {0.6133, 0}, {0.6516, 0}, {0.69, 0}, {0.7283, 0}, {0.7666, 0}, //M2L1 | ||
14 | + {0.805, 0}, {0.8433, 0}, {0.8816, 0}, {0.92, 0}, {0.9583, 0}, //M2L2 | ||
15 | + {0.5566, 0.25}, {0.5933, 0.25}, {0.6299, 0.25}, {0.6666, 0.25}, //P2-1 | ||
16 | + {0.8366, 0.25}, {0.8699, 0.25}, {0.9032, 0.25}, {0.9366, 0.25}, {0.9699, 0.25}, //P2-2 | ||
17 | + {1, 0.06}, {1, 0.115}, {1, 0.17}, {1, 0.225}, {1, 0.28}, {1, 0.335}, {1, 0.39}, //M2l1 | ||
18 | + | ||
19 | + // Planche 3 | ||
20 | + {0.3366, 0.4}, {0.3366, 0.45}, {0.3366, 0.5}, //P3-1 | ||
21 | + {0.3366, 0.75}, {0.3366, 0.8}, //P3-2 | ||
22 | + {0, 0.48}, {0, 0.5375}, {0, 0.595}, {0, 0.6525}, {0, 0.71}, {0, 0.7675}, //M3l1 | ||
23 | + | ||
24 | + // Planche 4 | ||
25 | + {1, 0.445}, {1, 0.5}, {1, 0.555}, {1, 0.61}, {1, 0.665}, {1, 0.72}, {1, 0.775}, //M4l1 | ||
26 | + | ||
27 | + // Planche 5 | ||
28 | + {0.0383, 1}, {0.0766, 1}, {0.115, 1}, {0.1533, 1}, {0.1916, 1}, {0.23, 1}, //M5L1 | ||
29 | + {0.2683, 1}, {0.306, 1}, {0.345, 1}, {0.383, 1}, {0.4216, 1}, {0.46, 1}, {0.4983, 1}, //M5L2 | ||
30 | + {0.3366, 0.85}, {0.3366, 0.9}, {0.3366, 0.95}, //P5-1 | ||
31 | + {0, 0.8255}, {0, 0.8835}, {0, 0.9415}, //M5l1 | ||
32 | + | ||
33 | + // Planche 6 | ||
34 | + {0.5366, 1}, {0.575, 1}, {0.6133, 1}, {0.6516, 1}, {0.69, 1}, {0.7283, 1}, {0.7666, 1}, //M6L1 | ||
35 | + {0.805, 1}, {0.8433, 1}, {0.8816, 1}, {0.92, 1}, {0.9583, 1}, //M6L2 | ||
36 | + {1, 0.83}, {1, 0.885}, {1, 0.94} //M6l1 | ||
37 | + }; | ||
38 | + | ||
39 | + public static final int VERTICAL_DOWN = 0; | ||
40 | + public static final int VERTICAL_UP = 1; | ||
41 | + public static final int HORIZONTAL_TO_LEFT = 2; | ||
42 | + public static final int HORIZONTAL_TO_RIGHT = 3; | ||
43 | + public static final int DIAGONAL_TOP_RIGHT_DOWN_LEFT = 4; | ||
44 | + public static final int DIAGONAL_DOWN_LEFT_TOP_RIGHT = 5; | ||
45 | + public static final int DIAGONAL_TOP_LEFT_DOWN_RIGHT = 6; | ||
46 | + public static final int DIAGONAL_DOWN_RIGHT_TOP_LEFT = 7; | ||
47 | + public static final int CENTER_OUT = 8; | ||
48 | + public static final int CENTER_IN = 9; | ||
49 | + public static final int ALL = 10; | ||
11 | 50 | ||
12 | private int animation; | 51 | private int animation; |
52 | + private int effectDuration; | ||
53 | + private double[][] lightsCoords; | ||
13 | 54 | ||
14 | - public MusicPath(int animation) { | 55 | + public MusicPath(int animation, int effectDuration) { this(animation, effectDuration, LIGHT_COORDS); } |
56 | + public MusicPath(int animation, int effectDuration, double[][] lightsCoords) { | ||
15 | this.animation = animation; | 57 | this.animation = animation; |
58 | + this.effectDuration = effectDuration; | ||
59 | + this.lightsCoords = lightsCoords; | ||
16 | } | 60 | } |
17 | 61 | ||
18 | - // TODO transform music according to animation | ||
19 | - // what format ? int[nled][pattern] (ms) ? | 62 | + public int[] calculateTickDelais() { // tick in ms |
63 | + int[] ticksDelais = new int[lightsCoords.length]; | ||
64 | + for(int i=0; i<ticksDelais.length; i++) { | ||
65 | + ticksDelais[i] = 0; | ||
66 | + if(animation == VERTICAL_DOWN | ||
67 | + || animation == VERTICAL_UP | ||
68 | + || animation == HORIZONTAL_TO_LEFT | ||
69 | + || animation == HORIZONTAL_TO_RIGHT | ||
70 | + || animation == DIAGONAL_TOP_RIGHT_DOWN_LEFT | ||
71 | + || animation == DIAGONAL_DOWN_LEFT_TOP_RIGHT | ||
72 | + || animation == DIAGONAL_TOP_LEFT_DOWN_RIGHT | ||
73 | + || animation == DIAGONAL_DOWN_RIGHT_TOP_LEFT | ||
74 | + || animation == CENTER_OUT | ||
75 | + || animation == CENTER_IN) { | ||
76 | + switch (animation) { | ||
77 | + case VERTICAL_DOWN: | ||
78 | + ticksDelais[i] += tickLateVerticalDown(LIGHT_COORDS[i][1]); | ||
79 | + break; | ||
80 | + case VERTICAL_UP: | ||
81 | + ticksDelais[i] += tickLateVerticalUp(LIGHT_COORDS[i][1]); | ||
82 | + break; | ||
83 | + case HORIZONTAL_TO_LEFT: | ||
84 | + ticksDelais[i] += tickLateHorizontalToLeft(LIGHT_COORDS[i][0]); | ||
85 | + break; | ||
86 | + case HORIZONTAL_TO_RIGHT: | ||
87 | + ticksDelais[i] += tickLateHorizontalToRight(LIGHT_COORDS[i][0]); | ||
88 | + break; | ||
89 | + case DIAGONAL_TOP_RIGHT_DOWN_LEFT: | ||
90 | + ticksDelais[i] += tickLateDiagTRDL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); | ||
91 | + break; | ||
92 | + case DIAGONAL_DOWN_LEFT_TOP_RIGHT: | ||
93 | + ticksDelais[i] += tickLateDiagDLTR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); | ||
94 | + break; | ||
95 | + case DIAGONAL_TOP_LEFT_DOWN_RIGHT: | ||
96 | + ticksDelais[i] += tickLateDiagTLDR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); | ||
97 | + break; | ||
98 | + case DIAGONAL_DOWN_RIGHT_TOP_LEFT: | ||
99 | + ticksDelais[i] += tickLateDiagDRTL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); | ||
100 | + break; | ||
101 | + case CENTER_OUT: | ||
102 | + ticksDelais[i] += tickLateCenterOut(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); | ||
103 | + break; | ||
104 | + case CENTER_IN: | ||
105 | + ticksDelais[i] += tickLateCenterIn(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); | ||
106 | + break; | ||
107 | + } | ||
108 | + } | ||
109 | + else if(animation == ALL); | ||
110 | + } | ||
111 | + return ticksDelais; | ||
112 | + } | ||
113 | + | ||
114 | + private int tickLateVerticalDown(double y) {return (int) ((1-y) * effectDuration);} | ||
115 | + private int tickLateVerticalUp(double y) {return (int) (y * effectDuration);} | ||
116 | + private int tickLateHorizontalToRight(double x) {return (int) ((1-x) * effectDuration);} | ||
117 | + private int tickLateHorizontalToLeft(double x) {return (int) (x * effectDuration);} | ||
118 | + private int tickLateDiagTRDL(double x, double y) {return (int) ((x - y) / 2d * (double) effectDuration);} | ||
119 | + private int tickLateDiagDLTR(double x, double y) {return (int) ((-x + y) / 2d * (double) effectDuration);} | ||
120 | + private int tickLateDiagDRTL(double x, double y) {return (int) ((x + y) / 2d * (double) effectDuration);} | ||
121 | + private int tickLateDiagTLDR(double x, double y) {return (int) ((-x - y) / 2d * (double) effectDuration);} | ||
122 | + private int tickLateCenterOut(double x, double y) {return (int) ((1 - (x-0.5)*(x-0.5) - (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);} | ||
123 | + private int tickLateCenterIn(double x, double y) {return (int) (((x-0.5)*(x-0.5) + (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);} | ||
124 | + | ||
125 | + public int getNumberOfLights() { | ||
126 | + return this.lightsCoords.length; | ||
127 | + } | ||
20 | } | 128 | } |
VRGNYMusicLights/Sources/MusicPattern.java
@@ -7,10 +7,35 @@ public class MusicPattern { | @@ -7,10 +7,35 @@ public class MusicPattern { | ||
7 | * 3 : fall time | 7 | * 3 : fall time |
8 | */ | 8 | */ |
9 | private int[] pattern; // in ms | 9 | private int[] pattern; // in ms |
10 | + private int totalLentgh; | ||
11 | + private int[] patternTiming = new int[4]; // in ms | ||
12 | + private long begin; // in ms | ||
13 | + private long stop; // in ms | ||
10 | 14 | ||
11 | - public MusicPattern(int[] pattern) { | 15 | + public MusicPattern(int[] pattern, int repeat, long begin) { |
12 | if(pattern.length != 4) | 16 | if(pattern.length != 4) |
13 | throw new InvalidPatternException(); | 17 | throw new InvalidPatternException(); |
14 | this.pattern = pattern; | 18 | this.pattern = pattern; |
19 | + this.totalLentgh = pattern[0] + pattern[1] + pattern[2] + pattern[3]; | ||
20 | + this.patternTiming[0] = pattern[0]; | ||
21 | + for(int i=1; i<4; i++) | ||
22 | + this.patternTiming[i] = this.patternTiming[i-1] + pattern[i]; | ||
23 | + this.begin = begin; | ||
24 | + this.stop = repeat * totalLentgh; | ||
25 | + } | ||
26 | + | ||
27 | + public double render(long tick) { // tick in ms | ||
28 | + if(tick <= begin) | ||
29 | + return 0; | ||
30 | + if(tick >= stop) | ||
31 | + return 0; | ||
32 | + int tickMod = (int) (tick % totalLentgh); | ||
33 | + if(tickMod < patternTiming[0]) | ||
34 | + return 0; | ||
35 | + if(tickMod < patternTiming[1]) | ||
36 | + return (double) (tickMod - patternTiming[0]) / (double) (pattern[1]); | ||
37 | + if(tickMod < patternTiming[2]) | ||
38 | + return 1; | ||
39 | + return 1 - ((double) (tickMod - patternTiming[2]) / (double) (pattern[3])); | ||
15 | } | 40 | } |
16 | } | 41 | } |