/* * Created on Apr 26, 2004 * */ package jmsltestsuite; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import com.didkovsky.portview.PVButton; import com.didkovsky.portview.PVPanel; import com.softsynth.jmsl.*; import com.softsynth.jmsl.jsyn.JSynInsFromClassName; import com.softsynth.jmsl.jsyn.JSynMusicDevice; import com.softsynth.jmsl.util.EventDistributions; import com.softsynth.jmsl.util.Oof; import com.softsynth.jmsl.view.MusicShapeEditor; import com.softsynth.jmsl.view.PVPanelAdapter; import com.softsynth.jsyn.AppletFrame; /** * JMSLJSynApplet.java * * Generate and play a MusicShape Use a JSyn SynthNote wrapped in a polyphonic * JMSL Instrument Every repeat, the MusicShape scrambles a random subrange of * data Calls MusicShapeEditor.refresh() to update display after data changes * * * @author Nick Didkovsky, didkovn@mail.rockefeller.edu (C) 2003 Nick Didkovsky * * JSyn (C) Phil Burk, visit www.softsynth.com JMSL (c) Nick Didkovsky and Phil * Burk, visit www.algomusic.com * */ public class JMSLJSynApplet extends java.applet.Applet implements ActionListener { MusicShape myMusicShape; JMSLMixerContainer mixer; MusicShapeEditor musicShapeEditor; PVButton startButton; PVButton stopButton; public void init() { JMSLRandom.randomize(); } /** * Stuff a MusicShape with 16 algorithmically generated musical events. * Duration is Myhill distributed. Pitch is 1/F Amplitude is uniformly * random 0 .. 0.25 Hold time is in randomly chosen range 0.5 .. 2.0 times * duration * */ void buildMusicShape() { myMusicShape.removeAll(); Oof oof = new Oof(7); oof.randomize(); for (int i = 0; i < 16; i++) { double dur = EventDistributions.genEntryDelayMyhill(4.0, 20.0); double pitch = 60 + (oof.next() / 2); double amp = JMSLRandom.choose(0.25); double hold = dur * JMSLRandom.choose(0.5, 2.0); myMusicShape.add(dur, pitch, amp, hold); } myMusicShape.print(); musicShapeEditor.refresh(); // add a Playable that scrambles some data every time this MusicShape // repeats myMusicShape.addRepeatPlayable(new MusicShapeScrambler(musicShapeEditor)); } public void start() { JMSL.setIsApplet(true); JMSL.clock.setAdvance(0.1); JSynMusicDevice dev = JSynMusicDevice.instance(); dev.open(); mixer = new JMSLMixerContainer(); mixer.start(); JSynInsFromClassName ins = new JSynInsFromClassName(8, com.softsynth.jsyn.circuits.FilteredSawtoothBL.class.getName()); mixer.addInstrument(ins); myMusicShape = new MusicShape(4); myMusicShape.useStandardDimensionNameSpace(); myMusicShape.setInstrument(ins); myMusicShape.setRepeats(1000); buildGUI(); getParent().validate(); getToolkit().sync(); } private void buildGUI() { setLayout(new BorderLayout()); musicShapeEditor = new MusicShapeEditor(); musicShapeEditor.addMusicShape(myMusicShape); add(BorderLayout.NORTH, musicShapeEditor.getComponent()); add(BorderLayout.CENTER, mixer.getPanAmpControlPanel()); PVPanel buttonPanel = new PVPanelAdapter(); buttonPanel.setLayout(new FlowLayout()); buttonPanel.add((startButton = JMSL.getViewFactory().createButton("Click to start")).getComponent()); buttonPanel.add((stopButton = JMSL.getViewFactory().createButton("Click to stop")).getComponent()); add(BorderLayout.SOUTH, buttonPanel.getComponent()); startButton.addActionListener(this); stopButton.addActionListener(this); stopButton.setEnabled(false); } public void stop() { removeAll(); myMusicShape.finishAll(); try { myMusicShape.waitForDone(); } catch (InterruptedException e) { e.printStackTrace(); } mixer.stop(); JMSL.closeMusicDevices(); } public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == startButton) { buildMusicShape(); myMusicShape.launch(JMSL.now()); startButton.setEnabled(false); stopButton.setEnabled(true); } if (source == stopButton) { myMusicShape.finishAll(); try { myMusicShape.waitForDone(); } catch (InterruptedException ex) { ex.printStackTrace(); } startButton.setEnabled(true); stopButton.setEnabled(false); } } /* Can be run as either an application or as an applet. */ public static void main(String args[]) { JMSLJSynApplet applet = new JMSLJSynApplet(); JMSL.setIsApplet(false); AppletFrame frame = new AppletFrame("JMSL & JSyn in an applet", applet); frame.setSize(800, 500); frame.show(); frame.test(); } } /** * This class implements Playable and can be added to a MusicShape's * RepeatPlayables. It scrambles a randomly chosen subset of data every time the * MusicShape repeats * * @author Nick Didkovsky, email: didkovn@mail.rockefeller.edu, (c) 2004 Nick * Didkovsky, all rights reserved. * */ class MusicShapeScrambler implements Playable { MusicShapeEditor editor; /** * Pass in the MusicShapeEditor just so we can call refresh() on it after * scarmalbing. Pass in null if you don't care * */ MusicShapeScrambler(MusicShapeEditor editor) { this.editor = editor; } public double play(double playTime, Composable parent) { MusicShape s = (MusicShape) parent; int randomIndex1 = JMSLRandom.choose(s.size()); int randomIndex2 = JMSLRandom.choose(s.size()); // sort them so start less than end int startIndex = Math.min(randomIndex1, randomIndex2); int endIndex = Math.max(randomIndex1, randomIndex2); System.out.println("Scrambling from " + startIndex + " to " + endIndex); // scramble some subrange of durations s.scramble(startIndex, endIndex, 0); // scramble some subrange of pitches s.scramble(startIndex, endIndex, 1); if (editor != null) { editor.refresh(); } return playTime; } }