package jmsltestsuite; import java.awt.Button; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import com.softsynth.jmsl.JMSLRandom; import com.softsynth.jsyn.AppletFrame; import com.softsynth.jsyn.EnvelopePlayer; import com.softsynth.jsyn.LineOut; import com.softsynth.jsyn.SawtoothOscillatorBL; import com.softsynth.jsyn.Synth; import com.softsynth.jsyn.SynthCircuit; import com.softsynth.jsyn.SynthEnvelope; import com.softsynth.jsyn.SynthNote; import com.softsynth.jsyn.util.BussedVoiceAllocator; /** * Deprecated demo. Don't bother with this unless you are intrerested in ancient history * or unless you want to rewrite in v103 using TunedSynthNoteInstrument as an exercise * * Hit the BANG button: play a SynthNote pulled from a polyphonic allocator, sustain for a random hold time, use a random pitch in 13 tone ET Demonstrates: Using a BussedVoiceAllocator to implement polyphonic SynthNotes Using a JSyn envelope player to cue up the attack/sustin portion of a sound Using a JSyn envelope player to release sound and autostop the circuit Calling SynthNote.note() to fire a sound with a hold time. Using JMSLRandom to randomize frequencies and amplitudes @author Nick Didkovsky 5/28/01 1:09PM Nancy */ public class TestNoteOnNoteOff extends java.applet.Applet implements ActionListener { Button bang; BussedVoiceAllocator allocator; LineOut out; public void init() { JMSLRandom.randomize(); add(bang = new Button("BANG FREQUENTLY AND HEAR SOUNDS OVERLAP")); bang.addActionListener(this); } public void start() { Synth.startEngine(0); // build an allocator that return up to 8 voices allocator = new BussedVoiceAllocator(8) { public SynthCircuit makeVoice() { SynthCircuit circuit = new SustainingSynthNote(); return addVoiceToMix(circuit); } }; out = new LineOut(); allocator.output.connect(0, out.input, 0); allocator.output.connect(0, out.input, 1); out.start(); /* Synchronize Java display. */ getParent().validate(); getToolkit().sync(); } public void stop() { Synth.stopEngine(); } void handleBang() { double hold = JMSLRandom.choose(0.3, 5.0); double frequency = 220 * Math.pow(2.0, JMSLRandom.choose(13) / 13.0); double amplitude = JMSLRandom.choose(0.1, 0.3); int onTime = Synth.getTickCount(); int holdTime = (int) (Synth.getTickRate() * hold); // request a voice from the allocator for the specified duration SynthNote voice = (SynthNote) allocator.steal(onTime + holdTime); // call noteon/noteoff in one convenient method voice.note(onTime, holdTime, frequency, amplitude); } public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == bang) handleBang(); } public static void main(String args[]) { java.applet.Applet applet = new TestNoteOnNoteOff(); AppletFrame f = new AppletFrame("Test Polyphonic SynthNotes sustaining for random duration", applet); f.setSize(600, 200); f.setVisible(true); f.test(); } } class SustainingSynthNote extends SynthNote { SawtoothOscillatorBL osc; EnvelopePlayer ampEnvPlayer; SynthEnvelope ampEnv; public SustainingSynthNote() { add(osc = new SawtoothOscillatorBL()); add(ampEnvPlayer = new EnvelopePlayer()); ampEnvPlayer.output.connect(osc.amplitude); // expose the freq and amp of the sineOscillator as aliases addPort(frequency = osc.frequency); addPort(amplitude = ampEnvPlayer.amplitude); // expose an output port aliased to the oscillator's output addPort(output = osc.output, "Output"); double[] envData = { 0.06, 1.0, 0.2, 0.1, 0.5, 0.0 }; ampEnv = new SynthEnvelope(envData); } public void setStage(int time, int stage) { switch (stage) { case 0 : // note on by convention start(time); ampEnvPlayer.envelopePort.clear(time); ampEnvPlayer.envelopePort.queue(time, ampEnv, 0, 2); // queue first two frames, the attack break; case 1 : // note off by convention ampEnvPlayer.envelopePort.clear(time); ampEnvPlayer.envelopePort.queue(time, ampEnv, 2, 1, Synth.FLAG_AUTO_STOP); // release and shut off circuit break; default : break; } } }