From f93d4c5dd61cd3f5d0c09e5c338c636699da24f7 Mon Sep 17 00:00:00 2001 From: Christopher Baines Date: Sun, 18 Sep 2011 23:13:32 +0100 Subject: New Keyboard using midi, cleaned simple keyboard. --- .../src/uk/ac/open/punchingbag/PunchingBagGUI.java | 7 +- .../uk/ac/open/punchingbag/examples/Keyboard.java | 316 +++++++++++++++++++++ .../open/punchingbag/examples/SimpleKeyboard.java | 137 --------- 3 files changed, 320 insertions(+), 140 deletions(-) create mode 100644 PunchingBag/src/uk/ac/open/punchingbag/examples/Keyboard.java diff --git a/PunchingBag/src/uk/ac/open/punchingbag/PunchingBagGUI.java b/PunchingBag/src/uk/ac/open/punchingbag/PunchingBagGUI.java index 7a7010c..f76c033 100644 --- a/PunchingBag/src/uk/ac/open/punchingbag/PunchingBagGUI.java +++ b/PunchingBag/src/uk/ac/open/punchingbag/PunchingBagGUI.java @@ -53,6 +53,7 @@ import javax.sound.sampled.UnsupportedAudioFileException; import javax.sound.sampled.AudioFormat.Encoding; import javax.sound.sampled.Mixer.Info; +import uk.ac.open.punchingbag.examples.Keyboard; import uk.ac.open.punchingbag.examples.SimpleKeyboard; import PicHelper.ImagePanel; @@ -64,7 +65,7 @@ public class PunchingBagGUI implements MouseListener, MouseMotionListener, Debug, Menu }; - Mode currentMode = Mode.Menu; + Mode currentMode = Mode.Debug; JFrame frame; @@ -94,7 +95,7 @@ public class PunchingBagGUI implements MouseListener, MouseMotionListener, public static void main(String[] args) throws InterruptedException { new PunchingBagGUI(); - new SimpleKeyboard(); + new Keyboard(); } PunchingBagGUI() throws InterruptedException { @@ -146,7 +147,7 @@ public class PunchingBagGUI implements MouseListener, MouseMotionListener, programOptionsPanel.add(new JButton("Debug")); frame.add(bagDebugingPanel); - frame.add(new DisplayPanel(), BorderLayout.CENTER); + //frame.add(new DisplayPanel(), BorderLayout.CENTER); frame.add(programOptionsPanel, BorderLayout.SOUTH); setMode(currentMode); diff --git a/PunchingBag/src/uk/ac/open/punchingbag/examples/Keyboard.java b/PunchingBag/src/uk/ac/open/punchingbag/examples/Keyboard.java new file mode 100644 index 0000000..b502748 --- /dev/null +++ b/PunchingBag/src/uk/ac/open/punchingbag/examples/Keyboard.java @@ -0,0 +1,316 @@ +package uk.ac.open.punchingbag.examples; + +import java.awt.Color; +import java.awt.Rectangle; +import java.io.File; +import java.io.IOException; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Synthesizer; +import javax.sound.midi.Track; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.UnsupportedAudioFileException; + +import uk.ac.open.punchingbag.ButtonListener; +import uk.ac.open.punchingbag.Contact; +import uk.ac.open.punchingbag.PunchingBag; + +public class Keyboard implements Runnable, ButtonListener { + + Sequence[] notes = new Sequence[20]; + + static PunchingBag bag = PunchingBag.getBag(); + long lastActionTime = System.currentTimeMillis(); + boolean noising = false; + + public static final int DAMPER_PEDAL = 64; + + public static final int DAMPER_ON = 127; + + public static final int DAMPER_OFF = 0; + + public static final int END_OF_TRACK = 47; + + Sequencer sequencer; + + static final int[] offsets = { // add these amounts to the base value + // A B C D E F G + -4, -2, 0, 1, 3, 5, 7 }; + + public static void main(String[] args) throws InvalidMidiDataException, + MidiUnavailableException, IOException { + + try { + // bag.connectToArduinos(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + new SimpleKeyboard(); + + } + + public Keyboard() { + bag.addButtonListener(this); + try { + System.out.println("Generating Keys"); + genKeys(); + System.out.println("Finished Generating Keys"); + /*System.out.println("Testing Keys"); + for (int i=0; i<5; i++) { + System.out.println("Playing " + i); + playKey(i); + System.out.println("Played " + i); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }*/ + } catch (InvalidMidiDataException | MidiUnavailableException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + new Thread(this).start(); + } + + public void buttonPressed(int x, int y) { + if (noising = true) { + bag.clearLEDs(); + noising = false; + } + lastActionTime = System.currentTimeMillis(); + System.out.println("Button Pressed: " + x + " " + y); + bag.fillRect(0, y, 9, 2, Color.red, 500); + + try { + playKey(y - 10); + } catch (InvalidMidiDataException | MidiUnavailableException + | IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + void genKeys() throws InvalidMidiDataException, MidiUnavailableException { + for (int key = 0; key < 20; key++) { + int instrument = 0; + + // 16 ticks per quarter note. + Sequence sequence = new Sequence(Sequence.PPQ, 16); + + // Add the specified notes to the track + Track track = sequence.createTrack(); // Begin with a new track + + ShortMessage sm = new ShortMessage(); + sm.setMessage(ShortMessage.PROGRAM_CHANGE, 0, instrument, 0); + track.add(new MidiEvent(sm, 0)); + + // These values persist and apply to all notes 'till changed + int notelength = 16; // default to quarter notes + int velocity = 64; // default to middle volume + int basekey = 60; // 60 is middle C. Adjusted up and down by octave + boolean sustain = false; // is the sustain pedal depressed? + int numnotes = 0; // How many notes in current chord? + + int t = 0; // time in ticks for the composition + + /* + * ShortMessage m = new ShortMessage(); + * m.setMessage(ShortMessage.CONTROL_CHANGE, 0, DAMPER_PEDAL, + * sustain ? DAMPER_ON : DAMPER_OFF); track.add(new MidiEvent(m, + * t)); + */ + + ShortMessage on = new ShortMessage(); + on.setMessage(ShortMessage.NOTE_ON, 0, basekey + key, velocity); + ShortMessage off = new ShortMessage(); + off.setMessage(ShortMessage.NOTE_OFF, 0, basekey + key, velocity); + track.add(new MidiEvent(on, t)); + track.add(new MidiEvent(off, t + notelength)); + + notes[key] = sequence; + } + + // Set up the Sequencer and Synthesizer objects + sequencer = MidiSystem.getSequencer(); + sequencer.open(); + Synthesizer synthesizer = MidiSystem.getSynthesizer(); + synthesizer.open(); + sequencer.getTransmitter().setReceiver(synthesizer.getReceiver()); + } + + void playKey(int key) throws InvalidMidiDataException, + MidiUnavailableException, IOException { + int tempo = 120; + // Specify the sequence to play, and the tempo to play it at + sequencer.setSequence(notes[key + 10]); + sequencer.setTempoInBPM(tempo); + + // And start playing now. + if (sequencer.isRunning()) { + System.out.println("Is Running"); + sequencer.stop(); + sequencer.setTickPosition(sequencer.getLoopStartPoint()); + sequencer.start(); + } else { + System.out.println("Not Running"); + sequencer.setTickPosition(sequencer.getLoopStartPoint()); + sequencer.start(); + } + + } + + @Override + public void contact(Contact c) { + // TODO Auto-generated method stub + + } + + /* + * This method parses the specified char[] of notes into a Track. The + * musical notation is the following: A-G: A named note; Add b for flat and + * # for sharp. +: Move up one octave. Persists. -: Move down one octave. + * Persists. /1: Notes are whole notes. Persists 'till changed /2: Half + * notes /4: Quarter notes /n: N can also be, 8, 16, 32, 64. s: Toggle + * sustain pedal on or off (initially off) >: Louder. Persists <: Softer. + * Persists .: Rest. Length depends on current length setting Space: Play + * the previous note or notes; notes not separated by spaces are played at + * the same time + */ + public static void addTrack(Sequence s, int instrument, int tempo, + char[] notes) throws InvalidMidiDataException { + Track track = s.createTrack(); // Begin with a new track + + // Set the instrument on channel 0 + ShortMessage sm = new ShortMessage(); + sm.setMessage(ShortMessage.PROGRAM_CHANGE, 0, instrument, 0); + track.add(new MidiEvent(sm, 0)); + + int n = 0; // current character in notes[] array + int t = 0; // time in ticks for the composition + + // These values persist and apply to all notes 'till changed + int notelength = 16; // default to quarter notes + int velocity = 64; // default to middle volume + int basekey = 60; // 60 is middle C. Adjusted up and down by octave + boolean sustain = false; // is the sustain pedal depressed? + int numnotes = 0; // How many notes in current chord? + + while (n < notes.length) { + char c = notes[n++]; + + if (c == '+') + basekey += 12; // increase octave + else if (c == '-') + basekey -= 12; // decrease octave + else if (c == '>') + velocity += 16; // increase volume; + else if (c == '<') + velocity -= 16; // decrease volume; + else if (c == '/') { + char d = notes[n++]; + if (d == '2') + notelength = 32; // half note + else if (d == '4') + notelength = 16; // quarter note + else if (d == '8') + notelength = 8; // eighth note + else if (d == '3' && notes[n++] == '2') + notelength = 2; + else if (d == '6' && notes[n++] == '4') + notelength = 1; + else if (d == '1') { + if (n < notes.length && notes[n] == '6') + notelength = 4; // 1/16th note + else + notelength = 64; // whole note + } + } else if (c == 's') { + sustain = !sustain; + // Change the sustain setting for channel 0 + ShortMessage m = new ShortMessage(); + m.setMessage(ShortMessage.CONTROL_CHANGE, 0, DAMPER_PEDAL, + sustain ? DAMPER_ON : DAMPER_OFF); + track.add(new MidiEvent(m, t)); + } else if (c >= 'A' && c <= 'G') { + int key = basekey + offsets[c - 'A']; + if (n < notes.length) { + if (notes[n] == 'b') { // flat + key--; + n++; + } else if (notes[n] == '#') { // sharp + key++; + n++; + } + } + + addNote(track, t, notelength, key, velocity); + numnotes++; + } else if (c == ' ') { + // Spaces separate groups of notes played at the same time. + // But we ignore them unless they follow a note or notes. + if (numnotes > 0) { + t += notelength; + numnotes = 0; + } + } else if (c == '.') { + // Rests are like spaces in that they force any previous + // note to be output (since they are never part of chords) + if (numnotes > 0) { + t += notelength; + numnotes = 0; + } + // Now add additional rest time + t += notelength; + } + } + } + + // A convenience method to add a note to the track on channel 0 + public static void addNote(Track track, int startTick, int tickLength, + int key, int velocity) throws InvalidMidiDataException { + ShortMessage on = new ShortMessage(); + on.setMessage(ShortMessage.NOTE_ON, 0, key, velocity); + ShortMessage off = new ShortMessage(); + off.setMessage(ShortMessage.NOTE_OFF, 0, key, velocity); + track.add(new MidiEvent(on, startTick)); + track.add(new MidiEvent(off, startTick + tickLength)); + } + + @Override + public void run() { + while (true) { + System.out.println("Checking last action time"); + if ((System.currentTimeMillis() - lastActionTime) > 20000) { + System.out.println("Activating Noise"); + bag.noise(new Rectangle(0, 0, 9, 20)); + + noising = true; + + } else { + System.out.println("Waiting more"); + } + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + + } + } + + } +} diff --git a/PunchingBag/src/uk/ac/open/punchingbag/examples/SimpleKeyboard.java b/PunchingBag/src/uk/ac/open/punchingbag/examples/SimpleKeyboard.java index 1e791ee..245ed34 100644 --- a/PunchingBag/src/uk/ac/open/punchingbag/examples/SimpleKeyboard.java +++ b/PunchingBag/src/uk/ac/open/punchingbag/examples/SimpleKeyboard.java @@ -128,32 +128,6 @@ public class SimpleKeyboard implements ButtonListener, Runnable { e.printStackTrace(); } - /*char[] notes = { 'C', 'C' }; - - String filename = null; - int instrument = 0; - int tempo = 120; - - // 16 ticks per quarter note. - Sequence sequence = new Sequence(Sequence.PPQ, 16); - - // Add the specified notes to the track - addTrack(sequence, instrument, tempo, notes); - - // Set up the Sequencer and Synthesizer objects - Sequencer sequencer = MidiSystem.getSequencer(); - sequencer.open(); - Synthesizer synthesizer = MidiSystem.getSynthesizer(); - synthesizer.open(); - sequencer.getTransmitter().setReceiver(synthesizer.getReceiver()); - - // Specify the sequence to play, and the tempo to play it at - sequencer.setSequence(sequence); - sequencer.setTempoInBPM(tempo); - - // And start playing now. - sequencer.start();*/ - } @Override @@ -162,117 +136,6 @@ public class SimpleKeyboard implements ButtonListener, Runnable { } - /* - * This method parses the specified char[] of notes into a Track. The - * musical notation is the following: A-G: A named note; Add b for flat and - * # for sharp. +: Move up one octave. Persists. -: Move down one octave. - * Persists. /1: Notes are whole notes. Persists 'till changed /2: Half - * notes /4: Quarter notes /n: N can also be, 8, 16, 32, 64. s: Toggle - * sustain pedal on or off (initially off) >: Louder. Persists <: Softer. - * Persists .: Rest. Length depends on current length setting Space: Play - * the previous note or notes; notes not separated by spaces are played at - * the same time - */ - public static void addTrack(Sequence s, int instrument, int tempo, - char[] notes) throws InvalidMidiDataException { - Track track = s.createTrack(); // Begin with a new track - - // Set the instrument on channel 0 - ShortMessage sm = new ShortMessage(); - sm.setMessage(ShortMessage.PROGRAM_CHANGE, 0, instrument, 0); - track.add(new MidiEvent(sm, 0)); - - int n = 0; // current character in notes[] array - int t = 0; // time in ticks for the composition - - // These values persist and apply to all notes 'till changed - int notelength = 16; // default to quarter notes - int velocity = 64; // default to middle volume - int basekey = 60; // 60 is middle C. Adjusted up and down by octave - boolean sustain = false; // is the sustain pedal depressed? - int numnotes = 0; // How many notes in current chord? - - while (n < notes.length) { - char c = notes[n++]; - - if (c == '+') - basekey += 12; // increase octave - else if (c == '-') - basekey -= 12; // decrease octave - else if (c == '>') - velocity += 16; // increase volume; - else if (c == '<') - velocity -= 16; // decrease volume; - else if (c == '/') { - char d = notes[n++]; - if (d == '2') - notelength = 32; // half note - else if (d == '4') - notelength = 16; // quarter note - else if (d == '8') - notelength = 8; // eighth note - else if (d == '3' && notes[n++] == '2') - notelength = 2; - else if (d == '6' && notes[n++] == '4') - notelength = 1; - else if (d == '1') { - if (n < notes.length && notes[n] == '6') - notelength = 4; // 1/16th note - else - notelength = 64; // whole note - } - } else if (c == 's') { - sustain = !sustain; - // Change the sustain setting for channel 0 - ShortMessage m = new ShortMessage(); - m.setMessage(ShortMessage.CONTROL_CHANGE, 0, DAMPER_PEDAL, - sustain ? DAMPER_ON : DAMPER_OFF); - track.add(new MidiEvent(m, t)); - } else if (c >= 'A' && c <= 'G') { - int key = basekey + offsets[c - 'A']; - if (n < notes.length) { - if (notes[n] == 'b') { // flat - key--; - n++; - } else if (notes[n] == '#') { // sharp - key++; - n++; - } - } - - addNote(track, t, notelength, key, velocity); - numnotes++; - } else if (c == ' ') { - // Spaces separate groups of notes played at the same time. - // But we ignore them unless they follow a note or notes. - if (numnotes > 0) { - t += notelength; - numnotes = 0; - } - } else if (c == '.') { - // Rests are like spaces in that they force any previous - // note to be output (since they are never part of chords) - if (numnotes > 0) { - t += notelength; - numnotes = 0; - } - // Now add additional rest time - t += notelength; - } - } - } - - // A convenience method to add a note to the track on channel 0 - public static void addNote(Track track, int startTick, int tickLength, - int key, int velocity) throws InvalidMidiDataException { - ShortMessage on = new ShortMessage(); - on.setMessage(ShortMessage.NOTE_ON, 0, key, velocity); - ShortMessage off = new ShortMessage(); - off.setMessage(ShortMessage.NOTE_OFF, 0, key, velocity); - track.add(new MidiEvent(on, startTick)); - track.add(new MidiEvent(off, startTick + tickLength)); - } - @Override public void run() { while (true) { -- cgit v1.2.3