Mercurial > hg > jslab
view src/samer/midi/MidiSynth.java @ 5:b67a33c44de7
Remove some crap, etc
author | samer |
---|---|
date | Fri, 05 Apr 2019 21:34:25 +0100 |
parents | 74cc9e431818 |
children |
line wrap: on
line source
/* * Copyright (c) 2000, Samer Abdallah, King's College London. * All rights reserved. * * This software is provided AS iS and WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. */ package samer.midi; import samer.core.*; import samer.core.types.*; import samer.core.util.*; import samer.tools.*; import samer.maths.*; import java.util.*; import java.io.*; import javax.sound.midi.*; /** A class which generates midi events from the values of an input vector. Each element of the vector corresponds to a certain midi note number. The loudness of a note depends on the value of the corresponding vector element. Parameters: trigger note on events. offset is added to the vector element number to get a midi note number. pedal control whether or not note off events are generated */ public class MidiSynth extends Viewable implements Agent, Task, Saveable { VVector in; Synthesizer synthesizer=null; protected int n; protected double [] x; protected int [] nnums; protected int [] chans; protected MidiChannel [] cc; protected VDouble factor; protected VInteger offset; protected VBoolean pedal; public MidiSynth(VVector input) { super("midisynth"); Shell.push(node); factor = new VDouble("factor",128,0); offset = new VInteger("offset",0,0); pedal = new VBoolean("pedal",false,0); setAgent(this); addAgent(new Saver(this)); Shell.pop(); in = input; n = in.size(); x = in.array(); nnums = new int[n]; chans = new int[n]; for (int i=0; i<n; i++) { nnums[i]=i; chans[i]=0; } try { getAgent().execute("load", Shell.env()); open(); } catch (Exception ex) { ex.printStackTrace(); } } public Viewer getViewer() { return new BaseViewer(this) { { panel().setLayout( new StackLayout(3)); add(factor); add(offset); add(pedal); add(Shell.createButtonsFor(MidiSynth.this)); } }; } public void open() throws Exception { if (synthesizer!=null) { Shell.print("already open"); return; } if ((synthesizer = MidiSystem.getSynthesizer()) == null) { throw new Exception("getSynthesizer() failed"); } Shell.print("opening synthesizer"); synthesizer.open(); cc = synthesizer.getChannels(); Shell.print("got synth and channel:"+synthesizer+cc); } public void close() { if (synthesizer != null) { Shell.print("closing synthesiser"); synthesizer.close(); synthesizer = null; } } public void dispose() { close(); factor.dispose(); offset.dispose(); pedal.dispose(); super.dispose(); } public void silence() { for (int i=0; i<n; i++) { cc[chans[i]].noteOff(nnums[i]+offset.value, 0); } } public void starting() {} public void stopping() {} public void run() { if (synthesizer==null) return; for (int i=0; i<n; i++) { if (x[i]>0) { cc[chans[i]].noteOn(nnums[i]+offset.value,mapVelocity(x[i])); } else if (x[i]<0 && !pedal.value) { cc[chans[i]].noteOff(nnums[i]+offset.value, 0); } } } public void getCommands(Agent.Registry r) { r.add("open").add("close").add("silence").add("edit"); } public void execute(String cmd, Environment env) throws Exception { if (cmd.equals("open")) open(); else if (cmd.equals("close")) close(); else if (cmd.equals("silence")) silence(); else if (cmd.equals("edit")) Shell.expose( new Editor(),"MidiSynthEditor"); } public void save(OutputStream s) throws Exception { ObjectOutputStream o=new ObjectOutputStream(s); o.writeObject(nnums); o.writeObject(chans); o.flush(); } public void load(InputStream s) throws Exception { ObjectInputStream o=new ObjectInputStream(s); int [] newnotes = (int [])o.readObject(); int [] newchans = (int [])o.readObject(); safecopy( newnotes, nnums); safecopy( newchans,chans); } public void read(Reader r) throws Exception { throw new Exception("unsupported"); } public void write(Writer w) throws Exception { throw new Exception("unsupported"); } private static void safecopy( int [] src, int [] dest) { int n=src.length; if (dest.length<n) n=dest.length; System.arraycopy( src, 0, dest, 0, n); } public int mapVelocity(double x) { int vel=(int)(factor.value*x); if (vel>127) vel=127; return vel; } class Editor extends BaseViewer { VInteger i=new VInteger("input number",0,Variable.NOINIT); VInteger n=new VInteger("note number",nnums[0],Variable.NOINIT); VInteger c=new VInteger("channel number",chans[0],Variable.NOINIT); VInteger p=new VInteger("program",0,0); VBoolean l1=new VBoolean("lock note",false,Variable.NOINIT); VBoolean l2=new VBoolean("lock channel",false,Variable.NOINIT); public Editor() { super(MidiSynth.this); i.setRange(0,nnums.length-1); n.setRange(0,127); c.setRange(0,15); n.setRange(0,127); p.setRange(0,127); setLayout( new StackLayout()); add(i); add(n); add(c); add(p); add(l1); add(l2); i.addObserver(this); n.addObserver(this); c.addObserver(this); p.addObserver(this); } public void update(Observable o, Object arg) { disposeFilter(o,arg); if (arg==this) return; // &&& if (o==i) { if (l1.value) { nnums[i.value]=n.value; } else { n.value = nnums[i.value]; n.changed(this); } if (l2.value) { chans[i.value]=c.value; } else { c.value = chans[i.value]; c.changed(this); } p.value = cc[c.value].getProgram(); p.changed(this); } else if (o==n) { nnums[i.value]=n.value; } else if (o==c) { chans[i.value]=c.value; } else if (o==p) { cc[c.value].programChange(p.value); } } } }