using System; using System.Collections; using System.Collections.Generic; // This is where you write your machine. Scroll down through the code and fill in all the places // where it says 'TODO'. Instructions are provided for each section you will come across. With this // you can build a basic effect machine. For more examples on how to write this and other types of // machines, see the machines that ship with VioLet Composer. // This is the very first layer in the machine writing API. This interface is still not frozen, but // once it is we can build more advanced APIs on top. // You should download the API docs from SourceForge if you haven't already, and you should look // at things like the WaveletOscillator, EnvelopeSample, MachineWrapper and all the fun stuff // that you have to play with. namespace Wavelet_Tracker { public class MyMachine : MachineParameterisedBase { ////////////////////////////////////////////////////////////////////////// // TODO: Fill in (and *maintain*) these values. ////////////////////////////////////////////////////////////////////////// private const string type = "New Machine"; private const string author = "Demonstration"; private const int version = 1; ////////////////////////////////////////////////////////////////////////// // TODO: Add any internal variables you want to use here. ////////////////////////////////////////////////////////////////////////// private int numEchoes; // You must not alter the signature of the machine, but you can rename // this class which helps find bugs. public MyMachine(string name) : base(type, author, version, name) { ////////////////////////////////////////////////////////////////////////// // TODO: Initialise your own internal variables ONLY here. ////////////////////////////////////////////////////////////////////////// // Note that there may be things you want to reinitialise when seek()ed, // such as the ringbuffer in a standard cross-delay implementation. Here // you should only be initialising constants. // OK so this is a gay example but you might want to make some tables or // something. :-) numEchoes = 8; } protected override void endSetupInputOutputImpl() { ////////////////////////////////////////////////////////////////////////// // TODO: Describe your machine's inputs and outputs as demonstrated below. ////////////////////////////////////////////////////////////////////////// // We have one output called 'Wet' and one called 'Dry'. All outputs are the // same except for their name. Each output must have a unique name. outputs = new MachineConnection[2]; outputs[0] = new MachineConnection("Wet"); outputs[1] = new MachineConnection("Dry"); // This is how we tell the system we have no inputs. (If you comment the // lines below and don't uncomment this one, the machine will crash.) // The same applies if we (for some strange reason) have no outputs. // inputs = new MachineConnection[0]; // In our case, we have a single input, called 'Input'. This is all // that is required to set up the jacks on our machine. inputs = new MachineConnection[1]; inputs[0] = new MachineConnection("Input"); } protected override void endSetupParametersImpl() { ////////////////////////////////////////////////////////////////////////// // TODO: Describe your machine's parameters as demonstrated below. ////////////////////////////////////////////////////////////////////////// parameters = new MachineParameter[1]; // This is all you have to do to create a parameter. MachineParameterContinuous delay = new MachineParameterContinuous("Delay", 0, 0.2f); // There do exists *some* *rudimentary* bitties for labeling your controls. delay.multiplier = 1000; delay.label = "ms"; // Like the jacks, don't forget to put them into the array or you'll be all like "Waa, // I created 18 parameters, where are they? Waa!" and stuff. parameters[0] = delay; // At present four types of parameter exist: // MachineParameterContinuous 4-digits double-precision value // MachineParameterDiscrete 3-digits integer value // MachineParameterSwitch ON/OFF bool value // MachineParameterNote Note+FT+Vol NoteEvent value // See the API docs for more information. } protected override void endProductionImpl(long interval) { ////////////////////////////////////////////////////////////////////////// // TODO: Generate sound as demonstrated below. ////////////////////////////////////////////////////////////////////////// // See the bottom of this file for information on the different types of // events that exist. // getForProcessing() brings us the events from each of our buffers which we want // to process. The boolean at the end indicates (in this case) that we are going // to be done with these events having processed them once, and that they can // be removed. If you don't do this, your computer will explode and you will // get wavelets all over you. List list = inputs[0].buffer.getForProcessing(playTime, interval, true); // We are simply going to loop through the list of events we have. for (int x = 0; x < list.Count; x++) { SoundEvent e = list[x]; // Here we can see the machine filtering out the events that it is interested in. if (e.eventType == EventType.AUDIO_WAVELETS) { WaveletEvent w = (WaveletEvent)e; float wamp = w.amplitude; long wtime = w.startTime; for (int y = 0; y < numEchoes; y++) { wamp *= 0.8f; // On this line we read back the current value of a parameter. Can you see // an efficiency saving we could make here? wtime += (long)(((float)parameters[0].parameterValue) * App.TIME_RES); // Here we create a new event and insert it into the 'wet' output buffer. WaveletEvent v = new WaveletEvent(w.frequency, wamp, w.length, w.phase, wtime); outputs[0].buffer.addEvent(v); } // The original event is put into the 'dry' output. outputs[1].buffer.addEvent(w); } } } protected override void endSeekImpl(long seekTime) { ////////////////////////////////////////////////////////////////////////// // TODO: Anything you might need to do before each time play is pressed. // At this time, playTime is being set to seekTime. You may wish to reset // some internal timers, cancel currently playing notes or samples, things // like that. ////////////////////////////////////////////////////////////////////////// } protected override void endTickImpl(ArrayList parameterChanges) { ////////////////////////////////////////////////////////////////////////// // TODO: Explicitly handle pattern events if you so desire. See the score // machine for an example of this. ////////////////////////////////////////////////////////////////////////// } } } // Event Types: // All events have a startTime and endTime. // Wavelet Mathematical freq, amp, length, phase // PCM Numerical float[][] // Note Musical note, finetune, volume