package jmslexamples.jsyn2; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import com.softsynth.jmsl.*; import com.softsynth.jmsl.jsyn2.JSynMusicDevice; import com.softsynth.jmsl.jsyn2.JSynUnitVoiceInstrument; import com.softsynth.jmsl.score.*; import com.softsynth.jmsl.util.Patch; /** * Demonstrates how a JMSL Score can have one instrument in one staff apply * signal processing to the output of other instrument(s) on other staves. Here * two instruments (FilteredSawtoothBL and RingModBell) are bussed to an * instrument with an interpolating delay line. Different notes in the delay * instrument have different values for feedback and delay time, so you will * hear delay behavior change. Note that a JSynSignalProcessingInstrument is a * polyphonic signal processor, so you can create a chord where each note has * different delay/feedback values (as is the case in this demo). * * Upgraded to JSyn2 API Dec 2016 * * @author Nick Didkovsky, July 9, 2002, (c) copyright 2002 Nick Didkovsky, all * rights reserved */ public class SignalProcessingScore { JSynUnitVoiceInstrument ins1; JSynUnitVoiceInstrument ins2; JSynUnitVoiceInstrument insSP; Score score; ScoreFrame scoreFrame; Orchestra orch; int[] prettyIntervals = { 0, 4, 7, 9 }; void build() { initMusicDevice(); initScore(); buildInstruments(); buildOrchestra(); buildComposition(); } void initMusicDevice() { JSynMusicDevice.instance().open(); JMSL.clock.setAdvance(0.1); } void initScore() { score = new Score(3, 800, 400); score.setName("Signal Processing Score"); score.setComposer("Nick Didkovsky"); score.setCopyright("(c) 2016 Nick Didkovsky"); } void buildInstruments() { // A signal source ins1 = new JSynUnitVoiceInstrument(); ins1.setPolyphony(4); ins1.setUnitVoiceClassName(com.softsynth.jmsl.jsyn2.unitvoices.FilteredSawtoothBL.class.getName()); ins1.buildFromAttributes(); // A signal source ins2 = new JSynUnitVoiceInstrument(); ins2.setPolyphony(4); ins2.setUnitVoiceClassName(com.softsynth.jmsl.jsyn2.unitvoices.RingModBell.class.getName()); ins2.buildFromAttributes(); // a signal processor insSP = new JSynUnitVoiceInstrument(); insSP.setPolyphony(3); insSP.setUnitVoiceClassName(com.softsynth.jmsl.jsyn2.unitvoices.DelayWithFeedback.class.getName()); insSP.buildFromAttributes(); new MusicShape(insSP.getDimensionNameSpace()).print(); } void buildOrchestra() { orch = new Orchestra(); score.setOrchestra(orch); addInstrumentsToOrchestra(); patchSignals(); setupMix(); } private void setupMix() { // set up a custom mix JMSLMixerContainer mixer = orch.getJMSLMixerContainer(); mixer.panAmpChange(0, 0.0, 0.2); mixer.panAmpChange(1, 0.25, 0.4); mixer.panAmpChange(2, 1.0, 0.9); } private void patchSignals() { // no need to addSignalSource() explicitly here. orch.patchInstruments() will do it after you set up orch patches // insSP.addSignalSource(ins1.getOutput()); // insSP.addSignalSource(ins2.getOutput()); // bus signal sources to signal processor // Add to orchestra patch list. This way it will save/load to a score // xml file orch.addOrchPatch(new Patch(0, 2)); orch.addOrchPatch(new Patch(1, 2)); orch.patchInstruments(); } private void addInstrumentsToOrchestra() { orch.addInstrument(ins1, "Filtered Sawtooth BL"); orch.addInstrument(ins2, "Ring Mod Bell"); orch.addInstrument(insSP, "Variable Delay with Feedback"); } void buildComposition() { score.addMeasure(); buildFirstStaff(); buildSecondStaff(); buildThirdStaff(); } private void buildFirstStaff() { // insert some notes in first staff score.rewind(); score.setCurrentStaffNumber(0); for (int i = 0; i < 8; i++) { score.addNote(1.0, 60 + JMSLRandom.choose(prettyIntervals.length), 0.5, 0.2); } } private void buildSecondStaff() { // insert some notes in second staff score.rewind(); score.setCurrentStaffNumber(1); for (int i = 0; i < 16; i++) { double octaveTranspositionEveryOtherNote = -12 * (i % 2); score.addNote(0.5, 84 + JMSLRandom.choose(prettyIntervals.length) + octaveTranspositionEveryOtherNote, 0.5, 0.9); } } private void buildThirdStaff() { // insert signal processing notes in third staff score.rewind(); score.setCurrentStaffNumber(2); // third staff DimensionNameSpace spNameSpace = insSP.getDimensionNameSpace(); // quick little trick to see a UnitVoice's dimensions new MusicShape(spNameSpace).print(); double[] spDouble = { 4.0, 60, 0.5, 3.9, 0.8, 0.1 }; score.addNote(spNameSpace, spDouble); spDouble[spNameSpace.getDimension("pitch")] = 72; spDouble[spNameSpace.getDimension("feedback")] = 0.2; spDouble[spNameSpace.getDimension("delay")] = 4.0 / 3.0; score.addInterval(spNameSpace, spDouble); spDouble[spNameSpace.getDimension("duration")] = 2.0; spDouble[spNameSpace.getDimension("pitch")] = 60; spDouble[spNameSpace.getDimension("hold")] = 1.9; spDouble[spNameSpace.getDimension("feedback")] = 0.5; spDouble[spNameSpace.getDimension("delay")] = 0.25; score.addNote(spNameSpace, spDouble); spDouble[spNameSpace.getDimension("duration")] = 1.0; spDouble[spNameSpace.getDimension("pitch")] = 60; spDouble[spNameSpace.getDimension("hold")] = 1.0; spDouble[spNameSpace.getDimension("delay")] = 0.333 / 2; spDouble[spNameSpace.getDimension("feedback")] = 0.95; spDouble[spNameSpace.getDimension("amplitude")] = 0.4; score.addNote(spNameSpace, spDouble); score.addNote(1.0, 0, 0, 0); // rest } void buildShowScoreFrame() { scoreFrame = new ScoreFrame(); scoreFrame.addScore(score); scoreFrame.setVisible(true); scoreFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { JMSL.closeMusicDevices(); scoreFrame.quit(); } }); } public static void main(String args[]) { JMSLRandom.randomize(); SignalProcessingScore signalProcessingScore = new SignalProcessingScore(); signalProcessingScore.build(); signalProcessingScore.buildShowScoreFrame(); } }