[jmsl] Navigating Sequential Sequence

jmsl at music.columbia.edu jmsl at music.columbia.edu
Tue Apr 28 08:30:02 EDT 2009


Thanks. It's making some progress!
I needed it to stop when it reaches end instead of going back to 0, so I 
made a repeatPlayable to keep checking if currentPosition is same as 
original position and finishAll() when they are the same.
I'm stil having problem with moving during playback. It works in a slow 
moving, but it doesn't work if I press previous like 2 or 3 times.
Here is my new code.
Thanks,

Chi

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import com.didkovsky.portview.swing.ViewFactorySwing;
import com.softsynth.jmsl.Behavior;
import com.softsynth.jmsl.Composable;
import com.softsynth.jmsl.EventScheduler;
import com.softsynth.jmsl.JMSL;
import com.softsynth.jmsl.JMSLMixerContainer;
import com.softsynth.jmsl.JMSLRandom;
import com.softsynth.jmsl.MusicShape;
import com.softsynth.jmsl.Playable;
import com.softsynth.jmsl.SequentialCollection;
import com.softsynth.jmsl.midi.MidiIO_JavaSound;
import com.softsynth.jmsl.midi.MidiInstrument;

public class SequenceTest extends JApplet {

private JMSLMixerContainer mixer;
private MidiInstrument ins;
private MusicShape ms;
private SequentialCollection sequenceCol;
private JCheckBoxMenuItem sequencePlayCB;
private JMenuItem moveMi, nextMi, prevMi, addMi, insertMi, removeMi, 
midiOutMi;
private JButton position;
private JLabel program;
private int currentSequence;

private String[] programNames = {
"1 Acoustic Grand Piano",
"2 Bright Acoustic Piano", "3 Electric Grand Piano",
"4 Honky-tonk Piano", "5 Electric Piano 1", "6 Electric Piano 2",
"7 Harpsichord", "8 Clavinet", "9 Celesta", "10 Glockenspiel",
"11 Music Box", "12 Vibraphone", "13 Marimba", "14 Xylophone",
"15 Tubular Bells", "16 Dulcimer", "17 Drawbar Organ",
"18 Percussive Organ", "19 Rock Organ", "20 Church Organ",
"21 Reed Organ", "22 Accordion", "23 Harmonica",
"24 Tango Accordion", "25 Acoustic Guitar (nylon)",
"26 Acoustic Guitar (steel)", "27 Electric Guitar (jazz)",
"28 Electric Guitar (clean)", "29 Electric Guitar (muted)",
"30 Overdriven Guitar", "31 Distortion Guitar",
"32 Guitar harmonics", "33 Acoustic Bass",
"34 Electric Bass (finger)", "35 Electric Bass (pick)",
"36 Fretless Bass", "37 Slap Bass 1", "38 Slap Bass 2",
"39 Synth Bass 1", "40 Synth Bass 2", "41 Violin", "42 Viola",
"43 Cello", "44 Contrabass", "45 Tremolo Strings",
"46 Pizzicato Strings", "47 Orchestral Harp", "48 Timpani",
"49 String Ensemble 1", "50 String Ensemble 2",
"51 Synth Strings 1", "52 Synth Strings 2", "53 Choir Aahs",
"54 Voice Oohs", "55 Synth Voice", "56 Orchestra Hit",
"57 Trumpet", "58 Trombone", "59 Tuba", "60 Muted Trumpet",
"61 French Horn", "62 Brass Section", "63 Synth Brass 1",
"64 Synth Brass 2", "65 Soprano Sax", "66 Alto Sax",
"67 Tenor Sax", "68 Baritone Sax", "69 Oboe", "70 English Horn",
"71 Bassoon", "72 Clarinet", "73 Piccolo", "74 Flute",
"75 Recorder", "76 Pan Flute", "77 Blown Bottle", "78 Shakuhachi",
"79 Whistle", "80 Ocarina", "81 Lead 1 (square)",
"82 Lead 2 (sawtooth)", "83 Lead 3 (calliope)",
"84 Lead 4 (chiff)", "85 Lead 5 (charang)", "86 Lead 6 (voice)",
"87 Lead 7 (fifths)", "88 Lead 8 (bass + lead)",
"89 Pad 1 (new age)", "90 Pad 2 (warm)", "91 Pad 3 (polysynth)",
"92 Pad 4 (choir)", "93 Pad 5 (bowed)", "94 Pad 6 (metallic)",
"95 Pad 7 (halo)", "96 Pad 8 (sweep)", "97 FX 1 (rain)",
"98 FX 2 (soundtrack)", "99 FX 3 (crystal)",
"100 FX 4 (atmosphere)", "101 FX 5 (brightness)",
"102 FX 6 (goblins)", "103 FX 7 (echoes)", "104 FX 8 (sci-fi)",
"105 Sitar", "106 Banjo", "107 Shamisen", "108 Koto",
"109 Kalimba", "110 Bag pipe", "111 Fiddle", "112 Shanai",
"113 Tinkle Bell", "114 Agogo", "115 Steel Drums", "116 Woodblock",
"117 Taiko Drum", "118 Melodic Tom", "119 Synth Drum",
"120 Reverse Cymbal", "121 Guitar Fret Noise", "122 Breath Noise",
"123 Seashore", "124 Bird Tweet", "125 Telephone Ring",
"126 Helicopter", "127 Applause", "128 Gunshot"
};

public SequenceTest() {
super();
start();
}

public void start() {
synchronized (JMSL.class) {
initJMSL();
initMixer();
initInstrument();
buildCollection();
initMusicShape();
buildGUI();
}
}

public void stop() {
synchronized (JMSL.class) {
removeAll();
sequenceCol.finishAll();
try {
sequenceCol.waitForDone();
} catch (InterruptedException e) {
e.printStackTrace();
}
mixer.stop();
JMSL.scheduler.stop();
JMSL.closeMusicDevices();
}
}

private void initJMSL() {
JMSL.setViewFactory(new ViewFactorySwing());
JMSL.scheduler = new EventScheduler();
JMSL.scheduler.start();
JMSL.clock.setAdvance(0.1);
JMSLRandom.randomize();
JMSL.midi = MidiIO_JavaSound.instance();
JMSL.midi.open();
}

private void initMixer() {
mixer = new JMSLMixerContainer();
mixer.start();
}

private void initInstrument() {
ins = new MidiInstrument(1, 0);
ins.setProgram(10);
mixer.addInstrument(ins);
mixer.panAmpChange(0, 0.5, 1.0);
}

private void buildCollection() {
sequenceCol = new SequentialCollection();
sequenceCol.setRepeats(Integer.MAX_VALUE);
sequenceCol.addRepeatPlayable(new SequenceRepeatPlayable());
sequenceCol.addStopPlayable(new SequenceStopPlayable());
}

private void initMusicShape() {
ms = new MusicShape(ins.getDimensionNameSpace());
ms.useStandardDimensionNameSpace();
ms.setInstrument(ins);
sequenceCol.add(generate());
}

private void buildGUI() {
setName("Random");
setSize(640, 480);
setLayout(new BorderLayout());

JMenuBar mb = new JMenuBar();
setJMenuBar(mb);
JMenu m;
JButton bt;
mb.add(m = new JMenu("Action"));
m.setMnemonic(KeyEvent.VK_A);

m.add(sequencePlayCB = new JCheckBoxMenuItem("Play"));
sequencePlayCB.setMnemonic(KeyEvent.VK_P);
sequencePlayCB.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, 0));
sequencePlayCB.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (sequencePlayCB.getState()) {
playSequence();
} else {
stopSequence();
}
}
});

