public override void Process() { if (haveSimulationError) { monoInput.PassThroughTo(monoOutput); } else { double[][] inBuffers = monoInput.GetAudioBuffers(); double[][] outBuffers = monoOutput.GetAudioBuffers(); // Read input samples from unmanaged memory monoInput.ReadData(); try { SimulationProcessor.RunSimulation(inBuffers, outBuffers, inBuffers[0].Length); } catch (Exception ex) { haveSimulationError = true; new Thread(() => { MessageBox.Show("Error running circuit simulation.\n\n" + ex.Message, "Simulation Error", MessageBoxButton.OK, MessageBoxImage.Error); }).Start(); } // Write outout samples to unmanaged memory monoOutput.WriteData(); } }
/// <summary> /// Restore plugin state /// </summary> /// <param name="stateData">Byte array of data to restore</param> public override void RestoreState(byte[] stateData) { XmlSerializer serializer = new XmlSerializer(typeof(VstProgramParameters)); try { using (MemoryStream memoryStream = new MemoryStream(stateData)) { VstProgramParameters programParameters = serializer.Deserialize(memoryStream) as VstProgramParameters; if (string.IsNullOrEmpty(programParameters.SchematicPath)) { haveSimulationError = false; SimulationProcessor.ClearSchematic(); } else { LoadSchematic(programParameters.SchematicPath); } SimulationProcessor.Oversample = programParameters.OverSample; SimulationProcessor.Iterations = programParameters.Iterations; foreach (VSTProgramControlParameter controlParameter in programParameters.ControlParameters) { var wrapper = SimulationProcessor.InteractiveComponents.Where(i => i.Name == controlParameter.Name).SingleOrDefault(); if (wrapper != null) { switch (wrapper) { case PotWrapper potWrapper: potWrapper.PotValue = controlParameter.Value; break; case DoubleThrowWrapper doubleThrowWrapper: doubleThrowWrapper.Engaged = (controlParameter.Value == 1); break; case MultiThrowWrapper multiThrowWrapper: multiThrowWrapper.Position = (int)controlParameter.Value; break; } } } if (EditorView != null) { EditorView.UpdateSchematic(); } } } catch (Exception ex) { Logger.Log("Load state failed: " + ex.Message); } }
/// <summary> /// Set plugin state from program data /// </summary> /// <param name="program">The program data</param> /// <param name="index">The index of the program</param> public void SetProgramData(Program program, int index) { Logging.Log("Load program: " + index); XmlSerializer serializer = new XmlSerializer(typeof(VstProgramParameters)); try { using (MemoryStream memoryStream = new MemoryStream(program.Data)) { VstProgramParameters programParameters = serializer.Deserialize(memoryStream) as VstProgramParameters; if (string.IsNullOrEmpty(programParameters.SchematicPath)) { haveSimulationError = false; SimulationProcessor.ClearSchematic(); } else { LoadSchematic(programParameters.SchematicPath); } SimulationProcessor.Oversample = programParameters.OverSample; SimulationProcessor.Iterations = programParameters.Iterations; foreach (VSTProgramControlParameter controlParameter in programParameters.ControlParameters) { ComponentWrapper wrapper = SimulationProcessor.InteractiveComponents.Where(i => i.Name == controlParameter.Name).SingleOrDefault(); if (wrapper != null) { if (wrapper.Name == controlParameter.Name) { if (wrapper is PotWrapper) { (wrapper as PotWrapper).PotValue = controlParameter.Value; } else if (wrapper is ButtonWrapper) { (wrapper as ButtonWrapper).Engaged = (controlParameter.Value == 1); } } } } if (EditorView != null) { EditorView.UpdateSchematic(); } } } catch (Exception ex) { Logging.Log("Load program failed: " + ex.Message); } }
public void LoadSchematic(string path) { haveSimulationError = false; try { SimulationProcessor.LoadSchematic(path); } catch (Exception ex) { MessageBox.Show(String.Format("Error loading schematic from: {0}\n\n{1}", path, ex.ToString()), "Schematic Load Error", MessageBoxButton.OK, MessageBoxImage.Error); } }
/// <summary> /// Process a buffer of samples from the VST host /// </summary> /// <param name="input">IntPtr to a double** of input samples</param> /// <param name="output">IntPtr to a double** of output samples</param> /// <param name="inChannelCount">The number of input channels</param> /// <param name="outChannelCount">The number of output channels</param> /// <param name="bufferSize">The buffer size in samples</param> public void ProcessSample(IntPtr input, IntPtr output, uint inChannelCount, uint outChannelCount, uint bufferSize) { if (haveSimulationError) { // If we had an error running the simulation, bypass it uint bytesToCopy = bufferSize * sizeof(double); Buffer.MemoryCopy((void *)((double **)input)[0], (void *)((double **)output)[0], bytesToCopy, bytesToCopy); } else { // Check if our buffer size has changed if (currentBufferSize != bufferSize) { if (currentBufferSize < bufferSize) { currentBufferSize = (int)bufferSize; Array.Resize <double>(ref inputBuffers[0], currentBufferSize); Array.Resize <double>(ref outputBuffers[0], currentBufferSize); } else { currentBufferSize = (int)bufferSize; } } // We are doing mono processing, so just grab the left input and output channel IntPtr leftIn = (IntPtr)((double **)input)[0]; IntPtr leftOut = (IntPtr)((double **)output)[0]; Marshal.Copy(leftIn, inputBuffers[0], 0, currentBufferSize); try { SimulationProcessor.RunSimulation(inputBuffers, outputBuffers, currentBufferSize); } catch (Exception ex) { haveSimulationError = true; new Thread(() => { MessageBox.Show("Error running circuit simulation.\n\n" + ex.Message, "Simulation Error", MessageBoxButton.OK, MessageBoxImage.Error); }).Start(); } Marshal.Copy(outputBuffers[0], 0, leftOut, currentBufferSize); } }
public LiveSPICEPlugin() { DevInfo = new DeviceInfo(); DevInfo.Developer = ""; DevInfo.DeviceID = "LiveSPICEVst"; DevInfo.EditorHeight = 200; DevInfo.EditorWidth = 350; DevInfo.HasEditor = true; DevInfo.Name = "LiveSPICEVst"; DevInfo.ProgramCount = 1; DevInfo.Type = DeviceType.Effect; DevInfo.UnsafeProcessing = true; DevInfo.Version = 1000; DevInfo.VstId = DeviceUtilities.GenerateIntegerId(DevInfo.DeviceID); string codeBase = Assembly.GetExecutingAssembly().CodeBase; UriBuilder uri = new UriBuilder(codeBase); string path = Uri.UnescapeDataString(uri.Path); // Not sure if this helps, but... GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; ParameterInfo = new Parameter[0]; PortInfo = new SharpSoundDevice.Port[2] { new SharpSoundDevice.Port() { Direction = PortDirection.Input, Name = "Mono Input", NumberOfChannels = 1 }, new SharpSoundDevice.Port() { Direction = PortDirection.Output, Name = "Mono Output", NumberOfChannels = 1 } }; // Initialize as arrays of arrays, even though we are only using one channel, since that is what the simulation takes inputBuffers = new double[1][]; inputBuffers[0] = null; outputBuffers = new double[1][]; outputBuffers[0] = null; SimulationProcessor = new SimulationProcessor(); }
public LiveSPICEPlugin() { Company = ""; Website = "livespice.org"; Contact = ""; PluginName = "LiveSPICEVst"; PluginCategory = "Fx"; PluginVersion = "1.1.0"; // Unique 64bit ID for the plugin PluginID = 0xDC8558DC41A44872; HasUserInterface = true; EditorWidth = 350; EditorHeight = 200; //GCSettings.LatencyMode = GCLatencyMode.LowLatency; SimulationProcessor = new SimulationProcessor(); }