import jm.music.data.*; import jm.JMC; import jm.util.*; import jm.music.tools.*; /** * Class that represents elements of the song * amazing grace * @author Mark Guzdial * @author Barb Ericson */ public class AmazingGraceSongElement { /** the next element */ private AmazingGraceSongElement next; /** my part in the song */ private Part myPart; /** * When we make a new element, the next part is * empty, and ours is a blank new part */ public AmazingGraceSongElement() { this.next = null; this.myPart = new Part(); } /** * addPhrase1 puts the first part of AmazingGrace * into our part of the song at the desired start * time with the given instrument * @param startTime the time to start playing this element * @param instrument the instrument to use */ public void addPhrase1(double startTime, int instrument) { double[] phrase1Data = { JMC.G4, JMC.QN, JMC.C5, JMC.HN, JMC.E5,JMC.EN, JMC.C5,JMC.EN, JMC.E5,JMC.HN,JMC.D5,JMC.QN, JMC.C5,JMC.HN,JMC.A4,JMC.QN, JMC.G4,JMC.HN,JMC.G4,JMC.EN,JMC.A4,JMC.EN, JMC.C5,JMC.HN,JMC.E5,JMC.EN,JMC.C5,JMC.EN, JMC.E5,JMC.HN,JMC.D5,JMC.EN,JMC.E5,JMC.EN, JMC.G5,JMC.DHN }; Phrase myPhrase = new Phrase(startTime); myPhrase.addNoteList(phrase1Data); this.myPart.addPhrase(myPhrase); // In MVAmazingGraceSong, we did this when we initialized // the part. But we CAN do it later this.myPart.setInstrument(instrument); } /** * Add the second phrase * @param startTime the time to start * @param instrument the instrument to use */ public void addPhrase2(double startTime, int instrument) { double[] phrase2Data = { JMC.G5,JMC.HN,JMC.E5,JMC.EN,JMC.G5,JMC.EN, JMC.G5,JMC.HN,JMC.E5,JMC.EN,JMC.C5,JMC.EN, JMC.E5,JMC.HN,JMC.D5,JMC.QN, JMC.C5,JMC.HN,JMC.A4,JMC.QN, JMC.G4,JMC.HN,JMC.G4,JMC.EN,JMC.A4,JMC.EN, JMC.C5,JMC.HN,JMC.E5,JMC.EN,JMC.C5,JMC.EN, JMC.E5,JMC.HN,JMC.D5,JMC.QN, JMC.C5,JMC.DHN }; Phrase myPhrase = new Phrase(startTime); myPhrase.addNoteList(phrase2Data); this.myPart.addPhrase(myPhrase); this.myPart.setInstrument(instrument); } /** * Set the next element * @param nextOne the one to use as the next */ public void setNext(AmazingGraceSongElement nextOne) { this.next = nextOne; } /** * Method to get the next element * @return the next element */ public AmazingGraceSongElement getNext() { return this.next; } /** We could just access myPart directly * but we can CONTROL access by using a method * We'll use it in showFromMeOn * @return the part for this element */ public Part getPart() { return this.myPart; } /** We could just access myPart directly * but we can CONTROL access by using a method * We'll use it in showFromMeOn * @return the part for this element */ public Part part() { return this.myPart; } /** * Why do we need this? If we want one piece to * start after another, we need to know when the * last one ends. Notice: It's the phrase that knows the end time. * We have to ask the part for its phrase (assuming only one) * to get the end time. * @return the end time of this element */ public double getEndTime() { return this.myPart.getPhrase(0).getEndTime(); } /** We need setChannel because each part has to be in its * own channel if it has different start times. So, * we'll set the channel when we assemble the score. * (But if we only need it for showFromMeOn, we could * make it PRIVATE...) * @param channel the channel to use */ public void setChannel(int channel) { myPart.setChannel(channel); } /** * Method to show from this element on */ public void showFromMeOn() { // Make the score that we'll assemble the elements into Score myScore = new Score("Amazing Grace"); myScore.setTimeSignature(3,4); // Each element will be in its own channel int channelCount = 1; // Start from this element (this) AmazingGraceSongElement current = this; // While we're not through... while (current != null) { // Set the channel, increment the channel, then add it in. current.setChannel(channelCount); channelCount = channelCount + 1; myScore.addPart(current.part()); /* Now, move on to the next element * which we already know isn't null */ current = current.getNext(); } // At the end, let's see it! View.notate(myScore); } }