From: Einar Pehrson Date: Mon, 28 Apr 2003 01:08:49 +0000 (+0000) Subject: Added MooInstrumentList - a subcomponent to MooToolbar - X-Git-Url: https://ruin.nu/git/?p=moosique.git;a=commitdiff_plain;h=4ac3b6210979ea78dceb609a0501cb0265d00065 Added MooInstrumentList - a subcomponent to MooToolbar - and MooKeyboard - a keylistener intended for MooView or MooTrackView - and built up a basic frame in MooGUI to test them. Changed some details in Moosique and MooNote. --- diff --git a/MooGUI.java b/MooGUI.java index c06dc3a..0c17202 100644 --- a/MooGUI.java +++ b/MooGUI.java @@ -1,22 +1,33 @@ import javax.sound.midi.*; import javax.swing.*; +import java.awt.*; +import java.awt.event.*; /* * Moosique's graphical user interface. * - * @author Andersson, Andreen, Lanneskog, Pehrson - * @version 1 + * @author Mikael Andreen */ -public class MooGUI { +public class MooGUI extends JFrame implements WindowListener { Sequence seq; /* * Creates the GUI. */ - public MooGUI (Sequence seq) { - + public MooGUI(Sequence seq) { + super("Moosique"); + MooInstrumentList m = new MooInstrumentList(); + getContentPane().add(m); + m.addKeyListener(new MooKeyboard()); + pack(); + Dimension bounds = new Dimension(300,70); +// setSize(bounds.width,bounds.height); + setLocation((Toolkit.getDefaultToolkit().getScreenSize().width / 2) - (bounds.width / 2), (Toolkit.getDefaultToolkit().getScreenSize().height / 2) - (bounds.height / 2)); +// setResizable(false); + setBackground(Color.white); + setVisible(true); } /* @@ -26,4 +37,12 @@ public class MooGUI { public void setSequence(Sequence sequence) { seq = sequence; } + + public void windowOpened(WindowEvent e) {} + public void windowClosing(WindowEvent e) {} + public void windowClosed(WindowEvent e) {Moosique.quit();} + public void windowIconified(WindowEvent e) {} + public void windowDeiconified(WindowEvent e) {} + public void windowActivated(WindowEvent e) {} + public void windowDeactivated(WindowEvent e) {} } \ No newline at end of file diff --git a/MooInstrumentList.java b/MooInstrumentList.java new file mode 100644 index 0000000..3e538d4 --- /dev/null +++ b/MooInstrumentList.java @@ -0,0 +1,154 @@ +import javax.sound.midi.*; +import javax.swing.*; +import java.awt.event.*; + +/* + * A Combo Box where the instrument of the currently active channel can be selected. + * + * @author Einar Pehrson + */ + +public class MooInstrumentList extends JComboBox implements ActionListener { + + public MooInstrumentList() { + super(instruments); + addActionListener(this); + } + + public void actionPerformed(ActionEvent e) { + JComboBox box = (JComboBox)e.getSource(); + int instrument = box.getSelectedIndex(); + Moosique.getActiveChannel().programChange(instrument); + } + + public static final String[] instruments = { + " 0 Acoustic Grand Piano", + " 1 Bright Acoustic Piano", + " 2 Electric Grand Piano", + " 3 Honky-Tonk Piano", + " 4 Rhodes Piano", + " 5 Chorused Piano", + " 6 Harpischord", + " 7 Clavinet", + " 8 Celesta", + " 9 Glockenspiel", + " 10 Music Box", + " 11 Vibraphone", + " 12 Marimba", + " 13 Xylophone", + " 14 Tubular Bells", + " 15 Dulcimer", + " 16 Hammond Organ", + " 17 Percussive Organ", + " 18 Rock Organ", + " 19 Church Organ", + " 20 Reed Organ", + " 21 Accordion", + " 22 Harmonica", + " 23 Tango Accordion", + " 24 Acoustic Nylon Guitar", + " 25 Acoustic Steel Guitar", + " 26 Electric Jazz Guitar", + " 27 Electric Clean Guitar", + " 28 Electric Muted Guitar", + " 29 Overdriven Guitar", + " 30 Distortion Guitar", + " 31 Guitar Harmonics", + " 32 Acoustic Bass", + " 33 Electric Bass Fingered", + " 34 Electric Bass Picked", + " 35 Fretless Bass", + " 36 Slap Bass 1", + " 37 Slap Bass 2", + " 38 Synth Bass 1", + " 39 Synth Bass 2", + " 40 Violin", + " 41 Viola", + " 42 Cello", + " 43 Contrabass", + " 44 Tremolo Strings", + " 45 Pizzicato Strings", + " 46 Orchestral Harp", + " 47 Timpani", + " 48 String Ensemble 1", + " 49 String Ensemble 2", + " 50 Synth Strings 1", + " 51 Synth Strings 2", + " 52 Choir Aahs", + " 53 Voice Oohs", + " 54 Synth Voice", + " 55 Orchestral Hit", + " 56 Trumpet", + " 57 Trombone", + " 58 Tuba", + " 59 Muted Trumpet", + " 60 French Horn", + " 61 Brass Section", + " 62 Synth Brass 1", + " 63 Synth Brass 2", + " 64 Soprano Sax", + " 65 Alto Sax", + " 66 Tenor Sax", + " 67 Baritone Sax", + " 68 Oboe", + " 69 English Horn", + " 70 Bassoon", + " 71 Clarinet", + " 72 Piccolo", + " 73 Flute", + " 74 Recorder", + " 75 Pan Flute", + " 76 Bottle Blow", + " 77 Shakuhachi", + " 78 Whistle", + " 79 Ocarina", + " 80 Synth Lead 1 Square Wave Lead", + " 81 Synth Lead 2 Sawtooth Wave Lead", + " 82 Synth Lead 3 Caliope Lead", + " 83 Synth Lead 4 Chiff Lead", + " 84 Synth Lead 5 Charang", + " 85 Synth Lead 6 Solo Synth Voice", + " 86 Synth Lead 7 Bright Saw Wave", + " 87 Synth Lead 8 Brass and Lead", + " 88 Synth Pad 1 Fantasia Pad", + " 89 Synth Pad 2 Warm Pad", + " 90 Synth Pad 3 Poly Synth Pad", + " 91 Synth Pad 4 Space Voice Pad", + " 92 Synth Pad 5 Bowed Glass Pad", + " 93 Synth Pad 6 Metal Pad", + " 94 Synth Pad 7 Halo Pad", + " 95 Synth Pad 8 Sweep Pad", + " 96 Synth SFX 1 Ice Rain", + " 97 Synth SFX 2 Sound Track", + " 98 Synth SFX 3 Crystal", + " 99 Synth SFX 4 Atmosphere", + " 100 Synth SFX 5 Brightness", + " 101 Synth SFX 6 Goblin", + " 102 Synth SFX 7 Echo Drops", + " 103 Synth SFX 8 Star Theme", + " 104 Sitar", + " 105 Banjo", + " 106 Shamisen", + " 107 Koto", + " 108 Kalimba", + " 109 Bagpipe", + " 110 Fiddle", + " 111 Shanai", + " 112 Tinkle Bells", + " 113 Agogo", + " 114 Steel Drums", + " 115 Woodblock", + " 116 Taiko Drum", + " 117 Melodic Tom", + " 118 Synth Drum", + " 119 Reverse Cymbal", + " 120 Guitar Fret Noise", + " 121 Breath Noise", + " 122 Seashore", + " 123 Bird Tweet", + " 124 Telephone Ring", + " 125 Helicopter", + " 126 Applause", + " 127 Gunshot" + }; +} \ No newline at end of file diff --git a/MooKeyboard.java b/MooKeyboard.java new file mode 100644 index 0000000..0ebfa63 --- /dev/null +++ b/MooKeyboard.java @@ -0,0 +1,87 @@ +import javax.sound.midi.*; +import java.awt.event.*; + +/* + * Functional representation of a MIDI note, which contains two MIDI events, note on and note off. + * + * @author Einar Pehrson + */ + +public class MooKeyboard extends KeyAdapter { + + private boolean[] isOn = new boolean[120]; + private static final int startNote = 48; + private static final int[] keyToNote = new int[120]; + + /* + * Plays the appropriate MIDI NoteOn event. + */ + public void keyPressed(KeyEvent e) { + try { + // Retrieves the notenumber from the conversion array. + int noteNumber = keyToNote[e.getKeyCode()]; + // If note is not already on and the key is mapped to a note, sends the NoteOn event. + if (!isOn[noteNumber] && noteNumber > 0) Moosique.getActiveChannel().noteOn(noteNumber, 127); + isOn[noteNumber] = true; + } catch (ArrayIndexOutOfBoundsException x) { + return; + } + } + + /* + * Plays the appropriate MIDI NoteOff event. + */ + public void keyReleased(KeyEvent e) { + try { + // Retrieves the notenumber from the conversion array. + int noteNumber = keyToNote[e.getKeyCode()]; + // Sends the NoteOff event. + Moosique.getActiveChannel().noteOff(noteNumber); + isOn[noteNumber] = false; + } catch (ArrayIndexOutOfBoundsException x) { + return; + } + } + + /* Maps keycodes (array indices) to MIDI note numbers using the following layout: + * + * 2 3 5 6 7 9 0 => # # # # # # # + * q w e r t y u i o p => c d e f g a b c d e + * s d g h j l => # # # # # # + * z x c v b n m , . => c d e f g a b c d + */ + static { + keyToNote[90] = startNote; + keyToNote[83] = startNote + 1; + keyToNote[88] = startNote + 2; + keyToNote[68] = startNote + 3; + keyToNote[67] = startNote + 4; + keyToNote[86] = startNote + 5; + keyToNote[71] = startNote + 6; + keyToNote[66] = startNote + 7; + keyToNote[72] = startNote + 8; + keyToNote[78] = startNote + 9; + keyToNote[74] = startNote + 10; + keyToNote[77] = startNote + 11; + keyToNote[44] = startNote + 12; + keyToNote[76] = startNote + 13; + keyToNote[46] = startNote + 14; + keyToNote[81] = startNote + 12; + keyToNote[50] = startNote + 13; + keyToNote[87] = startNote + 14; + keyToNote[51] = startNote + 15; + keyToNote[69] = startNote + 16; + keyToNote[82] = startNote + 17; + keyToNote[53] = startNote + 18; + keyToNote[84] = startNote + 19; + keyToNote[54] = startNote + 20; + keyToNote[89] = startNote + 21; + keyToNote[55] = startNote + 22; + keyToNote[85] = startNote + 23; + keyToNote[73] = startNote + 24; + keyToNote[57] = startNote + 25; + keyToNote[79] = startNote + 26; + keyToNote[48] = startNote + 27; + keyToNote[80] = startNote + 28; + } +} \ No newline at end of file diff --git a/MooNote.java b/MooNote.java index 12e1238..2004788 100644 --- a/MooNote.java +++ b/MooNote.java @@ -1,16 +1,16 @@ import javax.sound.midi.*; /* - * Functional representation of a MIDI note, which contains two MIDI events, note on and note off. + * Functional representation of a MIDI note, which adds functionality to the existent MidiEvent class. + * Also provides a reference to the corresponding NoteOff event. * - * @author Andersson, Andreen, Lanneskog, Pehrson - * @version 2.0 + * @author Einar Pehrson */ public class MooNote extends MidiEvent { - private MidiEvent noteOffEvent; - private ShortMessage noteOnMsg, noteOffMsg; + protected MidiEvent noteOffEvent; + protected ShortMessage noteOnMsg, noteOffMsg; /* * Creates a MooNote from the given NoteOn event in the current track. diff --git a/Moosique.java b/Moosique.java index 01070c1..32c4d37 100644 --- a/Moosique.java +++ b/Moosique.java @@ -5,23 +5,23 @@ import java.io.*; /* * Moosique - The MIDI Tracker * - * Main class that handles initiation, IO and sound FX. + * Main class that handles initiation, IO and sound. * - * @author Andersson, Andreen, Lanneskog, Pehrson - * @version 1 + * @author Einar Pehrson */ public class Moosique { - private static MooGUI gui; - private static Sequence seq; + protected static MooGUI gui; + protected static Sequence seq; - private static Sequencer sequencer = null; - private static Synthesizer synthesizer = null; - private static MidiChannel[] channels; + protected static Sequencer sequencer = null; + protected static Synthesizer synthesizer = null; + protected static MidiChannel[] channels; + protected static MidiChannel activeChannel; - private static String filename; - private static long position; + protected static String filename; + protected static long position; /* * Starts the application. @@ -34,12 +34,12 @@ public class Moosique { sequencer = MidiSystem.getSequencer(); System.out.print("."); sequencer.open(); - System.out.print("."); synthesizer = MidiSystem.getSynthesizer(); System.out.print("."); synthesizer.open(); - System.out.print("."); sequencer.getTransmitter().setReceiver(synthesizer.getReceiver()); + channels = synthesizer.getChannels(); + setActiveChannel(0); } catch (MidiUnavailableException e) { System.out.println("Failed, quitting."); quit(); @@ -58,7 +58,6 @@ public class Moosique { // Sets up channels and GUI. System.out.print("Creating GUI..."); - channels = synthesizer.getChannels(); gui = new MooGUI(seq); System.out.println("Done"); } @@ -72,13 +71,36 @@ public class Moosique { } /* - * Returns a pointer to the current sequence. - * @return the current sequence + * Returns a pointer to the MidiChannels of the selected synthesizer. + * @return the available MidiChannels + */ + public static MidiChannel[] getChannels() { + return channels; + } + + /* + * Returns a pointer to the currently active MidiChannel. + * @return the active MidiChannel + */ + public static MidiChannel getActiveChannel() { + return activeChannel; + } + + /* + * Sets the currently active MidiChannel. + * @param channel the number of the MidiChannel to activate + */ + public static void setActiveChannel(int channel) { + activeChannel = channels[channel]; + } + + /* + * Replaces the current sequence with a new one, holding three empty tracks. */ public static void clearSequence() { // Creates sequence. try { - seq = new Sequence(Sequence.PPQ, 96); + seq = new Sequence(Sequence.PPQ, 96, 3); } catch (InvalidMidiDataException e) {} // Sends sequence to GUI. if (gui != null) gui.setSequence(seq); diff --git a/To Do.txt b/To Do.txt index ba19b3b..907d0a3 100644 --- a/To Do.txt +++ b/To Do.txt @@ -1,9 +1,6 @@ * Inställningar - MIDI-enhet Öppna en dialogruta med innehållet i getMidiDeviceInfo() och låt användaren välja. -* Keyjazz - MidiChannel: noteOn, programChange etc. - * Referenser eller objekt?!? tracks.get(tracks.indexOf(noteOffEvent) ??? @@ -16,4 +13,20 @@ * Kanalinställning Hur sparas i spår? -* Rolle är dum // Einar \ No newline at end of file +* Global KeyListener + Görs uppenbarligen så här: + + JFrame someFrame = new JFrame(); + + JComponent rootPane = someFrame.getRootPane(); + ActionMap am = rootPane.getActionMap(); + + Action helpAction = new AbstractAction() { + public void actionPerformed(ActionEvent ae) { + showHelpWindow(); + }}; + am.put("help", helpAction); + + InputMap im = rootPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + KeyStroke helpKey = KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0); + im.put(helpKey, "help"); \ No newline at end of file