Skip to content

Add headless Linux runner for LiveSPICE - #271

Open
jopdorp wants to merge 6 commits into
dsharlet:masterfrom
jopdorp:linux
Open

Add headless Linux runner for LiveSPICE#271
jopdorp wants to merge 6 commits into
dsharlet:masterfrom
jopdorp:linux

Conversation

@jopdorp

@jopdorp jopdorp commented May 5, 2026

Copy link
Copy Markdown

Summary

Adds a headless Linux runner for the LiveSPICE simulation core.

This keeps Circuit as a library, adds LiveSPICE.Headless for CLI execution, and moves shared simulation setup into Circuit/AudioSimulationFactory.cs so the headless and VST paths use the same wiring logic.

Validation

  • built Circuit/Circuit.csproj
  • built LiveSPICE.Headless/LiveSPICE.Headless.csproj
  • ran Tests/Circuits/Passive 1stOrder Highpass RC.schx
  • ran real WAV input through:
    • Tests/Examples/MXR Distortion +.schx
    • Tests/Examples/Marshall JCM800 2203 preamp modded.schx

Notes for reviewers

This branch also includes a merge from upstream/master.

The feature-specific review surface is mainly LiveSPICE.Headless/*, Circuit/AudioSimulationFactory.cs, LiveSPICEVst/SimulationProcessor.cs, Circuit/Circuit.csproj, and README.md.

Copilot AI review requested due to automatic review settings May 5, 2026 22:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a cross-platform, headless console runner for the LiveSPICE simulation core and refactors the audio simulation setup so both the VST and headless paths share the same wiring/solve logic.

Changes:

  • Introduce LiveSPICE.Headless (CLI) with basic WAV I/O and signal generation.
  • Add Circuit/AudioSimulationFactory.cs and update the VST path to reuse the same solve/wiring logic.
  • Update solution + README to include/build/run the headless runner.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
README.md Documents submodule init plus build/run usage for the new headless runner.
LiveSPICEVst/SimulationProcessor.cs Switches VST simulation setup to AudioSimulationFactory and fixes update clocking placement.
LiveSPICE.sln Adds the headless project to the solution (but has inconsistent/mismatched solution metadata).
LiveSPICE.Headless/WaveFile.cs Implements minimal WAV read/write for the CLI runner.
LiveSPICE.Headless/Program.cs Implements the CLI simulation loop, options parsing, and optional WAV in/out.
LiveSPICE.Headless/LiveSPICE.Headless.csproj New net8.0 console project referencing Circuit.
Circuit/Circuit.csproj Adds new NuGet dependencies to the Circuit library.
Circuit/AudioSimulationFactory.cs Centralizes solve + input/output wiring for audio simulations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread LiveSPICE.sln
Comment on lines +95 to +98
{51F8BCEC-5C29-46BA-8448-06B516715840}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51F8BCEC-5C29-46BA-8448-06B516715840}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51F8BCEC-5C29-46BA-8448-06B516715840}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51F8BCEC-5C29-46BA-8448-06B516715840}.Release|Any CPU.Build.0 = Release|Any CPU
Comment thread LiveSPICE.sln
.github\workflows\test.yml = .github\workflows\test.yml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveSPICE.Headless", "LiveSPICE.Headless\LiveSPICE.Headless.csproj", "{FF178A26-25B0-462A-9927-4FD42C710136}"
Comment thread Circuit/Circuit.csproj
Comment on lines +27 to 29
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="5.0.0" />
<PackageReference Include="MathNet.Numerics" Version="4.12.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
Comment on lines +47 to +55
if (chunkId == "fmt ")
{
audioFormat = reader.ReadUInt16();
channels = reader.ReadUInt16();
sampleRate = reader.ReadInt32();
reader.ReadInt32();
reader.ReadUInt16();
bitsPerSample = reader.ReadUInt16();
}
Comment on lines +42 to +47
int count = Math.Min(remaining, input.Length);
FillInput(input, count, generated, options, inputWave);
Array.Clear(output, 0, count);

simulation.Run(count, new[] { input }, new[] { output });

Comment on lines +275 to 291
TransientSolution ts = AudioSimulationFactory.Solve(circuit, sampleRate, oversample);

lock (sync)
{
if (id > clock)
{
if (rebuild)
{
Expression inputExpression = circuit.Components.OfType<Input>().Select(i => i.In).SingleOrDefault();

if (inputExpression == null)
{
simulationUpdateException = new NotSupportedException("Circuit has no inputs.");
}
else
{
IEnumerable<Speaker> speakers = circuit.Components.OfType<Speaker>();

Expression outputExpression = 0;

// Output is voltage drop across the speakers
foreach (Speaker speaker in speakers)
{
outputExpression += speaker.Out;
}

if (outputExpression.EqualsZero())
{
simulationUpdateException = new NotSupportedException("Circuit has no speaker outputs.");
}
else
{
simulation = new Simulation(ts)
{
Oversample = oversample,
Iterations = iterations,
Input = new[] { inputExpression },
Output = new[] { outputExpression }
};
}
}
simulation = AudioSimulationFactory.Create(circuit, ts, oversample, iterations);
}
else
{
simulation.Solution = ts;
clock = id;
}

clock = id;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants