[jmsl] Reverb tweaked for use in JSyn and JMSL
jmsl at music.columbia.edu
jmsl at music.columbia.edu
Sat Jan 10 23:41:17 EST 2009
Here's a revision of Reverb2 I posted earlier.
This wraps Phil's Reverb1 wrapped up in a SynthNote, which addresses a
few issues, so that now this works fine with JMSL.
main() has two tests in it: one pure JSyn and another for JMSL
Thanks
Nick Didkovsky
package com.punosmusic.circuitgrabbag;
/**
* SynthNote Reverb
*
* This is a SynthNote wrapper around Phil Burk's Reverb1 SynthCircuit
*
* This is suitable for use in JMSL's signal processing
SynthNoteAllPortsInstrumentSP, which therefore also works in JMSL Score.
*
* See main() for testing as pure JSyn or JMSL test
*
* @author Nick Didkovsky 1/10/09
*
*/
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import com.softsynth.jmsl.*;
import com.softsynth.jmsl.jsyn.*;
import com.softsynth.jsyn.*;
import com.softsynth.jsyn.circuits.FilteredSawtoothBL;
import com.softsynth.jsyn.circuits.Reverb1;
public class Reverb2 extends SynthNote {
private Reverb1 reverb1;
private BusWriter busWriter;
public SynthInput input;
public SynthInput dryGain;
public SynthInput rate;
SynthEnvelope env;
EnvelopePlayer envPlayer;
MultiplyUnit mult;
public Reverb2() {
add(reverb1 = new Reverb1());
add(envPlayer = new EnvelopePlayer());
add(busWriter = new BusWriter());
add(mult = new MultiplyUnit());
reverb1.busInput.connect(0, busWriter.busOutput, 0);
envPlayer.output.connect(mult.inputA);
reverb1.output.connect(mult.inputB);
addPort(input = busWriter.input, "input");
addPort(dryGain = reverb1.dryGain);
addPort(rate = envPlayer.rate, "envRate");
addPort(output = mult.output, "output");
addPort(amplitude = envPlayer.amplitude, "amplitude");
rate.setup(0.1, 1.0, 2.0);
dryGain.setup(0, 0.15, 1.0);
double[] envData = { 0.1, 1.0, 0.1, 0 };
env = new SynthEnvelope(envData);
}
public void setStage(int time, int stage) {
switch (stage) {
case 0:
start(time);
envPlayer.envelopePort.queue(time, env, 0, 1);
break;
case 1:
envPlayer.envelopePort.queue(time, env, 1, 1,
Synth.FLAG_AUTO_STOP);
break;
default:
break;
}
}
public static void main(String[] args) {
boolean TEST_JSYN = true;
if (TEST_JSYN) {
System.out.println("Test Reverb2 with JSyn only");
Synth.startEngine(0);
SynthObject.enableTracking(true);
LineOut out = new LineOut();
out.start();
// sine for dry signal in left channel
SineOscillator osc = new SineOscillator();
osc.amplitude.set(0.5);
osc.start();
MultiplyUnit mult = new MultiplyUnit();
mult.start();
// toss a multiplier in to reduce dry signal level, cheap
mixing...
mult.inputA.set(0.5);
osc.output.connect(mult.inputB);
mult.output.connect(0, out.input, 0);
// lag to sweep sine's frequency around so we can hear reverb
ExponentialLag lag = new ExponentialLag();
lag.input.set(100);
lag.halfLife.set(0.2);
lag.output.connect(osc.frequency);
lag.input.set(1000);
lag.start();
// connect our reverb to right channel
Reverb2 reverb2 = new Reverb2();
reverb2.output.connect(0, out.input, 1);
reverb2.setStage(0);
// connect dry signal to reverb
osc.output.connect(reverb2.input);
Frame f = new Frame();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
Synth.stopEngine();
System.exit(0);
}
});
f.setSize(320, 200);
f.setVisible(true);
// wake up every so often and sweep to a new frequency
while (true) {
try {
Thread.sleep((long) (Math.random() * 3000 + 500));
} catch (InterruptedException e1) {
}
double freq = Math.random() * 2000;
lag.input.set(freq);
System.out.println("Sweeping to " + freq + " Hz");
}
} else {
System.out.println("Test Reverb2 with JMSL");
java.awt.Frame f = new java.awt.Frame("Test Reverb2 with JMSL");
f.setLayout(new java.awt.BorderLayout());
f.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent e) {
JMSL.closeMusicDevices();
System.exit(0);
}
});
f.setSize(300, 200);
f.setVisible(true);
JSynMusicDevice.instance().edit(f);
JSynMusicDevice.instance().open();
JMSL.clock.setAdvance(0.5);
JMSLRandom.randomize();
// create two instruments, one to play dry melody and
another to play reverb
SynthNoteAllPortsInstrumentSP reverbIns = new
SynthNoteAllPortsInstrumentSP(8, Reverb2.class.getName());
SynthNoteAllPortsInstrument melodicIns = new
SynthNoteAllPortsInstrument(8, FilteredSawtoothBL.class.getName());
// patch output of melodic ins to input of reverb
reverbIns.addSignalSource(melodicIns.getOutput());
// add instruments to mixer and pan them hard left/right
JMSLMixerContainer mixer = new JMSLMixerContainer();
mixer.start();
mixer.addInstrument(melodicIns);
mixer.addInstrument(reverbIns);
mixer.panAmpChange(0, 0, 0.35);
mixer.panAmpChange(1, 1, 0.75);
f.add(java.awt.BorderLayout.NORTH,
mixer.getPanAmpControlPanel());
// melody playing MusicShape
MusicShape melodicShape = new
MusicShape(melodicIns.getDimensionNameSpace());
melodicShape.setName("melody");
melodicShape.setInstrument(melodicIns);
melodicShape.prefab();
melodicShape.setRepeats(1000);
// reverb playing MusicShape
MusicShape reverbMusicShape = new
MusicShape(reverbIns.getDimensionNameSpace());
reverbMusicShape.setName("reverb");
reverbMusicShape.setInstrument(reverbIns);
reverbMusicShape.setRepeats(1000);
// stuff reverb shape with long durations
double[] defaultData =
MusicShape.getDefaultArray(reverbMusicShape);
defaultData[0]=8; // long durations
defaultData[2]=0.8; // amp
defaultData[3]=7; // long hold time for reverb
for (int i = 0; i < 5; i++) {
reverbMusicShape.add(defaultData);
}
final com.softsynth.jmsl.view.MusicShapeEditor se = new
com.softsynth.jmsl.view.MusicShapeEditor();
se.addMusicShape(reverbMusicShape);
se.addMusicShape(melodicShape);
f.add(java.awt.BorderLayout.SOUTH, se.getComponent());
f.pack();
melodicShape.addRepeatPlayable(new Playable() {
public double play(double time, Composable parent)
throws InterruptedException {
MusicShape m = (MusicShape) parent;
m.scramble(0, m.size() - 1, 0);
m.scramble(0, m.size() - 1, 1);
se.refresh();
return time;
}
});
ParallelCollection col = new
ParallelCollection(melodicShape, reverbMusicShape);
col.launch(JMSL.now() + 3);
}
}
}
More information about the jmsl
mailing list