package jmslexamples.jsyn; import java.util.*; import java.awt.*; import java.awt.event.*; import java.applet.Applet; import com.softsynth.jsyn.*; import com.softsynth.jsyn.view102.*; import com.softsynth.jsyn.util.*; import com.softsynth.jsyn.circuits.*; import com.softsynth.jmsl.*; import com.softsynth.jmsl.util.*; import com.softsynth.jmsl.jsyn.*; // =========================================================================== /** Play various sequences. */ public class SeqGenDemo extends Applet implements ActionListener, ItemListener { BussedVoiceAllocator allocator; SynthNote voice; LineOut unitOut; SynthScope scope; Vector generators; Panel bPanel; Choice genChoice; Button resetButton; Button randomButton; Label seedLabel; SeqDisplay seqDisplay; SeqJob seqJob; SequenceGenerator currentGenerator; /* Can be run as either an application or as an applet. */ public static void main(String args[]) { SeqGenDemo applet = new SeqGenDemo(); AppletFrame frame = new AppletFrame("SeqGenDemo", applet); frame.setSize(600,500); frame.show(); frame.test(); } /* * Setup synthesis. */ public void start() { setLayout( new BorderLayout(0,1) ); Panel topPanel = new Panel(); topPanel.add( genChoice = new Choice() ); topPanel.add( resetButton = new Button("Reset") ); topPanel.add( randomButton = new Button("Randomize") ); topPanel.add( seedLabel = new Label() ); add( topPanel, "North" ); generators = new Vector(); // Setup Random Sequence Generator genChoice.add("Random"); RandomSequence randSeq = new RandomSequence(); currentGenerator = randSeq; randSeq.setMinimum( 0 ); randSeq.setMaximum( 60 ); randSeq.setSeed( 12345 ); updateSeedLabel(); generators.addElement( randSeq ); // Setup Random Sequence Generator genChoice.add("RandomWalk"); RandomWalkSequence walkSeq = new RandomWalkSequence(); walkSeq.setMinimum( 0 ); walkSeq.setMaximum( 60 ); walkSeq.setMaximumStep( 3 ); walkSeq.setSeed( 987 ); generators.addElement( walkSeq ); // Setup HailStone Sequence Generator genChoice.add("HailStone"); HailstoneSequence hailSeq = new HailstoneSequence(); hailSeq.setOffset( 0 ); hailSeq.setSeed( 21 ); generators.addElement( hailSeq ); bPanel = new Panel(); bPanel.setLayout( new GridLayout(0,1) ); add( bPanel, "Center" ); seqDisplay = new SeqDisplay( 10, 20 ); bPanel.add( seqDisplay ); genChoice.addItemListener(this); resetButton.addActionListener(this); randomButton.addActionListener(this); try { /* Start synthesis engine. */ Synth.startEngine( 0 ); /* Make clock for JMSL. */ JMSL.clock = new SynthClock(); JMSL.clock.setAdvance( 0.5 ); // Create a voice allocator and connect it to a LineOut. voice = new RingModBell(); unitOut = new LineOut( ); voice.output.connect( 0, unitOut.input, 0 ); voice.output.connect( 0, unitOut.input, 1 ); // Show signal on a scope. scope = new SynthScope(); scope.createProbe( voice.output, "Voice out", Color.yellow ); // Create a MusicJob seqJob = new SeqJob(); seqJob.setDuration( 0.2 ); seqJob.setRepeats( Integer.MAX_VALUE ); // play forever seqJob.launch(JMSL.now()); } catch (SynthException e) { SynthAlert.showError(this,e); } bPanel.add( scope ); /* Synchronize Java display. */ getParent().validate(); getToolkit().sync(); System.out.println("Exiting start() --------------------------------"); } public void stop() { System.out.println("STOPPING --------------------------------"); seqJob.finish(); removeAll(); try { Synth.stopEngine(); } catch (SynthException e) { SynthAlert.showError(this,e); } } void updateSeedLabel() { seedLabel.setText( "Seed = " + currentGenerator.getSeed() ); } public void itemStateChanged(ItemEvent evt) { Object source = evt.getSource(); if( source == genChoice ) { int index = genChoice.getSelectedIndex(); currentGenerator = (SequenceGenerator) generators.elementAt( index ); } } public void actionPerformed(ActionEvent evt) { Object source = evt.getSource(); if( source == resetButton ) { currentGenerator.reset(); updateSeedLabel(); } else if( source == randomButton ) { currentGenerator.randomize(); updateSeedLabel(); } } int getNextIndex() { int index = currentGenerator.next(); seqDisplay.showCurrent( index ); return index; } // =========================================================================== public class SeqJob extends MusicJob { public double start( double playTime ) throws InterruptedException { int itime = (int) JMSL.clock.timeToNative( playTime ); try { voice.start(itime); unitOut.start(itime); } catch (SynthException e) { System.err.println(e); } return playTime; } public double repeat( double playTime ) throws InterruptedException { int itime = (int) JMSL.clock.timeToNative( playTime ); try { int pitch = getNextIndex() + 30; double frequency = EqualTemperedTuning.getMIDIFrequency( pitch ); voice.noteOn( itime, frequency, 0.5 ); playTime += getDuration(); } catch (SynthException e) { SynthAlert.showError(null,e); } return playTime; } public double stop( double playTime ) throws InterruptedException { try { unitOut.stop(); voice.stop(); } catch (SynthException e) { System.err.println(e); } return playTime; } } // =========================================================================== /** Show the index in the sequence. */ class SeqDisplay extends Canvas implements MouseListener { int numRows; int numColumns; int previous = -1; int dx; int dy; public SeqDisplay( int numRows, int numColumns ) { this.numRows = numRows; this.numColumns = numColumns; addMouseListener(this); } public void showCurrent( int current ) { Graphics g = getGraphics(); if( g == null ) return; drawCurrent( g, previous ); drawCurrent( g, current ); previous = current; } void drawCurrent( Graphics g, int current ) { int x,y; // highlight current if( current > 0 ) { g.setXORMode( Color.orange ); x = (current%numColumns) * dx; y = (current/numColumns) * dy; g.setColor( Color.green ); g.fillRect( x, y, dx, dy ); g.setPaintMode(); } } public void paint(Graphics g) { int x,y; int w = getBounds().width; int h = getBounds().height; dx = w/numColumns; dy = h/numRows; // draw grid g.setColor( Color.black ); for( int i=0; i<(numRows+1); i++ ) { y = i*dy; g.drawLine( 0, y, numColumns*dx, y ); } for( int i=0; i<(numColumns+1); i++ ) { x = i*dx; g.drawLine( x, 0, x, numRows*dy ); } // setup highlighting drawCurrent( g, previous ); // Draw numbers in grid. g.setColor( Color.red ); for( int iy=0; iy