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. // TODO (Developer): Clean up the machines and comment them so they are a clear demonstration of the principles. // 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. namespace Wavelet_Tracker { public class CrossDelayMachine : MachineParameterisedBase { ////////////////////////////////////////////////////////////////////////// // TODO: Fill in these values. ////////////////////////////////////////////////////////////////////////// private const string type = "Cross Delay"; private const string author = "Internal"; private const int version = 1; ////////////////////////////////////////////////////////////////////////// // TODO: Add any internal variables you want to use here. ////////////////////////////////////////////////////////////////////////// private const int numEchoes = 8; public CrossDelayMachine(string name) : base(type, author, version, name) { machineLimitations = MachineLimitations.ProcessPCM; } protected override void endSetupInputOutputImpl() { // 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[1]; outputs[0] = new MachineConnection("Wet"); //outputs[1] = new MachineConnection("Dry"); // This is how we tell the system we have no inputs. (If you remove 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]; inputs = new MachineConnection[1]; inputs[0] = new MachineConnection("Input"); } protected override void endSetupParametersImpl() { parameters = new MachineParameter[2]; MachineParameterContinuous delay = new MachineParameterContinuous("Delay", 0, 0.02f); delay.multiplier = 10000; delay.label = "ms"; parameters[0] = delay; MachineParameterContinuous decay = new MachineParameterContinuous("Decay", 0, 0.2f); decay.multiplier = 100; decay.label = "%"; parameters[1] = decay; } protected unsafe override void endProductionImpl(long interval) { ////////////////////////////////////////////////////////////////////////// // TODO: Generate sound as demonstrated below. ////////////////////////////////////////////////////////////////////////// List list = inputs[0].buffer.getForProcessing(playTime, interval, true); long etime = (long) (((float) parameters[0].parameterValue)*App.TIME_RES*10); float edecay = (float) (1.0 - (float)parameters[1].parameterValue); for (int x = 0; x < list.Count; x++) { SoundEvent e = list[x]; if (e.eventType == EventType.AUDIO_PCM) { PCMEvent w = (PCMEvent)e; long wtime = w.startTime; long wend = w.endTime; float amp = 1.0f; bool goLeft = true; bool goRight = true; for (int y = 0; y < numEchoes; y++) { PCMEvent v = new PCMEvent(wtime, wend, 2, w.bufferLength, false); // Copy to the new event with amplitude amp, using goLeft and goRight // to determine which channels are copied to. for (int z = 0; z < w.bufferLength; z++) { if (goLeft) { *(v.data[0] + z) = *(w.data[0] + z) * amp; *(v.data[1] + z) = 0.0f; } if (goRight) { *(v.data[0] + z) = 0.0f; *(v.data[1] + z) = *(w.data[0] + z) * amp; } } if (goLeft) { goRight = true; goLeft = false; } else { goRight = false; goLeft = true; } outputs[0].buffer.addEvent(v); amp *= edecay; wtime += etime; wend += etime; } outputs[0].buffer.addEvent(w); } } } protected override void endSeekImpl(long seekTime) { ////////////////////////////////////////////////////////////////////////// // TODO: Anything you might need to do before each time play is pressed. ////////////////////////////////////////////////////////////////////////// } protected override void endTickImpl(ArrayList parameterChanges) { ////////////////////////////////////////////////////////////////////////// // TODO: Explicitly handle pattern events if you so desire. ////////////////////////////////////////////////////////////////////////// } } }