/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* JavaWorld Library, Copyright 2011 Bryan Chadwick *
* *
* FILE: ./world/sound/tunes/MusicBox.java *
* *
* This file is part of JavaWorld. *
* *
* JavaWorld is free software: you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation, either version *
* 3 of the License, or (at your option) any later version. *
* *
* JavaWorld is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with JavaWorld. If not, see . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package world.sound.tunes;
import java.util.ArrayList;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Synthesizer;
/** Represents/initializes the MIDI synthesizer and manages the
* channels/instruments in the MIDI program. Based in part on a
* class originally designed by Viera K. Proulx. */
public class MusicBox implements SoundConstants{
/** MIDI synthesizer that plays notes */
private Synthesizer synth;
/** MIDI channels that are currently assigned to the synthesizer */
private MidiChannel[] channels;
/** Is this MusicBox ready to play notes? (initialized correctly) */
private boolean READY = false;
/** The default constructor just initializes the MIDI synthesizer
* and sets the default program for the instruments. */
public MusicBox(){
initMusic();
initChannels();
}
/** Up to 16 instruments (really 24 I think, but not exactly sure) */
//private final static int NUM_CHANNELS = 16;
/** The MIDI synthesizer can also be initialized with a list of instrument
* numbers rather than setting the default program. */
public MusicBox(int ... instruments){
initMusic();
initChannels(instruments);
}
/** Initialize this MusicBox (instruments/program/channels) */
protected void initMusic(){
try{
this.synth = MidiSystem.getSynthesizer();
this.synth.open();
this.synth.loadAllInstruments(this.synth.getDefaultSoundbank());
this.channels = this.synth.getChannels();
if (this.channels != null){
this.initChannels();
this.READY = true;
}
}catch(javax.sound.midi.MidiUnavailableException e){
System.err.println("MidiUnavailableException: " +
e.getMessage());
this.READY = false;
}catch(NullPointerException e){
System.err.println("Midi Initialization Error: " +
e.getMessage());
this.READY = false;
}
}
/** Initialize the program to the default set of instruments defined in
* {@link world.sound.tunes.SoundConstants}. */
public void initChannels(){
this.initChannels(SoundConstants.INSTRUMENTS);
}
/** Initialize the MIDI channels to the given set of instruments. You
* may give up to 16 instrument numbers (as instrument numbers defined in
* {@link world.sound.tunes.SoundConstants}) to assign to the channels. */
public void initChannels(int ... instruments){
for (int i = 0; i < this.channels.length && i < instruments.length; i++){
this.channels[i].programChange(instruments[i]-1);
}
}
/** Produce the instrument currently assigned to the given channel. */
public int getProgram(int channel){
return this.channels[channel].getProgram();
}
/** Play all tunes in the given list of Tune
s */
public void playOn(ArrayList tunes){
for(int i = 0; i < tunes.size(); i++)
this.playTune(tunes.get(i));
}
/** Play the given tune on the channel assigned to it. */
public void playTune(Tune tune){
for(int i = 0; i < tune.chord.notes.size(); i++){
Note n = tune.chord.notes.get(i);
if(!n.isSilent()){
this.channels[tune.channel].noteOn(n.getPitch(), n.getVelocity());
n.nextBeat();
}
}
}
/** Stop playing all tunes in the given list of Tune
s. */
public void playOff(ArrayList tunes){
for(int i = 0; i < tunes.size(); i++)
this.stopTune(tunes.get(i));
}
/** Stop playing the given tune on the channel assigned to it. */
public void stopTune(Tune tune){
for(int i = 0; i < tune.chord.notes.size(); i++){
Note n = tune.chord.notes.get(i);
this.channels[tune.channel].noteOff(n.getPitch(), n.getVelocity());
}
}
/** Has this music box been initialized? */
public boolean isReady(){ return READY; }
}