m.add(moveMi = new JMenuItem("Go..."));
moveMi .setMnemonic(KeyEvent.VK_G);
moveMi .setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G, 0));
moveMi .addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String str = JOptionPane.showInputDialog(null, "Enter a new position: ", 
"New Position", 1);
if (str == null) return;
int n = 0;
try {n = Integer.parseInt(str);
} catch (NumberFormatException error) {return;}
move(n-1);
}
});

m.add(prevMi = new JMenuItem("Previous"));
prevMi .setMnemonic(KeyEvent.VK_V);
prevMi .setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, 0));
prevMi .addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
prevSequence();
}
});

m.add(nextMi = new JMenuItem("Next"));
nextMi .setMnemonic(KeyEvent.VK_N);
nextMi .setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0));
nextMi .addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
nextSequence();
}
});

m.add(addMi = new JMenuItem("Add"));
addMi .setMnemonic(KeyEvent.VK_A);
addMi .setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0));
addMi .addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
addSequence();
}
});

m.add(insertMi = new JMenuItem("Insert"));
insertMi .setMnemonic(KeyEvent.VK_I);
insertMi .setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, 0));
insertMi .addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
insertSequence();
}
});

m.add(removeMi = new JMenuItem("Remove"));
removeMi .setMnemonic(KeyEvent.VK_R);
removeMi .setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, 0));
removeMi .addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
removeSequence();
}
});

int ctrl = InputEvent.CTRL_MASK;
m.add(midiOutMi = new JMenuItem("Midi Output"));
midiOutMi .setMnemonic(KeyEvent.VK_O);
midiOutMi .setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ctrl));
midiOutMi .addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JMSL.midi.edit(new java.awt.Frame());
mixer.panAmpChange(0, 0.5, 1.0);
}
});

add(position = new JButton("" + (currentSequence+1) + "/" + 
sequenceCol.size()), BorderLayout.NORTH);
position.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
moveMi.doClick();
}
});

JPanel p = new JPanel();
p.setLayout(new GridLayout(2,3));
p.setVisible(true);
add(p, BorderLayout.CENTER);

