/** * ShapeToot03.java * * Fill a MusicShape with random numbers, view it in a MusicShapeEditor. * * @author Phil Burk and Nick Didkovsky */ /* * (C) 1997..2001 Nick Didkovsky and Phil Burk, All Rights Reserved JMSL is * based upon HMSL (C) Phil Burk, Larry Polansky and David Rosenboom. */ package jmsltutorial; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.MalformedURLException; import java.net.URL; import com.softsynth.jmsl.*; import com.softsynth.jmsl.midi.MidiIO_JavaSound; import com.softsynth.jmsl.util.HarmonicComplexity; import com.softsynth.jmsl.view.MusicShapeEditor; public class ShapeToot03 extends java.applet.Applet implements ActionListener { MusicShape myMusicShape; TextArea myTextArea; MusicShapeEditor myShapeEditor; Button launchButton; Button finishButton; public void init() { JMSL.setIsApplet(true); } /* Build data when the applet starts, and send JMSL's STDOut to a TextArea */ public void start() { buildCleanClock(); buildCleanScheduler(); setupJavaSoundMidi(); defineMyMusicShape(); buildMyMusicShape(); buildAndSetInstrument(); myShapeEditor = new MusicShapeEditor(); myShapeEditor.addMusicShape(myMusicShape); buildGUI(); } private void setupJavaSoundMidi() { JMSL.midi = MidiIO_JavaSound.instance(); try { ((MidiIO_JavaSound) JMSL.midi).setSoundbankURL(new URL(getCodeBase(), "javasound/soundbank-min.gm")); } catch (MalformedURLException e) { e.printStackTrace(); } // JMSL.midi.edit(new Frame()); JMSL.midi.open(); } /** * */ private void buildGUI() { setLayout(new BorderLayout()); // initialize the TextArea with 15 rows, 50 columns myTextArea = new TextArea(10, 80); // Add the TextArea to the applet's layout add(BorderLayout.SOUTH, myTextArea); // Hand this TextArea to a new TextAreaSTDOut, and use it for JMSL.out JMSL.setSTDOut(new TextAreaSTDOut(myTextArea)); add(BorderLayout.NORTH, myShapeEditor.getComponent()); Panel p = new Panel(); p.setLayout(new FlowLayout(FlowLayout.CENTER)); p.add(launchButton = new Button("LAUNCH")); p.add(finishButton = new Button("FINISH")); launchButton.addActionListener(this); finishButton.addActionListener(this); finishButton.setEnabled(false); add(p); } private void buildCleanClock() { JMSL.clock = new DefaultMusicClock(); JMSL.clock.setAdvance(0.1); } /** * Create a new EventScheduler each time this applet starts, so old threads don't hang around */ private void buildCleanScheduler() { JMSL.scheduler = new EventScheduler(); JMSL.scheduler.start(); } /** * allocate a new MusicShape and define the meaning of each of its dimensions */ private void defineMyMusicShape() { myMusicShape = new MusicShape(5); myMusicShape.setRepeats(Integer.MAX_VALUE); // play forever myMusicShape.setDimensionName(0, "Duration"); myMusicShape.setLimits(0, 0.0, 4.0); // dim, low, high myMusicShape.setDefault(0, 1.0); // default 1 myMusicShape.setDimensionName(1, "Chord Root"); myMusicShape.setLimits(1, 20.0, 80.0); myMusicShape.setDefault(1, 60.0); myMusicShape.setDimensionName(2, "Number of Intervals"); myMusicShape.setLimits(2, 0.0, 8.0); myMusicShape.setDefault(2, 1.0); myMusicShape.setDimensionName(3, "Harmonic Complexity"); myMusicShape.setLimits(3, 0.0, 11.0); myMusicShape.setDefault(3, 1.0); myMusicShape.setDimensionName(4, "Time Window"); myMusicShape.setLimits(4, 0.0, 1.0); myMusicShape.setDefault(4, 0.0); } /** * fill MusicShape with data */ private void buildMyMusicShape() { for (int i = 0; i < 20; i++) { // choose a duration between 0.25 and 3.0 seconds double duration = JMSLRandom.choose(0.25, 3.0); // choose a chord root between Midi pitch 40 and 64 double root = (double) JMSLRandom.choose(40, 64); // choose a number of intervals in chord double intervals = (double) JMSLRandom.choose(1, 6); // choose a harmonic complexity value 0..11 double harmonicComplexity = JMSLRandom.choose(12); // choose a time window value 0..1 double timeWindow = JMSLRandom.choose(0.25); myMusicShape.add(duration, root, intervals, harmonicComplexity, timeWindow); } } /** * define an instrument that interprets myMusicShape's data appropriately and set myMusicShape * to use it. */ private void buildAndSetInstrument() { Instrument chordMakingInstrument = new InstrumentAdapter() { public double play(double playTime, double timeStretch, double[] data) { double duration = data[0]; int root = (int) data[1]; int intervals = (int) data[2]; int harmonicComplexity = (int) data[3]; double timeWindow = data[4]; double offtime = playTime + JMSLRandom.choose(0.5, 1.5) * duration; JMSL.midi.noteOn(playTime, 1, root, JMSLRandom.choose(20, 80)); JMSL.midi.noteOff(offtime, 1, root, 0); String msg = "New chord playing at " + playTime + ", root = " + root; if (intervals > 0) { msg += ", intervals: "; } for (int i = 0; i < intervals; i++) { int newInterval = root + HarmonicComplexity.gimmeRandomHarmonicComplexity(harmonicComplexity); newInterval += 12 * JMSLRandom.choose(3); // transpose 8va's double timeStampOfInterval = playTime + JMSLRandom.choose(timeWindow); offtime = timeStampOfInterval + JMSLRandom.choose(0.5, 1.5) * duration; JMSL.midi.noteOn(timeStampOfInterval, 1, newInterval, JMSLRandom.choose(20, 80)); JMSL.midi.noteOff(offtime, 1, newInterval, 0); msg += newInterval + " "; } JMSL.out.println(msg); return playTime + duration * timeStretch; } }; myMusicShape.setInstrument(chordMakingInstrument); } public void stop() { removeAll(); myMusicShape.finish(); JMSL.closeMusicDevices(); } public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == launchButton) { myMusicShape.launch(JMSL.now()); launchButton.setEnabled(false); finishButton.setEnabled(true); } if (source == finishButton) { myMusicShape.finish(); launchButton.setEnabled(true); finishButton.setEnabled(false); } } }