From e49cbedbb512d2cbadb19f9b4b84c1b0ef39ff9c Mon Sep 17 00:00:00 2001 From: Einar Pehrson Date: Tue, 27 May 2003 22:25:48 +0000 Subject: [PATCH] no message --- MooDialog.java | 18 +- MooGUI.java | 6 +- MooToolbar.java | 23 ++- MooTrackTitle.java | 29 --- MooView.java | 13 ++ Moosique.java | 459 ++++++++++++++++++++++++++------------------- To Do.txt | 12 +- images/stop.gif | Bin 93 -> 869 bytes 8 files changed, 322 insertions(+), 238 deletions(-) diff --git a/MooDialog.java b/MooDialog.java index 07e719a..fc9c2c0 100644 --- a/MooDialog.java +++ b/MooDialog.java @@ -30,7 +30,8 @@ public class MooDialog extends JDialog { SET_TEMPO = 9, PREFERENCES = 10, TRANSPOSE = 11, - SCALE_VELOCITY = 12; + SCALE_VELOCITY = 12, + RECORD = 13; /** * Constructor of the dialogs. @@ -701,6 +702,21 @@ public class MooDialog extends JDialog { */ } + private void makeRecordDialog(Container pane) { + /* Show a dialog with: + "Track" combo box, + "Channel" field? (disabled?, + "Quantize" pane with + "Quantize" checkbox, + "Resolution" combo box, + "Location" checkboxes and + "Duration" checkboxes + "Start Recording" button. + + Moosique.record(track); + */ + } + private MooNote note; private JOptionPane optionPane; private JTextField pitch; diff --git a/MooGUI.java b/MooGUI.java index 57759c9..2ae23a6 100644 --- a/MooGUI.java +++ b/MooGUI.java @@ -19,7 +19,7 @@ public class MooGUI extends JFrame { private MooView view; private JLabel statusBar; private java.util.Timer timer; - private boolean updateView = true; + private boolean updateView = false; public static final int statusResetDelay = 3000; public static final Font FONT = new Font("Helvetica", Font.PLAIN, 10); public static final Color bgColor = new Color(192, 224, 255); @@ -146,6 +146,10 @@ public class MooGUI extends JFrame { toolbar.updateProgInd(tickPosition); } + public MooView getView() { + return view; + } + /** * Creates an action for a specific octave. * @param increase true for increase, false for decrease diff --git a/MooToolbar.java b/MooToolbar.java index bca50ef..de41669 100644 --- a/MooToolbar.java +++ b/MooToolbar.java @@ -10,7 +10,7 @@ import java.awt.event.*; */ public class MooToolbar extends JToolBar { - private JButton rewind, playpause, stop, fastforward; + private JButton rewind, playpause, stop, fastforward, record; private JLabel measure, beats, ticks, measuresValue, beatsValue, ticksValue; private JPanel progIndPanel; private ImageIcon playIcon, pauseIcon; @@ -31,6 +31,7 @@ public class MooToolbar extends JToolBar { // Creates playback buttons rewind = createButton("images/rewind.gif", "Rewind"); + record = createButton("images/record.gif", "Record"); playpause = createButton("images/play.gif", "Play"); stop = createButton("images/stop.gif", "Stop"); fastforward = createButton("images/forward.gif", "Fast forward"); @@ -39,6 +40,7 @@ public class MooToolbar extends JToolBar { // Adds playback buttons add(rewind); + add(record); add(playpause); add(stop); add(fastforward); @@ -81,10 +83,10 @@ public class MooToolbar extends JToolBar { System.out.println("1:1:1"); } else { int[] position = Moosique.getPositionForTicks(tickPosition); - System.out.println("" + position[0] + ":" + position[1] + ":" + position[2]); - measuresValue.setText(Integer.toString(position[0])); - beatsValue.setText(Long.toString(position[1])); - ticksValue.setText(Long.toString(position[2])); + System.out.println("" + (position[0] + 1) + ":" + (position[1] + 1) + ":" + (position[2] + 1)); + measuresValue.setText(Integer.toString(position[0] + 1)); + beatsValue.setText(Long.toString(position[1] + 1)); + ticksValue.setText(Long.toString(position[2] + 1)); } } @@ -151,16 +153,17 @@ public class MooToolbar extends JToolBar { } else if (command == "Resume") { updatePlayButton("Pause", pauseIcon); Moosique.resume(); + } else if (command == "Stop") { + updatePlayButton("Play", playIcon); + Moosique.stop(); + } else if (command == "Record") { + MooDialog recordDialog = new MooDialog(MooDialog.RECORD); } else if (command == "Rewind") { - System.out.println("Rewound!"); - // Different implementation, perhaps? updatePlayButton("Play", playIcon); Moosique.setEditPosition(0); Moosique.stop(); } else if (command == "Fast forward") { - } else if (command == "Stop") { - updatePlayButton("Play", playIcon); - Moosique.stop(); + } } else if (e.getSource() instanceof JLabel) { long position = Moosique.getEditPosition(); diff --git a/MooTrackTitle.java b/MooTrackTitle.java index 4822dca..9cffb14 100644 --- a/MooTrackTitle.java +++ b/MooTrackTitle.java @@ -22,7 +22,6 @@ public class MooTrackTitle extends JPanel { private JComboBox channelBox; private JCheckBox mute; private JCheckBox solo; - private JButton record; private String trackName = ""; private int channel = 0; @@ -106,11 +105,6 @@ public class MooTrackTitle extends JPanel { solo.addActionListener(tl); checkboxes.add(solo); - record = new JButton("Record"); - record.setFont(Moosique.getGUI().FONT); - record.addActionListener(tl); - checkboxes.add(record); - add(checkboxes); } @@ -174,29 +168,6 @@ public class MooTrackTitle extends JPanel { Moosique.setTrackMute(track, false); } Moosique.setTrackSolo(track, selected); - } else if (source == record) { - Sequencer sequencer = Moosique.getSequencer(); - boolean quantize = false; - if (record.getText() == "Record") { - /* Show a dialog with: - "Track" combo box, - "Channel" combo box (disabled?, - "Quantize" checkbox and - "Start Recording" button. - */ - record.setText("Stop"); - mtv.enableKeyboardRecording(); - sequencer.recordEnable(track, channel); - sequencer.startRecording(); - Moosique.setEdited(); - } else { - record.setText("Record"); - mtv.disableKeyboardRecording(); - sequencer.stopRecording(); - sequencer.recordDisable(track); - java.util.List newNotes = Moosique.convertTrack(track, quantize); - mtv.placeNewNotes(newNotes); - } } } } diff --git a/MooView.java b/MooView.java index a5ebf90..9bf8367 100644 --- a/MooView.java +++ b/MooView.java @@ -120,6 +120,19 @@ public class MooView extends JScrollPane { getViewport().setViewPosition(new Point((int)getViewport().getViewPosition().getX(), (int)(tickPosition / (Moosique.getSequence().getResolution() / 4)) * MooTrackView.NOTE_HEIGHT)); } + + /** + * Creates a view for the given track and adds it to the main view. + * @param track the track for which to find the view + */ + public MooTrackView getTrackView(Track track) { + for (int i = 0; i < trackPanel.getComponents().length; i++) { + MooTrackView mtv = (MooTrackView)(trackPanel.getComponents())[i]; + if(mtv.getTrack() == track) return mtv; + } + return null; + } + /** * Creates a view for the given track and adds it to the main view. * @param track the track for which to add a view diff --git a/Moosique.java b/Moosique.java index 5ad1afe..68bfd17 100644 --- a/Moosique.java +++ b/Moosique.java @@ -20,6 +20,8 @@ public class Moosique { private static Receiver receiver; private static MidiChannel[] channels; private static MidiChannel activeChannel; + private static Track recordTrack = null; + private static MooTrackView recordTrackView = null; private static ArrayList copyBuffer, emptyTracks, timeSignatures, tempoChanges; private static TreeSet selection; @@ -31,7 +33,7 @@ public class Moosique { private static long editPosition; private static boolean makeGUI = true, initSound = true, edited = false, drawEmptyTracks = false; public static final int DEFAULT_RESOLUTION = 96, DEFAULT_TRACKS = 4; - public static final int WHOLE_NOTE = 0, HALF_NOTE = 1, QUARTER_NOTE = 2, EIGHTH_NOTE = 3, SIXTEENTH_NOTE = 4; + public static final int WHOLE_NOTE = 16, HALF_NOTE = 8, QUARTER_NOTE = 4, EIGHTH_NOTE = 2, SIXTEENTH_NOTE = 1; /** * Starts the application. @@ -52,20 +54,22 @@ public class Moosique { // Acquires MIDI devices and connects them. out("Initializing MIDI devices.", false); try { - // Configures sequencer + // Configures sequencer. sequencer = MidiSystem.getSequencer(); advanceStatus(); sequencer.open(); sequencer.addMetaEventListener(new SongEndListener()); - // Configures synthesizer + // Configures synthesizer. synthesizer = MidiSystem.getSynthesizer(); advanceStatus(); synthesizer.open(); - // Configures receiver, transmitter and channels. + // Connects devices. receiver = synthesizer.getReceiver(); sequencer.getTransmitter().setReceiver(receiver); + + // Configures channels. channels = synthesizer.getChannels(); setActiveChannel(0); } catch (MidiUnavailableException e) { @@ -166,41 +170,6 @@ public class Moosique { return gui; } - /** - * Calculates the position (measures, beats, ticks) in the current sequence for the given tick position. - * @param tickPosition the tick position for which to calculate the position - * @return an array of integers where index 0 is measures, 1 is beats and 2 is ticks. - */ - public static int[] getPositionForTicks(long tickPosition) { - int ticksPerBeat = seq.getResolution(), sigs = timeSignatures.size(), beatsPerMeasure = 4; - long measures = 0, beats = 0, ticks = 0; - if (sigs > 1) { - /* - Iterator it = timeSignatures.iterator(); - MidiEvent lastTSEvent = (MidiEvent)it.next(); - if (lastTSEvent.getTick() != 0) tickPos += (int)lastTSEvent.getTick(); - while(it.hasNext()) { - MidiEvent nextTSEvent = (MidiEvent)it.next(); - long tickDiff = nextTSEvent.getTick() - lastTSEvent.getTick(); - ts = decodeTimeSig(((MetaMessage)lastTSEvent.getMessage()).getData()); - beatsPerMeasure = ts[0] * (4 / ts[1]); - tickPos += ((beatsPerMeasure * measures + beats) * res + ticks); - } - */ - } else { - if (sigs == 1) { - MidiEvent TSEvent = (MidiEvent)timeSignatures.get(0); - int[] ts = decodeTimeSig(((MetaMessage)TSEvent.getMessage()).getData()); - beatsPerMeasure = ts[0] * (4 / ts[1]); - } - measures = tickPosition / (beatsPerMeasure * ticksPerBeat); - beats = (tickPosition - measures * beatsPerMeasure * ticksPerBeat) / ticksPerBeat; - ticks = tickPosition - measures * beatsPerMeasure * ticksPerBeat - beats * ticksPerBeat; - } - int[] pos = {(int)measures + 1, (int)beats + 1, (int)ticks + 1}; - return pos; - } - /** * Returns the receiver of the current sequencer. * @return the receiver @@ -225,73 +194,6 @@ public class Moosique { return sequencer; } - /** - * Returns the tempo in the given tick position. - * @param tick the tick position for which to return the tempo - * @return the tempo at the specified tick position - */ - public static int getTempo(long tick) { - if (tempoChanges.size() == 0) return 120; - MidiEvent tempoEvent = (MidiEvent)tempoChanges.get(0); - if (tempoChanges.size() > 1) { - for (int i = 1; i < tempoChanges.size(); i++) { - MidiEvent nextTempoEvent = (MidiEvent)tempoChanges.get(i); - if (nextTempoEvent.getTick() < tick && nextTempoEvent.getTick() > tempoEvent.getTick()) - tempoEvent = nextTempoEvent; - } - } - return decodeTempo(((MetaMessage)tempoEvent.getMessage()).getData()); - } - - /** - * Calculates the tick position in the current sequence for the given position (measures, beats, ticks). - * @return the tick position. - */ - public static long getTicksForPosition(int measures, int beats, int ticks) { - int res = seq.getResolution(); - long tickPos = 0; - switch (timeSignatures.size()) { - case 0: - tickPos = (4 * measures + beats) * res + ticks; - case 1: - MidiEvent TSEvent = (MidiEvent)timeSignatures.get(0); - int[] ts = decodeTimeSig(((MetaMessage)TSEvent.getMessage()).getData()); - int beatsPerMeasure = ts[0] * (4 / ts[1]); - tickPos = (beatsPerMeasure * measures + beats) * res + ticks; - default: - Iterator it = timeSignatures.iterator(); - MidiEvent lastTSEvent = (MidiEvent)it.next(); - if (lastTSEvent.getTick() != 0) tickPos += (int)lastTSEvent.getTick(); - while(it.hasNext()) { - MidiEvent nextTSEvent = (MidiEvent)it.next(); - long tickDiff = nextTSEvent.getTick() - lastTSEvent.getTick(); - ts = decodeTimeSig(((MetaMessage)lastTSEvent.getMessage()).getData()); - beatsPerMeasure = ts[0] * (4 / ts[1]); - tickPos += ((beatsPerMeasure * measures + beats) * res + ticks); - } - } - return tickPos; - } - - /** - * Returns the time signature in the given tick position. - * @param tick the tick position for which to return the time signature - * @return an array of two integers where [0] is the numerator and [1] the denominator - */ - public static int[] getTimeSig(long tick) { - int[] ts = {4, 4}; - if (timeSignatures.size() == 0) return ts; - MidiEvent timeSigEvent = (MidiEvent)timeSignatures.get(0); - if (timeSignatures.size() > 1) { - for (int i = 1; i < timeSignatures.size(); i++) { - MidiEvent nextTimeSigEvent = (MidiEvent)timeSignatures.get(i); - if (nextTimeSigEvent.getTick() < tick && nextTimeSigEvent.getTick() > timeSigEvent.getTick()) - timeSigEvent = nextTimeSigEvent; - } - } - return decodeTimeSig(((MetaMessage)timeSigEvent.getMessage()).getData()); - } - /** * Returns true if the current sequence has been edited. * @return the tick position @@ -431,75 +333,6 @@ public class Moosique { - /* *** - ** ENCODING / DECODING METHODS ** - *** */ - - - - - - - - - /** - * Returns the byte array for the given tempo. - * @param tempo the tempo in beats per minute - * @return an array of bytes representing the given tempo - */ - public static byte[] encodeTempo(int tempo) { - int microSecsPerQuarter = 60000000 / tempo; - byte[] b = new byte[3]; - b[0] = (byte)(microSecsPerQuarter / 65536); - b[1] = (byte)((microSecsPerQuarter - (b[0] * 65536)) / 256); - b[2] = (byte)(microSecsPerQuarter - (b[0] * 65536) - (b[1] * 256)); - return b; - } - - /** - * Returns the tempo for the given byte array. - * @param an array of three bytes representing the tempo - * @return the tempo in beats per minute - */ - public static int decodeTempo(byte[] bytes) { - return 60000000 / (bytes[0] * 65536 + bytes[1] * 256 + bytes[2]); - } - - /** - * Returns the byte array for the given time signature. - * @param numerator the numerator of the time signature - * @param denominator the denominator of the time signature - * @return an array of bytes representing the given time signature - */ - public static byte[] encodeTimeSig(int numerator, int denominator) { - byte[] b = { - (byte)numerator, - (byte)(Math.log(denominator) / Math.log(2)), // logarithm of denominator in base 2 - (byte)96, - (byte)8 - }; - return b; - } - /** - * Returns the time signature for the given byte array. - * @param an array of four bytes representing the time signature - * @return an array of two integers where [0] is the numerator and [1] the denominator - */ - public static int[] decodeTimeSig(byte[] bytes) { - int[] t = { - (int)bytes[0], - (int)(1 << bytes[1]) - }; - return t; - } - - - - - - - - /* *** ** SELECTION METHODS ** *** */ @@ -637,6 +470,221 @@ public class Moosique { sequencer.setTickPosition(editPosition); player = null; gui.update((long)0); + + if (recordTrack != null && recordTrackView != null) { + recordTrackView.disableKeyboardRecording(); + sequencer.stopRecording(); + sequencer.recordDisable(recordTrack); +// if (quantize) recordTrackView.placeNewNotes(quantize( +// convertTrack(recordTrack), SIXTEENTH_NOTE, true, true)); +// else recordTrackView.placeNewNotes(Moosique.convertTrack(recordTrack)); + } + } + + /** + * Enables recording to the given track. + */ + public static boolean record(Track track) { +/* try { + sequencer.recordEnable(track, channel); + sequencer.startRecording(); + } catch(Exception e) { + return false; + } + recordTrackView = gui.getView().getTrackView(track); + recordTrackView.enableKeyboardRecording(); + Moosique.setEdited(); +*/ + return true; + } + + + + + + + + + /* *** + ** TEMPO & TIME SIGNATURE METHODS ** + *** */ + + + + + + + + + /** + * Returns the byte array for the given tempo. + * @param tempo the tempo in beats per minute + * @return an array of bytes representing the given tempo + */ + public static byte[] encodeTempo(int tempo) { + int microSecsPerQuarter = 60000000 / tempo; + byte[] b = new byte[3]; + b[0] = (byte)(microSecsPerQuarter / 65536); + b[1] = (byte)((microSecsPerQuarter - (b[0] * 65536)) / 256); + b[2] = (byte)(microSecsPerQuarter - (b[0] * 65536) - (b[1] * 256)); + return b; + } + + /** + * Returns the tempo for the given byte array. + * @param an array of three bytes representing the tempo + * @return the tempo in beats per minute + */ + public static int decodeTempo(byte[] bytes) { + return 60000000 / (bytes[0] * 65536 + bytes[1] * 256 + bytes[2]); + } + + /** + * Returns the tempo in the given tick position. + * @param tick the tick position for which to return the tempo + * @return the tempo at the specified tick position + */ + public static int getTempo(long tick) { + if (tempoChanges.size() == 0) return 120; + MidiEvent tempoEvent = (MidiEvent)tempoChanges.get(0); + if (tempoChanges.size() > 1) { + for (int i = 1; i < tempoChanges.size(); i++) { + MidiEvent nextTempoEvent = (MidiEvent)tempoChanges.get(i); + if (nextTempoEvent.getTick() < tick && nextTempoEvent.getTick() > tempoEvent.getTick()) + tempoEvent = nextTempoEvent; + } + } + return decodeTempo(((MetaMessage)tempoEvent.getMessage()).getData()); + } + + /** + * Returns the byte array for the given time signature. + * @param numerator the numerator of the time signature + * @param denominator the denominator of the time signature + * @return an array of bytes representing the given time signature + */ + public static byte[] encodeTimeSig(int numerator, int denominator) { + byte[] b = { + (byte)numerator, + (byte)(Math.log(denominator) / Math.log(2)), // logarithm of denominator in base 2 + (byte)96, + (byte)8 + }; + return b; + } + /** + * Returns the time signature for the given byte array. + * @param an array of four bytes representing the time signature + * @return an array of two integers where [0] is the numerator and [1] the denominator + */ + public static int[] decodeTimeSig(byte[] bytes) { + int[] t = { + (int)bytes[0], + (int)(1 << bytes[1]) + }; + return t; + } + + /** + * Returns the time signature in the given tick position. + * @param tick the tick position for which to return the time signature + * @return an array of two integers where [0] is the numerator and [1] the denominator + */ + public static int[] getTimeSig(long tick) { + int[] ts = {4, 4}; + if (timeSignatures.size() == 0) return ts; + MidiEvent timeSigEvent = (MidiEvent)timeSignatures.get(0); + if (timeSignatures.size() > 1) { + for (int i = 1; i < timeSignatures.size(); i++) { + MidiEvent nextTimeSigEvent = (MidiEvent)timeSignatures.get(i); + if (nextTimeSigEvent.getTick() < tick && nextTimeSigEvent.getTick() > timeSigEvent.getTick()) + timeSigEvent = nextTimeSigEvent; + } + } + return decodeTimeSig(((MetaMessage)timeSigEvent.getMessage()).getData()); + } + + /** + * Calculates the position (measures, beats, ticks) in the current sequence for the given tick position. + * @param tickPosition the tick position for which to calculate the position + * @return an array of integers where index 0 is measures, 1 is beats and 2 is ticks. + */ + public static int[] getPositionForTicks(long tickPosition) { + int ticksPerBeat = seq.getResolution(); + long measures = 0, beats = 0, ticks = 0; + + // Counts for each time signature change up to the last one before the given tick position. + Iterator it = timeSignatures.iterator(); + MidiEvent lastTSEvent = (MidiEvent)it.next(); + while(it.hasNext()) { + MidiEvent nextTSEvent = (MidiEvent)it.next(); + if (nextTSEvent.getTick() > tickPosition) break; + long tickDiff = nextTSEvent.getTick() - lastTSEvent.getTick(); + int[] ts = decodeTimeSig(((MetaMessage)lastTSEvent.getMessage()).getData()); + int beatsPerMeasure = ts[0] * (4 / ts[1]); + long thisTSMeasures = tickDiff / (beatsPerMeasure * ticksPerBeat); + measures += thisTSMeasures; + long thisTSBeats = (tickDiff - thisTSMeasures * beatsPerMeasure * ticksPerBeat) / ticksPerBeat; + beats += thisTSBeats; + ticks += tickDiff - thisTSMeasures * beatsPerMeasure * ticksPerBeat - thisTSBeats * ticksPerBeat; + lastTSEvent = nextTSEvent; + } + + // Counts from the given tick position to the last time signature change before it. + long tickDiff = tickPosition - lastTSEvent.getTick(); + int[] ts = decodeTimeSig(((MetaMessage)lastTSEvent.getMessage()).getData()); + int beatsPerMeasure = ts[0] * (4 / ts[1]); + long thisTSMeasures = tickDiff / (beatsPerMeasure * ticksPerBeat); + measures += thisTSMeasures; + long thisTSBeats = (tickDiff - thisTSMeasures * beatsPerMeasure * ticksPerBeat) / ticksPerBeat; + beats += thisTSBeats; + ticks += tickDiff - thisTSMeasures * beatsPerMeasure * ticksPerBeat - thisTSBeats * ticksPerBeat; + + // Corrects any overflows. + if (ticks > ticksPerBeat) { + beats += Math.floor(ticks / ticksPerBeat); + ticks = ticks % ticksPerBeat; + } + if (beats > beatsPerMeasure) { + measures += Math.floor(beats / beatsPerMeasure); + beats = beats % beatsPerMeasure; + } + + // Returns the calculated values. + int[] pos = {(int)measures, (int)beats, (int)ticks}; + return pos; + } + + /** + * Calculates the tick position in the current sequence for the given position (measures, beats, ticks). + * @param measures the measure of the current position + * @param beats the beat of the current position + * @param tick the tick of the current position + * @return the tick position. + */ + public static long getTicksForPosition(int measures, int beats, int ticks) { + int res = seq.getResolution(); + int[] lastTSPos = new int[3]; + long tickPosition = 0; + + // Counts for each time signature change up to the last one before the given tick position. + Iterator it = timeSignatures.iterator(); + MidiEvent lastTSEvent = (MidiEvent)it.next(); + while(it.hasNext()) { + MidiEvent nextTSEvent = (MidiEvent)it.next(); + int[] nextTSPos = getPositionForTicks(nextTSEvent.getTick()); + if (nextTSPos[0] >= measures) break; + lastTSPos = nextTSPos; + lastTSEvent = nextTSEvent; + } + + // Counts from the given tick position to the last time signature change before it. + int measdiff = measures - lastTSPos[0]; + int[] ts = decodeTimeSig(((MetaMessage)lastTSEvent.getMessage()).getData()); + int beatsPerMeasure = ts[0] * (4 / ts[1]); + tickPosition = lastTSEvent.getTick() + (beatsPerMeasure * measures + beats) * res + ticks; + + return tickPosition; } @@ -684,7 +732,7 @@ public class Moosique { // Reinitializes sequence variables file = null; - reinitializeVariables(); + reinitializeLists(); // Sends the sequence to the GUI. if (gui != null) gui.setSequence(seq, null); @@ -718,7 +766,7 @@ public class Moosique { * @param quantize whether to round locations and durations in the track to nearest 16th * @return a list of the created MooNotes */ - public static List convertTrack(Track track, boolean quantize) { + public static List convertTrack(Track track) { // Searches the track for NoteOn and NoteOff events ArrayList noteOns = new ArrayList(track.size() / 2); ArrayList noteOffs = new ArrayList(track.size() / 2); @@ -773,7 +821,6 @@ public class Moosique { iOn.remove(); } } - if (quantize) quantize(newMooNotes, SIXTEENTH_NOTE, true, true); return newMooNotes; } @@ -789,7 +836,7 @@ public class Moosique { edited = false; Track[] tracks = seq.getTracks(); - reinitializeVariables(); + reinitializeLists(); // Searches track 0 for changes in tempo and time signature. MidiEvent event; @@ -808,9 +855,25 @@ public class Moosique { Collections.sort(tempoChanges, c); Collections.sort(timeSignatures, c); + try { + // If no time signature specified at tick 0, adds the standard one. + if (timeSignatures.size() == 0 || ((MidiEvent)timeSignatures.get(0)).getTick() != 0) { + MetaMessage timeSigMsg = new MetaMessage(); + timeSigMsg.setMessage(88, encodeTimeSig(4, 4), 4); + timeSignatures.add(0, new MidiEvent(timeSigMsg, (long)0)); + } + + // If no tempo specified at tick 0, adds the standard one. + if (tempoChanges.size() == 0 || ((MidiEvent)tempoChanges.get(0)).getTick() != 0) { + MetaMessage tempoMsg = new MetaMessage(); + tempoMsg.setMessage(81, encodeTempo(120), 3); + tempoChanges.add(0, new MidiEvent(tempoMsg, (long)0)); + } + } catch (Exception e) {} + // Converts tracks. for (int i = 0; i < tracks.length; i++) { - convertTrack(tracks[i], false); + convertTrack(tracks[i]); } // Sends sequence to GUI and sequencer, then returns @@ -828,21 +891,35 @@ public class Moosique { * @param location whether the quantize should affect the location of the note * @param duration whether the quantize should affect the duration of the note */ - public static void quantize(List notes, int resolution, boolean location, boolean duration) { - // Math.round(mn.getTick() / ticksPerSixteenth); + public static List quantize(List notes, int resolution, boolean location, boolean duration) { + Iterator it = notes.iterator(); + int noteSize = resolution * seq.getResolution() / 4; + while(it.hasNext()) { + MidiEvent note = (MidiEvent)it.next(); + if (note instanceof MooNote) { + MooNote mn = (MooNote)note; + if (location) mn.setTick(Math.round(mn.getTick() / noteSize) * noteSize); + if (duration) { + int length = Math.round(mn.getDuration() / noteSize) * noteSize; + if (length < noteSize) length = noteSize; + mn.setDuration(length); + } + } + } + return notes; } /** - * Reinitializes sequence-specific variables. + * Reinitializes sequence-specific collections. */ - private static void reinitializeVariables() { - emptyTracks = new ArrayList(); - timeSignatures = new ArrayList(); - tempoChanges = new ArrayList(); - trackSolo = new HashMap(); - trackMute = new HashMap(); - copyBuffer = new ArrayList(); - selection = new TreeSet(); + private static void reinitializeLists() { + emptyTracks = new ArrayList(); + timeSignatures = new ArrayList(); + tempoChanges = new ArrayList(); + copyBuffer = new ArrayList(); + trackSolo = new HashMap(); + trackMute = new HashMap(); + selection = new TreeSet(); } /** diff --git a/To Do.txt b/To Do.txt index d655e6d..a2b54a2 100644 --- a/To Do.txt +++ b/To Do.txt @@ -1,8 +1,8 @@ AKTIVITET -Björn Menyn -Einar Tempo / taktart +Björn Menyn, dialogerna +Einar Inspelning Mike Rolle Spara konfiguration Arbetskatalog @@ -14,13 +14,10 @@ BUGGAR x Exceptions vid inspelning till ny fil. x Play-knappen ändras inte till Pause. x Varför ritar den ut de tomma spåren i en ny fil? Rätt, men hur? -x Varför hänger sig Play om man ändrar duration på en not? +x Varför hänger sig Play när man spelar in eller ändrar längd på en not? x Kopiera/flytta spår, möjligt? -TEMPO / TAKTART -x Implementera getTicksForPosition, getPositionForTicks och quantize i Moosique. - ANNAT x Fixa InstrumentList. x Textfält som gör att man bara kan skriva in siffror? (MooNoteProp) @@ -36,6 +33,9 @@ Vilka mer booleaner ska man kunna SWING + MooDialog + Fixa en Record-dialog. + MooView Lägg till en tom panel för att fylla ut skärmen. Med BoxLayout? diff --git a/images/stop.gif b/images/stop.gif index 0b6558ff0f6ed6569d74c237efa59896e1d54314..fdb33e35cd5e841169d0cbfa3d6c5c6ed649b9ae 100644 GIT binary patch literal 869 zcmZ?wbh9u|6k`x$_|5#mvND4FFnmA+P`d literal 93 zcmZ?wbhEHb6k`x$XkY+=|Ns9h{u6aBN=+?% sZs}in`Yr$BIagY`jnCM;>8oAvy=OYdqPeFwMrDS5^0{6X%fMg_0Ba^8v;Y7A -- 2.39.2