patternjavaMinor
Playing MIDI instruments in Java
Viewed 0 times
playingmidiinstrumentsjava
Problem
This program offers 8 notes C, D, ..., A, B, C on keyboard keys 1, 2, ..., 8. Also, by typing Left or Right, you can cycle over MIDI instruments.
KeyboardPiano.java:
```
package net.coderodde.music;
import java.awt.Canvas;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.sound.midi.Instrument;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Soundbank;
import javax.sound.midi.Synthesizer;
import javax.swing.JFrame;
public class KeyboardPiano {
private static final String APP_TITLE = "Keyboard Piano";
private final JFrame frame = new JFrame(APP_TITLE);
private final Canvas canvas = new Canvas();
private Synthesizer synthesizer;
private final MidiChannel[] midiChannels;
private final Instrument[] instruments;
private int instrumentIndex = 0;
KeyboardPiano() {
try {
synthesizer = MidiSystem.getSynthesizer();
synthesizer.open();
} catch (MidiUnavailableException ex) {
ex.printStackTrace();
System.exit(1);
}
this.midiChannels = synthesizer.getChannels();
Soundbank bank = synthesizer.getDefaultSoundbank();
synthesizer.loadAllInstruments(bank);
this.instruments = synthesizer.getAvailableInstruments();
synthesizer.loadAllInstruments(synthesizer.getDefaultSoundbank());
synthesizer.getChannels()[0].programChange(instrumentIndex);
System.out.println("[STATE] MIDI channels: " + midiChannels.length);
System.out.println("[STATE] Instruments: " + instruments.length);
}
private void init() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(canvas);
frame.setSize(100, 100);
frame.setResizable(false);
canvas.addKeyListener(new KeyboardPianoListener());
canvas.setFocusable(true);
KeyboardPiano.java:
```
package net.coderodde.music;
import java.awt.Canvas;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.sound.midi.Instrument;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Soundbank;
import javax.sound.midi.Synthesizer;
import javax.swing.JFrame;
public class KeyboardPiano {
private static final String APP_TITLE = "Keyboard Piano";
private final JFrame frame = new JFrame(APP_TITLE);
private final Canvas canvas = new Canvas();
private Synthesizer synthesizer;
private final MidiChannel[] midiChannels;
private final Instrument[] instruments;
private int instrumentIndex = 0;
KeyboardPiano() {
try {
synthesizer = MidiSystem.getSynthesizer();
synthesizer.open();
} catch (MidiUnavailableException ex) {
ex.printStackTrace();
System.exit(1);
}
this.midiChannels = synthesizer.getChannels();
Soundbank bank = synthesizer.getDefaultSoundbank();
synthesizer.loadAllInstruments(bank);
this.instruments = synthesizer.getAvailableInstruments();
synthesizer.loadAllInstruments(synthesizer.getDefaultSoundbank());
synthesizer.getChannels()[0].programChange(instrumentIndex);
System.out.println("[STATE] MIDI channels: " + midiChannels.length);
System.out.println("[STATE] Instruments: " + instruments.length);
}
private void init() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(canvas);
frame.setSize(100, 100);
frame.setResizable(false);
canvas.addKeyListener(new KeyboardPianoListener());
canvas.setFocusable(true);
Solution
Repetition, specially when it occurs with switch cases is both bad for you and for your code. The
And then use this same map
The switch statment in
With everything put togheter the
switch (keyCode) is present two times in your code and all it does (almost) is just to map an integer. And I bolded map because that if that is what you want to do then we can use the HashMap to specify the note number that a key matches to.private HashMap mapNotes = new HashMap();
KeyboardPiano() {
try {
synthesizer = MidiSystem.getSynthesizer();
synthesizer.open();
} catch (MidiUnavailableException ex) {
ex.printStackTrace();
System.exit(1);
}
mapNotes.put(KeyEvent.VK_1, 60);
mapNotes.put(KeyEvent.VK_2, 62);
mapNotes.put(KeyEvent.VK_3, 64);
mapNotes.put(KeyEvent.VK_4, 65);
mapNotes.put(KeyEvent.VK_5, 67);
mapNotes.put(KeyEvent.VK_6, 69);
mapNotes.put(KeyEvent.VK_7, 71);
mapNotes.put(KeyEvent.VK_8, 72);
//...
}And then use this same map
public void keyPressed(KeyEvent e) {
int keyCode = e.getExtendedKeyCode();
int noteNumber = -1;
if(mapNotes.containsKey(keyCode)){
noteNumber = mapNotes.get(keyCode);
}
//...
}The switch statment in
keyPressed can also be simplified because there is common code. The following code is executed in both left and right key press.synthesizer.getChannels()[0].programChange(instrumentIndex);
System.out.println("Switched to " +
instruments[instrumentIndex].getName());With everything put togheter the
keyPressedbecomes the following:public void keyPressed(KeyEvent e) {
int keyCode = e.getExtendedKeyCode();
int noteNumber = -1;
if(mapNotes.containsKey(keyCode)){
noteNumber = mapNotes.get(keyCode);
}else{
switch (keyCode) {
case KeyEvent.VK_LEFT: {
if (instrumentIndex == 0) {
instrumentIndex = instruments.length - 1;
} else {
instrumentIndex--;
}
break;
}
case KeyEvent.VK_RIGHT: {
if (instrumentIndex == instruments.length - 1) {
instrumentIndex = 0;
} else {
instrumentIndex++;
}
break;
}
}
synthesizer.getChannels()[0].programChange(instrumentIndex);
System.out.println("Switched to " +
instruments[instrumentIndex].getName());
}
if (noteNumber != -1) {
midiChannels[0].noteOn(noteNumber, 600);
}
}Code Snippets
private HashMap<Integer, Integer> mapNotes = new HashMap<Integer, Integer>();
KeyboardPiano() {
try {
synthesizer = MidiSystem.getSynthesizer();
synthesizer.open();
} catch (MidiUnavailableException ex) {
ex.printStackTrace();
System.exit(1);
}
mapNotes.put(KeyEvent.VK_1, 60);
mapNotes.put(KeyEvent.VK_2, 62);
mapNotes.put(KeyEvent.VK_3, 64);
mapNotes.put(KeyEvent.VK_4, 65);
mapNotes.put(KeyEvent.VK_5, 67);
mapNotes.put(KeyEvent.VK_6, 69);
mapNotes.put(KeyEvent.VK_7, 71);
mapNotes.put(KeyEvent.VK_8, 72);
//...
}public void keyPressed(KeyEvent e) {
int keyCode = e.getExtendedKeyCode();
int noteNumber = -1;
if(mapNotes.containsKey(keyCode)){
noteNumber = mapNotes.get(keyCode);
}
//...
}synthesizer.getChannels()[0].programChange(instrumentIndex);
System.out.println("Switched to " +
instruments[instrumentIndex].getName());public void keyPressed(KeyEvent e) {
int keyCode = e.getExtendedKeyCode();
int noteNumber = -1;
if(mapNotes.containsKey(keyCode)){
noteNumber = mapNotes.get(keyCode);
}else{
switch (keyCode) {
case KeyEvent.VK_LEFT: {
if (instrumentIndex == 0) {
instrumentIndex = instruments.length - 1;
} else {
instrumentIndex--;
}
break;
}
case KeyEvent.VK_RIGHT: {
if (instrumentIndex == instruments.length - 1) {
instrumentIndex = 0;
} else {
instrumentIndex++;
}
break;
}
}
synthesizer.getChannels()[0].programChange(instrumentIndex);
System.out.println("Switched to " +
instruments[instrumentIndex].getName());
}
if (noteNumber != -1) {
midiChannels[0].noteOn(noteNumber, 600);
}
}Context
StackExchange Code Review Q#115559, answer score: 6
Revisions (0)
No revisions yet.