p.add(bt = new JButton("Play"));
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sequencePlayCB.doClick();
}
});

p.add(bt = new JButton("<--"));
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
prevMi.doClick();
}
});

p.add(bt = new JButton("-->"));
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
nextMi.doClick();
}
});

p.add(bt = new JButton("Add"));
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
addMi.doClick();
}
});

p.add(bt = new JButton("Insert"));
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
insertMi.doClick();
}
});

p.add(bt = new JButton("Remove"));
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
removeMi.doClick();
}
});

JPanel midi = new JPanel();
midi.setLayout(new BorderLayout());
midi.setVisible(true);
add(midi, BorderLayout.SOUTH);

midi.add(program = new JLabel 
(programNames[((MidiInstrument)ms.getInstrument()).getProgram()]), 
BorderLayout.CENTER);

midi.add(bt = new JButton("-"), BorderLayout.WEST);
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int p = ((MidiInstrument)ms.getInstrument()).getProgram()-1;
if (p > 0) {
((MidiInstrument)ms.getInstrument()).setProgram(p);
program.setText(programNames[p]);
}
}
});

midi.add(bt = new JButton("+"), BorderLayout.EAST);
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int p = ((MidiInstrument)ms.getInstrument()).getProgram()+1;
if (p < 127) {
((MidiInstrument)ms.getInstrument()).setProgram(p);
program.setText(programNames[p]);
}
}
});

validate();
setVisible(true);
}

private void playSequence() {
if (sequenceCol.size() > 0) {

sequenceCol.setBehavior(new SequentialCursorBehavior(currentSequence));
sequenceCol.launch(JMSL.now(), null);
}
}

private void stopSequence() {
sequenceCol.finishAll();
updatePosition();
}

private void prevSequence() {
move(currentSequence-2);
}

private void nextSequence() {
move(currentSequence+1);
}

private void insertSequence() {
sequenceCol.insert(generate(), currentSequence);
updatePosition();
}

private void addSequence() {
sequenceCol.add(generate());
updatePosition();
}

private MusicShape generate() {
MusicShape temp = (MusicShape) ms.clone();
temp.removeAll();
temp.add(0.25, JMSLRandom.choose(60, 88), 127, 0.25);
temp.add(0.75, JMSLRandom.choose(60, 88), 127, 0.25);
return temp;
}

private void removeSequence() {
if (sequenceCol.size() > 0) {
if (currentSequence >= sequenceCol.size() - 1)
currentSequence=sequenceCol.size() - 1;
sequenceCol.remove(currentSequence);
if (currentSequence >= sequenceCol.size() - 1)
currentSequence = sequenceCol.size() - 1;
}
}

private void updatePosition() {
position.setText("" + (currentSequence+ 1) + "/" + sequenceCol.size());
}

private void move(int n) {
if (n >= 0 && n < sequenceCol.size()) {
if (sequencePlayCB.getState() == true) {
sequenceCol.finishAll();
try {
sequenceCol.waitForDone();
} catch (InterruptedException e) {
e.printStackTrace();
}
currentSequence = n;
sequenceCol.setBehavior(new SequentialCursorBehavior(currentSequence));
sequenceCol.launch(JMSL.now(), null);
}
else {
currentSequence = n;
updatePosition();
}
}
}

public static void main(String[] args) {
JFrame frame = new JFrame("Sequence Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(680, 480);
frame.add(new SequenceTest());
frame.pack();
frame.validate();
frame.setVisible(true);
}

class SequenceRepeatPlayable implements Playable {
public double play(double playTime, Composable thing) throws 
InterruptedException {
SequentialCollection col = (SequentialCollection)thing;
SequentialCursorBehavior behavior = 
(SequentialCursorBehavior)col.getBehavior();
if (behavior.getOriginalPosition() == behavior.getCurrentPosition()) {
sequencePlayCB.doClick();
}
return playTime;
}
}

class SequenceStopPlayable implements Playable {
public double play(double playTime, Composable thing) throws 
InterruptedException {
SequentialCollection col = (SequentialCollection)thing;
SequentialCursorBehavior behavior = 
(SequentialCursorBehavior)col.getBehavior();
currentSequence = behavior.getOriginalPosition();
return playTime;
}
}

class SequentialCursorBehavior implements Behavior {

int currentPosition;
int originalPosition;

public int getCurrentPosition() {
return currentPosition;
}

public void setCurrentPosition(int currentPosition) {
this.currentPosition = currentPosition;
}

public int getOriginalPosition() {
return originalPosition;
}

public SequentialCursorBehavior(int pos) {
this.currentPosition = pos;
this.originalPosition = pos;
}

public Composable choose(SequentialCollection col) {
Composable nextChild = col.get(currentPosition);
updatePosition();
if (currentPosition == col.size() - 1) {
currentPosition = originalPosition;
}
else {
currentPosition++;
}
currentSequence=currentPosition;

return nextChild;
}
}

}



More information about the jmsl mailing list