/* * Created on Dec 20, 2003 * */ package jmslexamples.jsyn; import java.awt.*; import java.awt.event.*; import com.softsynth.jmsl.*; import com.softsynth.jmsl.jsyn.JSynInsFromClassName; import com.softsynth.jmsl.jsyn.JSynMusicDevice; import com.softsynth.jmsl.util.DataTranslatorVector; /** * Chain multiple DataTranslators together in a sequence. * * Play a MusicShape with chromatic pitches. Use DataTranslatorVector to add/remove DataTranslators to it. * * @see com.softsynth.jmsl.DataTranslator * @see com.softsynth.jmsl.util.DataTranslatorVector * * @author Nick Didkovsky, email: didkovn@mail.rockefeller.edu, (c) 2003 Nick Didkovsky, all rights reserved. * */ public class DataTranslatorVectorDemo extends java.applet.Applet implements ItemListener, ActionListener { private DataTranslatorVector translatorVector; private WholeToneTranslator wholeToneTranslator; private RhythmicJitterTranslator rhythmicJitterTranslator; private MusicShape myShape; private JMSLMixerContainer mixer; private Button startButton; private Button stopButton; private Checkbox useTranslatorCheckbox; private Checkbox useJitterCheckbox; public void init() { } public void start() { buildDataTranslators(); buildGUI(); buildMusic(); myShape.setDataTranslator(translatorVector); } private void buildDataTranslators() { translatorVector = new DataTranslatorVector(); wholeToneTranslator = new WholeToneTranslator(60); rhythmicJitterTranslator = new RhythmicJitterTranslator(0.1); } private void buildGUI() { setLayout(new BorderLayout()); Panel p = new Panel(); p.setLayout(new GridLayout(0, 1)); p.add(useTranslatorCheckbox = new Checkbox("Whole Tone Translator")); p.add(useJitterCheckbox = new Checkbox("Rhythmic Jitter Translator")); useTranslatorCheckbox.addItemListener(this); useJitterCheckbox.addItemListener(this); add(BorderLayout.NORTH, p); p = new Panel(); p.setLayout(new GridLayout(1, 2)); p.add(startButton = new Button("START")); startButton.addActionListener(this); p.add(stopButton = new Button("STOP")); add(BorderLayout.SOUTH, p); stopButton.addActionListener(this); stopButton.setEnabled(false); } private void buildMusic() { JMSL.clock.setAdvance(0.1); MusicDevice dev = JSynMusicDevice.instance(); dev.open(); JSynInsFromClassName ins = new JSynInsFromClassName(4, com.softsynth.jsyn.circuits.FilteredSawtoothBL.class.getName()); mixer = new JMSLMixerContainer(); mixer.addInstrument(ins); mixer.start(); myShape = new MusicShape(4); for (int i = 0; i < 13; i++) { myShape.add(0.25, i + 60, 0.5, 0.2); } myShape.setInstrument(ins); myShape.setRepeats(Integer.MAX_VALUE); } public void stop() { myShape.finishAll(); try { myShape.waitForDone(); } catch (InterruptedException e) { e.printStackTrace(); } removeAll(); JMSL.closeMusicDevices(); } public void itemStateChanged(ItemEvent ev) { Object source = ev.getSource(); if (source == useTranslatorCheckbox) { if (useTranslatorCheckbox.getState()) { translatorVector.addElement(wholeToneTranslator); } else { translatorVector.removeElement(wholeToneTranslator); } } if (source == useJitterCheckbox) { if (useJitterCheckbox.getState()) { translatorVector.addElement(rhythmicJitterTranslator); } else { translatorVector.removeElement(rhythmicJitterTranslator); } } } public void actionPerformed(ActionEvent ev) { Object source = ev.getSource(); if (source == startButton) { myShape.launch(JMSL.now()); startButton.setEnabled(false); stopButton.setEnabled(true); } if (source == stopButton) { myShape.finishAll(); try { myShape.waitForDone(); } catch (InterruptedException e) { e.printStackTrace(); } stopButton.setEnabled(false); startButton.setEnabled(true); } } private class WholeToneTranslator implements DataTranslator { double centerPitch; public WholeToneTranslator(double centerPitch) { this.centerPitch = centerPitch; } public double[] translate(MusicJob job, double[] data) { // make a copy of the incoming double[] double[] dar = new double[data.length]; System.arraycopy(data, 0, dar, 0, data.length); // shift pitch to whole tone scale double difference = dar[1] - centerPitch; dar[1] = dar[1] + 2 * difference; return dar; } } private class RhythmicJitterTranslator implements DataTranslator { double range; public RhythmicJitterTranslator(double range) { this.range = range; } public double[] translate(MusicJob job, double[] data) { // make a copy of the incoming double[] double[] dar = new double[data.length]; System.arraycopy(data, 0, dar, 0, data.length); // add or subtract some value from its duration dar[0] = dar[0] + JMSLRandom.choosePlusMinus(range); return dar; } } }