using System; using System.Collections; namespace Wavelet_Tracker { public class ScoreMachine : MachineParameterisedBase { private const string type = "Score Machine"; private const string author = "Internal"; private const int version = 1; // A composition node is a handy way to organise track data. private CompositionNode trackStuff = new CompositionNode("foo"); public ScoreMachine(string name) : base(type, author, version, name) { machineLimitations = MachineLimitations.EmitsNotes; } protected override void endProductionImpl(long interval) { // This machine does nothing during production; we cheat and do everything between production, during ticking. } protected override void endSeekImpl(long seekTime) { // We also do nothing during seeking, like most machines. } protected override void endSetupParametersImpl() { parameters = new MachineParameter[3]; // The score and volume parameters are created in a group by setting both of their group numbers to 1. // The master volume is a global parameter with group number 0. MachineParameterNote freq = new MachineParameterNote("Score", 1); //freq.scaleName = "Semitone Scale"; parameters[0] = freq; MachineParameterContinuous vol = new MachineParameterContinuous("Volume", 1, 1.0f); vol.multiplier = 100; vol.label = "%"; parameters[1] = vol; MachineParameterContinuous mVol = new MachineParameterContinuous("Master Volume", 0, 1.0f); mVol.multiplier = 100; mVol.label = "%"; parameters[2] = mVol; } protected override void endSetupInputOutputImpl() { outputs = new MachineConnection[1]; outputs[0] = new MachineConnection("Note Output"); inputs = new MachineConnection[0]; } protected override void endTickImpl(ArrayList parameterChanges) { // Handle the volume parameter on a per-track basis. for (int x = 0; x < parameterChanges.Count; x++) { MachineParameterChange mpc = (MachineParameterChange)parameterChanges[x]; if (mpc.parameter.parameterName.Equals("Volume")) { trackStuff.setAttribute("Volume " + mpc.trackNum, mpc.newValue); } } // We have to do the whole operation twice to ensure that all volume commands // are read before the note commands are processed. for (int x = 0; x < parameterChanges.Count; x++) { MachineParameterChange mpc = (MachineParameterChange)parameterChanges[x]; // This is what the programmer will do for each parameter that they want to watch // for changes. Any parameters that are just read from during production can be // ignored. if (mpc.parameter.parameterName.Equals("Score")) { float volume = (float) parameters[2].parameterValue; float trackVol = 1.0f; try { trackVol = (float) trackStuff.getAttribute("Volume " + mpc.trackNum); } catch (Exception) { } NoteEvent noteEvent = new NoteEvent(playTime, "Semitone Scale", ((NoteEvent)mpc.newValue).note, ((NoteEvent)mpc.newValue).fineTune); noteEvent.metadata.setAttribute("Volume", volume*trackVol); outputs[0].buffer.addEvent(noteEvent); } } } } }